diff --git a/nixd/lib/Controller/CodeAction.cpp b/nixd/lib/Controller/CodeAction.cpp index 6e737116f..ad6b47d0f 100644 --- a/nixd/lib/Controller/CodeAction.cpp +++ b/nixd/lib/Controller/CodeAction.cpp @@ -51,6 +51,7 @@ void Controller::onCodeAction(const lspserver::CodeActionParams &Params, bool IsPreferred = false; switch (D.kind()) { case nixf::Diagnostic::DK_UnusedDefLet: + case nixf::Diagnostic::DK_ExtraRecursive: IsPreferred = true; break; default: diff --git a/nixd/tools/nixd/test/code-action/extra-rec/basic.md b/nixd/tools/nixd/test/code-action/extra-rec/basic.md new file mode 100644 index 000000000..372840b62 --- /dev/null +++ b/nixd/tools/nixd/test/code-action/extra-rec/basic.md @@ -0,0 +1,78 @@ +# RUN: nixd --lit-test < %s | FileCheck %s + +Test basic `remove extra rec` action for unnecessary recursive attribute set. + +<-- initialize(0) + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"initialize", + "params":{ + "processId":123, + "rootPath":"", + "capabilities":{ + }, + "trace":"off" + } +} +``` + + +<-- textDocument/didOpen + +```nix file:///extra-rec.nix +rec { x = 1; } +``` + +<-- textDocument/codeAction(2) + + +```json +{ + "jsonrpc":"2.0", + "id":2, + "method":"textDocument/codeAction", + "params":{ + "textDocument":{ + "uri":"file:///extra-rec.nix" + }, + "range":{ + "start":{ + "line": 0, + "character": 0 + }, + "end":{ + "line":0, + "character": 3 + } + }, + "context":{ + "diagnostics":[], + "triggerKind":2 + } + } +} +``` + +The action should remove the `rec` keyword since no binding references another. + +``` + CHECK: "id": 2, + CHECK: "newText": "", + CHECK: "range": + CHECK: "end": + CHECK: "character": 3, + CHECK: "line": 0 + CHECK: "start": + CHECK: "character": 0, + CHECK: "line": 0 + CHECK: "isPreferred": true, + CHECK: "kind": "quickfix", + CHECK: "title": "remove `rec` keyword" +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +``` diff --git a/nixd/tools/nixd/test/code-action/extra-rec/empty-rec.md b/nixd/tools/nixd/test/code-action/extra-rec/empty-rec.md new file mode 100644 index 000000000..2c069415e --- /dev/null +++ b/nixd/tools/nixd/test/code-action/extra-rec/empty-rec.md @@ -0,0 +1,78 @@ +# RUN: nixd --lit-test < %s | FileCheck %s + +Test `remove extra rec` action for empty recursive attribute set. + +<-- initialize(0) + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"initialize", + "params":{ + "processId":123, + "rootPath":"", + "capabilities":{ + }, + "trace":"off" + } +} +``` + + +<-- textDocument/didOpen + +```nix file:///empty-rec.nix +rec { } +``` + +<-- textDocument/codeAction(2) + + +```json +{ + "jsonrpc":"2.0", + "id":2, + "method":"textDocument/codeAction", + "params":{ + "textDocument":{ + "uri":"file:///empty-rec.nix" + }, + "range":{ + "start":{ + "line": 0, + "character": 0 + }, + "end":{ + "line":0, + "character": 3 + } + }, + "context":{ + "diagnostics":[], + "triggerKind":2 + } + } +} +``` + +The action should remove the `rec` keyword since the attrset has no bindings at all. + +``` + CHECK: "id": 2, + CHECK: "newText": "", + CHECK: "range": + CHECK: "end": + CHECK: "character": 3, + CHECK: "line": 0 + CHECK: "start": + CHECK: "character": 0, + CHECK: "line": 0 + CHECK: "isPreferred": true, + CHECK: "kind": "quickfix", + CHECK: "title": "remove `rec` keyword" +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +``` diff --git a/nixd/tools/nixd/test/code-action/extra-rec/multiline.md b/nixd/tools/nixd/test/code-action/extra-rec/multiline.md new file mode 100644 index 000000000..9880255cd --- /dev/null +++ b/nixd/tools/nixd/test/code-action/extra-rec/multiline.md @@ -0,0 +1,81 @@ +# RUN: nixd --lit-test < %s | FileCheck %s + +Test `remove extra rec` action with multiline attribute set. + +<-- initialize(0) + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"initialize", + "params":{ + "processId":123, + "rootPath":"", + "capabilities":{ + }, + "trace":"off" + } +} +``` + + +<-- textDocument/didOpen + +```nix file:///extra-rec-multiline.nix +rec { + x = 1; + y = 2; +} +``` + +<-- textDocument/codeAction(2) + + +```json +{ + "jsonrpc":"2.0", + "id":2, + "method":"textDocument/codeAction", + "params":{ + "textDocument":{ + "uri":"file:///extra-rec-multiline.nix" + }, + "range":{ + "start":{ + "line": 0, + "character": 0 + }, + "end":{ + "line":0, + "character": 3 + } + }, + "context":{ + "diagnostics":[], + "triggerKind":2 + } + } +} +``` + +The action should remove the `rec` keyword since neither `x` nor `y` references the other. + +``` + CHECK: "id": 2, + CHECK: "newText": "", + CHECK: "range": + CHECK: "end": + CHECK: "character": 3, + CHECK: "line": 0 + CHECK: "start": + CHECK: "character": 0, + CHECK: "line": 0 + CHECK: "isPreferred": true, + CHECK: "kind": "quickfix", + CHECK: "title": "remove `rec` keyword" +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +``` diff --git a/nixd/tools/nixd/test/code-action/extra-rec/needed-rec.md b/nixd/tools/nixd/test/code-action/extra-rec/needed-rec.md new file mode 100644 index 000000000..8323eeee1 --- /dev/null +++ b/nixd/tools/nixd/test/code-action/extra-rec/needed-rec.md @@ -0,0 +1,69 @@ +# RUN: nixd --lit-test < %s | FileCheck %s + +Test that `remove extra rec` is NOT offered when `rec` is actually needed. + +<-- initialize(0) + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"initialize", + "params":{ + "processId":123, + "rootPath":"", + "capabilities":{ + }, + "trace":"off" + } +} +``` + + +<-- textDocument/didOpen + +```nix file:///needed-rec.nix +rec { x = 1; y = x; } +``` + +<-- textDocument/codeAction(2) + + +```json +{ + "jsonrpc":"2.0", + "id":2, + "method":"textDocument/codeAction", + "params":{ + "textDocument":{ + "uri":"file:///needed-rec.nix" + }, + "range":{ + "start":{ + "line": 0, + "character": 0 + }, + "end":{ + "line":0, + "character": 3 + } + }, + "context":{ + "diagnostics":[], + "triggerKind":2 + } + } +} +``` + +No code action should be offered because `y` depends on `x`, making `rec` necessary. + +``` + CHECK: "id": 2, +CHECK-NEXT: "jsonrpc": "2.0", +CHECK-NEXT: "result": [] +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +```