Skip to content

feat(code-action): add extract expression to file refactoring action#767

Merged
inclyc merged 1 commit into
mainfrom
feature/add-code-action-6
Jan 11, 2026
Merged

feat(code-action): add extract expression to file refactoring action#767
inclyc merged 1 commit into
mainfrom
feature/add-code-action-6

Conversation

@takeokunn

Copy link
Copy Markdown
Collaborator

Summary

This PR adds a new "Extract to File" code action that extracts Nix expressions to separate files, automatically generating appropriate import statements with free variable handling.

Example transformation:

Before:

{ pkgs }: { buildInputs = [ pkgs.foo pkgs.bar ]; }

After extraction:

- New file (buildInputs.nix):
{ pkgs }:
[ pkgs.foo pkgs.bar ]
- Original file:
{ pkgs }: { buildInputs = import ./buildInputs.nix { inherit pkgs; }; }

Changes

File Description
nixd/lib/Controller/CodeActions/ExtractToFile.cpp Core implementation with free variable detection and unique filename generation
nixd/lib/Controller/CodeActions/ExtractToFile.h Public interface declaration
nixd/lib/Controller/CodeAction.cpp Integration with code action dispatcher
nixd/lib/meson.build Build system integration
nixd/lspserver/include/lspserver/Protocol.h LSP resource operations (CreateFile, RenameFile, DeleteFile)
nixd/lspserver/src/Protocol.cpp JSON serialization for resource operations

Behavior

The action is offered when:

  • Cursor is on a non-trivial expression (attribute sets, lists, lambdas, let bindings, if expressions, etc.)
  • Cursor is on an attribute name (extracts the binding's value expression)

Free Variable Detection:

  • Automatically detects variables used but defined outside the expression
  • Wraps extracted code in a lambda with free variables as arguments
  • Generates import ./file.nix { inherit var1 var2; } syntax
  • Warns about with scope variables in action title (these may require manual adjustment)

Filename Generation:

  • Uses binding key name if inside a binding (e.g., buildInputs.nix)
  • Falls back to expression type (e.g., extracted-lambda.nix, extracted-attrs.nix)
  • Automatically generates unique filenames (name-1.nix, name-2.nix) if file exists

Explicitly Excluded

  • Trivial expressions: single variables, literals, paths, select expressions
  • Empty attribute sets {}
  • Empty lists []

Test Plan

  • CI passes
  • 4 regression tests covering:
    • Basic attribute set extraction (extract-attrs.md)
    • List expression extraction (extract-list.md)
    • Free variable detection (extract-with-free-vars.md)
    • with scope variable warning (extract-with-scope-vars.md)

Related

- Implement code action to extract selected Nix expressions to a new file
- Detect free variables and wrap extracted content in a lambda if needed
- Generate import statement with inherit for free variables in source file
- Warn in action title if extracted code uses 'with' scope variables
- Add tests for attribute sets, lists, free variables, and 'with' scope cases
- Update meson build and LSP protocol for resource operations support
@takeokunn takeokunn marked this pull request as ready for review January 10, 2026 15:54
@takeokunn takeokunn requested a review from inclyc as a code owner January 10, 2026 15:54
@takeokunn takeokunn added enhancement New feature or request nixd:controller labels Jan 10, 2026
@inclyc inclyc merged commit d7afe2e into main Jan 11, 2026
19 checks passed
@inclyc inclyc deleted the feature/add-code-action-6 branch January 11, 2026 05:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request nixd:controller

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants