feat(code-action): add flatten nested attribute set refactor action#757
Merged
Conversation
- Introduce addFlattenAttrsAction to provide a code action that flattens nested attribute sets into dot-notation assignments - Integrate flatten action into code action controller for eligible nodes - Ensure flattening only applies to static, non-recursive attribute sets
- Add tests for flattening simple, deep, and multi-level attrsets - Add negative tests for dynamic, empty, inherit, and rec attrsets - Verify correct code action offering and ordering in each scenario
3 tasks
inclyc
reviewed
Jan 4, 2026
inclyc
left a comment
Member
There was a problem hiding this comment.
The implementation LGTM; I’ve left some comments regarding the LLVM FileCheck directives.
In general, we should try to avoid testing redundant content or logic from other PRs within the .md regression tests (though this is sometimes unavoidable). You can use CHECK: patterns to skip over certain sections instead of using CHECK-NEXT:, and you can use CHECK-NOT: to verify the absence of specific structures.
Verify the absence of flatten action using CHECK-NOT directive instead of testing quote action from another PR.
Verify the absence of flatten action using CHECK-NOT directive instead of testing quote action from another PR.
Verify the absence of flatten action using CHECK-NOT directive instead of testing quote action from another PR.
- Remove quote action tests (belongs to different PR) - Use CHECK: instead of CHECK-NEXT: to skip intermediate sections - Focus only on testing flatten action functionality
Collaborator
Author
|
@inclyc |
inclyc
approved these changes
Jan 4, 2026
takeokunn
added a commit
that referenced
this pull request
Jan 5, 2026
Split pack-attrs-siblings-positive.md into two separate test files to fix the CI failure in the nix-build-develop-gcc (undefined, release, false) configuration. The original test contained 2 sequential code action requests followed by an exit notification. Under UBSan, the sanitizer overhead caused a race condition where the second response wasn't fully flushed to stdout before process termination. Following the pattern from PR #757, each test file now contains only ONE code action request, eliminating the race condition. New test files: - pack-attrs-sibling-inherit.md: Tests pack action with inherit sibling - pack-attrs-sibling-different-prefix.md: Tests pack with different prefix
takeokunn
added a commit
that referenced
this pull request
Jan 5, 2026
…#758) ## Summary Add a new code action that converts dotted attribute paths to nested attribute sets - the inverse of the "Flatten nested attribute set" action from #757. **Single Pack:** ```nix { foo.bar = 1; } → { foo = { bar = 1; }; } ``` **Bulk Pack** (multiple sibling bindings with same prefix): ```nix { foo.bar = 1; foo.baz = 2; } → { foo = { bar = 1; baz = 2; }; } ``` ## Changes | File | Description | |------|-------------| | nixd/lib/Controller/CodeAction.cpp | Add packAttrs function implementing the pack transformation with single and bulk modes | | **Single Pack Tests** | | | pack-attrs.md | Basic test for dotted path packing | | pack-attrs-deep.md | Test for multi-level dotted paths (packs one level at a time) | | pack-attrs-quoted.md | Test for preserving quoted attribute names | | pack-attrs-multiline.md | Test for multiline attribute set formatting | | pack-attrs-values.md | Test for various value types (empty sets, let expressions, nested sets) | | **Bulk Pack Tests** | | | pack-attrs-bulk.md | Test for bulk pack with sibling bindings | | pack-attrs-bulk-quoted.md | Test for bulk pack with quoted keys requiring proper quoting | | pack-attrs-escape.md | Test for escaping special characters (", \\, $) in quoted keys | | pack-attrs-sibling-inherit.md | Test for pack with inherit sibling (non-conflicting) | | pack-attrs-sibling-different-prefix.md | Test for pack with different prefix siblings | | **Negative Tests** | | | pack-attrs-single.md | Negative test for single-segment paths | | pack-attrs-rec.md | Negative test for recursive attribute sets | | pack-attrs-dynamic.md | Negative test for dynamic interpolation in paths | | pack-attrs-conflict.md | Negative test for non-path binding conflicts (e.g., `{ foo = 1; foo.bar = 2; }`) | | pack-attrs-sibling-dynamic.md | Negative test for dynamic attributes in sibling bindings | | flatten-attrs-deep.md | Updated to verify both Pack and Flatten actions offered together | ## Behavior ### Single Pack Action ("Pack dotted path to nested set") Action is offered when: - Cursor is on a dotted attribute path with 2+ segments (e.g., `foo.bar`) - The attribute is inside a non-recursive attribute set - No sibling bindings share the same first segment prefix ### Bulk Pack Action ("Pack all 'X' bindings to nested set") Action is offered when: - Multiple sibling bindings share the same first segment prefix (e.g., `foo.bar` and `foo.baz`) - All sibling binding paths are static (no dynamic interpolation) - No conflicting non-path binding exists for the prefix Transformation combines all matching siblings: ```nix { foo.bar = 1; foo.baz = 2; foo.qux = 3; } → { foo = { bar = 1; baz = 2; qux = 3; }; } ``` ### Explicitly Excluded - **Single-segment paths** (e.g., `foo = 1`): Nothing to pack - **Recursive attribute sets** (`rec { ... }`): Packing would change semantics - **Dynamic attribute paths** (e.g., `foo.${bar}`): Cannot safely transform interpolated paths - **Conflicting non-path bindings** (e.g., `{ foo = 1; foo.bar = 2; }`): Would create invalid Nix code - **Dynamic sibling attributes**: When any sibling has dynamic interpolation, bulk pack is disabled ### Deep Path Handling Deep paths are packed one level at a time: - `a.b.c = 1` → `a = { b.c = 1; }` (first application) - `a = { b.c = 1; }` → `a = { b = { c = 1; }; }` (second application) ### Key Quoting and Escaping The action correctly handles: - **Quoted keys**: Keys requiring quotes (e.g., `"1foo"`) are properly quoted in output - **Special character escaping**: Characters like `"`, `\`, and `$` are correctly escaped ## Test Plan - ✅ **All CI checks passing** - **16 test files** covering positive and negative cases - **Positive tests** verify correct transformation output for: - Basic single pack - Deep paths (multi-level) - Quoted attribute names - Multiline formatting - Various value types (empty sets, let expressions, nested sets) - Bulk pack with multiple siblings - Bulk pack with special characters in keys - Non-conflicting sibling scenarios (inherit, different prefixes) - **Negative tests** verify action is NOT offered in excluded scenarios: - Single-segment paths - Recursive attribute sets - Dynamic interpolation - Conflicting non-path bindings - Dynamic sibling attributes <img width="876" height="404" alt="CleanShot 2026-01-05 at 22 59 36@2x" src="https://github.com/user-attachments/assets/b32ba748-9ff6-4d40-95d1-8a51e7e82bd3" /> <img width="984" height="412" alt="CleanShot 2026-01-06 at 03 05 10@2x" src="https://github.com/user-attachments/assets/bb69bdc7-9d1f-40b1-8b21-a3ad125c91f2" /> ## Related - Part of #466 - Inverse of #757 (flatten nested attribute set) - Draft PR: #755 (this implements Split 3)
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
Adds a new "Flatten nested attribute set" code action that transforms nested attribute sets into dot notation:
This follows the existing pattern established in #756 for code actions.
Changes
Behavior
Flatten action offered when:
Explicitly excluded:
Test Plan
Related