feat(code-action): add quote/unquote refactoring for attribute names#756
Merged
Conversation
- Implement quote/unquote attribute name refactoring code actions - Add isValidNixIdentifier helper to validate unquoted names - Register "refactor.rewrite" kind in code action provider and protocol - Update tests to reflect new code action kinds
- Add tests for quoting and unquoting attribute names in various cases - Cover keywords, let bindings, empty strings, hyphens, invalid chars, digits, keywords, quote chars, and underscores - Update initialize.md and semantic-tokens/initialize.md to reference new code action tests
- Add "refactor.rewrite" to codeActionKinds in initialize.md tests - Ensure semantic-tokens/initialize.md reflects new supported code action kind
inclyc
approved these changes
Jan 4, 2026
| if (!AttrNameNode) | ||
| return; | ||
|
|
||
| // Only offer quote/unquote for attribute sets, not for let bindings. |
Member
There was a problem hiding this comment.
It is OK to offer quote/unquote for let-bindings?
Collaborator
Author
- Prevent quote/unquote code actions from being offered on let bindings - Add tests to verify quote/unquote are not available for let bindings - Add tests to ensure quote/unquote still work for attribute sets
…d or keyword let bindings - Add test for let bindings with invalid identifiers (e.g., starting with digit) - Add test for let bindings using keywords (e.g., "true") - Verify code action result is empty in both cases
This was referenced Jan 4, 2026
takeokunn
added a commit
that referenced
this pull request
Jan 4, 2026
…757) ## Summary Adds a new "Flatten nested attribute set" code action that transforms nested attribute sets into dot notation: ```nix # Before { foo = { bar = 1; }; } # After { foo.bar = 1; } ``` This follows the existing pattern established in #756 for code actions. ## Changes | File | Description | |-----------------------------------------------------------|------------------------------------------------------------------------------------------| | nixd/lib/Controller/CodeAction.cpp | Add getFlattenableBinds() helper and addFlattenAttrsAction() for the flatten refactoring | | nixd/tools/nixd/test/code-action/flatten-attrs.md | Basic test for simple nested attribute flattening | | nixd/tools/nixd/test/code-action/flatten-attrs-multi.md | Test for nested sets with multiple bindings | | nixd/tools/nixd/test/code-action/flatten-attrs-deep.md | Test for deeply nested attribute paths | | nixd/tools/nixd/test/code-action/flatten-attrs-rec.md | Test that rec sets are excluded | | nixd/tools/nixd/test/code-action/flatten-attrs-inherit.md | Test that sets with inherit are excluded | | nixd/tools/nixd/test/code-action/flatten-attrs-dynamic.md | Test that dynamic ${} names are excluded | | nixd/tools/nixd/test/code-action/flatten-attrs-empty.md | Test that empty nested sets are excluded | ## Behavior Flatten action offered when: - Cursor is on a binding whose value is an attribute set - All attribute names (outer and inner) are static identifiers - The nested set contains at least one binding ## Explicitly excluded: - Recursive attribute sets (rec { ... }): Flattening would change semantics - Inherited bindings (inherit x;): Cannot be represented in dot notation - Dynamic attribute names (${expr}): Cannot be statically flattened - Empty nested sets ({ foo = {}; }): No meaningful transformation ## Test Plan - Added 7 lit tests covering positive and negative cases - Tests verify the action is offered only when appropriate - Tests verify correct transformation output for various input shapes - All existing tests pass <img width="954" height="424" alt="CleanShot 2026-01-04 at 20 12 35@2x" src="https://github.com/user-attachments/assets/e0ccbeb2-705a-44dd-8e76-0eaa06f65b48" /> <img width="846" height="412" alt="CleanShot 2026-01-04 at 20 14 09@2x" src="https://github.com/user-attachments/assets/0ce5109c-e640-4c46-b642-3225ae574561" /> ## Related - Issue: #466 - Draft PR: #755 (this implements Split 2)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add refactoring code actions to quote/unquote attribute names in attribute sets.
{ foo = 1; }→ Offer "Quote attribute name" →{ "foo" = 1; }{ "bar" = 1; }→ Offer "Unquote attribute name" →{ bar = 1; }This is part of the code actions initiative (#466, #755).
Changes
nixd/lib/Controller/CodeAction.cppnixd/lib/Controller/LifeTime.cpprefactor.rewritecapabilitynixd/lspserver/include/lspserver/Protocol.hREFACTOR_REWRITE_KINDconstantnixd/lspserver/src/Protocol.cppREFACTOR_REWRITE_KINDnixd/tools/nixd/test/code-action/*.mdnixd/tools/nixd/test/initialize.mdBehavior
Quote action offered when:
foo)Unquote action offered when:
"foo")Explicitly excluded:
let foo = 1; in foo) - no actions offered"123","foo.bar") - no unquote action"true","if") - no unquote actionTest Plan
Related