From b3d257d8b3913d8c84db40975611df1574a59dcd Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:01:57 +0530 Subject: [PATCH 1/9] nixd/hover: Implement hover documentation for options --- nixd/lib/Controller/Hover.cpp | 64 ++++++++++++++++++++- nixd/tools/nixd/test/hover-options.md | 83 +++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 nixd/tools/nixd/test/hover-options.md diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index 597240483..8de022c9d 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -22,6 +22,31 @@ using namespace lspserver; namespace { +class OptionsHoverProvider { + AttrSetClient &Client; + +public: + OptionsHoverProvider(AttrSetClient &Client) : Client(Client) {} + std::optional resolveHover(std::vector Scope, + std::string Name) { + std::binary_semaphore Ready(0); + std::optional Desc; + auto OnReply = [&Ready, &Desc](llvm::Expected Resp) { + if (Resp) + Desc = *Resp; + else + elog("options hover: {0}", Resp.takeError()); + Ready.release(); + }; + + Client.optionInfo(Scope, std::move(OnReply)); + Scope.emplace_back(std::move(Name)); + Ready.acquire(); + + return Desc; + } +}; + /// \brief Provide package information, library information ... , from nixpkgs. class NixpkgsHoverProvider { AttrSetClient &NixpkgsClient; @@ -46,8 +71,7 @@ class NixpkgsHoverProvider { } if (Package.Description) { - OS << "## Description" - << "\n\n"; + OS << "## Description" << "\n\n"; OS << *Package.Description; OS << "\n\n"; @@ -122,6 +146,42 @@ void Controller::onHover(const TextDocumentPositionParams &Params, return; } } + + std::vector Scope; + auto R = findAttrPath(*N, PM, Scope); + if (R == FindAttrPathResult::OK) { + std::lock_guard _(OptionsLock); + for (const auto &[_, Client] : Options) { + if (AttrSetClient *C = Client->client()) { + OptionsHoverProvider OHP(*C); + std::optional Desc = + OHP.resolveHover(Scope, Name); + std::string Docs = ""; + if (Desc) { + if (Desc->Type) { + std::string TypeName = Desc->Type->Name.value_or(""); + std::string TypeDesc = Desc->Type->Description.value_or(""); + Docs += llvm::formatv("{0} ({1})", TypeName, TypeDesc); + } else { + Docs += "? (missing type)"; + } + if (Desc->Description) { + Docs += "\n" + Desc->Description.value_or(""); + } + Reply(Hover{ + .contents = + MarkupContent{ + .kind = MarkupKind::Markdown, + .value = std::move(Docs), + }, + .range = toLSPRange(N->range()), + }); + return; + } + } + } + } + // Reply it's kind by static analysis // FIXME: support more. Reply(Hover{ diff --git a/nixd/tools/nixd/test/hover-options.md b/nixd/tools/nixd/test/hover-options.md new file mode 100644 index 000000000..e7abc08d2 --- /dev/null +++ b/nixd/tools/nixd/test/hover-options.md @@ -0,0 +1,83 @@ +# RUN: nixd --lit-test \ +# RUN: --nixos-options-expr="{ foo.bar = { _type = \"option\"; }; }" \ +# RUN: < %s | FileCheck %s + + +<-- initialize(0) + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"initialize", + "params":{ + "processId":123, + "rootPath":"", + "capabilities":{ + }, + "trace":"off" + } +} +``` + + +<-- textDocument/didOpen + +```json +{ + "jsonrpc":"2.0", + "method":"textDocument/didOpen", + "params":{ + "textDocument":{ + "uri":"file:///basic.nix", + "languageId":"nix", + "version":1, + "text":"{ foo.bar = 1 }" + } + } +} +``` + +<-- textDocument/hover(2) + + +```json +{ + "jsonrpc":"2.0", + "id":2, + "method":"textDocument/hover", + "params":{ + "textDocument":{ + "uri":"file:///basic.nix" + }, + "position":{ + "line":0, + "character":6 + } + } +} +``` + +``` + CHECK: "id": 2, +CHECK-NEXT: "jsonrpc": "2.0", +CHECK-NEXT: "result": { +CHECK-NEXT: "contents": { +CHECK-NEXT: "kind": "markdown", +CHECK-NEXT: "value": "`Identifer`" +CHECK-NEXT: }, +CHECK-NEXT: "range": { +CHECK-NEXT: "end": { +CHECK-NEXT: "character": 9, +CHECK-NEXT: "line": 0 +CHECK-NEXT: }, +CHECK-NEXT: "start": { +CHECK-NEXT: "character": 6, +CHECK-NEXT: "line": 0 +CHECK-NEXT: } +CHECK-NEXT: } +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +``` From 58bdf2a0a50cbe4dcdee2293541ddde102a898bd Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:42:23 +0530 Subject: [PATCH 2/9] Pass vector in const reference Co-authored-by: Yingchi Long --- nixd/lib/Controller/Hover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index 8de022c9d..c89bac970 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -27,7 +27,7 @@ class OptionsHoverProvider { public: OptionsHoverProvider(AttrSetClient &Client) : Client(Client) {} - std::optional resolveHover(std::vector Scope, + std::optional resolveHover(const std::vector &Scope, std::string Name) { std::binary_semaphore Ready(0); std::optional Desc; From 8af52fdecf5e1bb7f41545877e6b0de889cb9206 Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:44:03 +0530 Subject: [PATCH 3/9] Revert accidental autoformatting --- nixd/lib/Controller/Hover.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index c89bac970..cc789f748 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -71,7 +71,8 @@ class NixpkgsHoverProvider { } if (Package.Description) { - OS << "## Description" << "\n\n"; + OS << "## Description" + << "\n\n"; OS << *Package.Description; OS << "\n\n"; From 2d9044ae83f30fa4af4e1d7c69589eb320cac01c Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:48:03 +0530 Subject: [PATCH 4/9] Remove unnecessary name parameter --- nixd/lib/Controller/Hover.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index cc789f748..4bc158274 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -27,8 +27,8 @@ class OptionsHoverProvider { public: OptionsHoverProvider(AttrSetClient &Client) : Client(Client) {} - std::optional resolveHover(const std::vector &Scope, - std::string Name) { + std::optional + resolveHover(const std::vector &Scope) { std::binary_semaphore Ready(0); std::optional Desc; auto OnReply = [&Ready, &Desc](llvm::Expected Resp) { @@ -40,7 +40,6 @@ class OptionsHoverProvider { }; Client.optionInfo(Scope, std::move(OnReply)); - Scope.emplace_back(std::move(Name)); Ready.acquire(); return Desc; From 4d5635863ed21302bd3a484055097d68f246dd57 Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:48:18 +0530 Subject: [PATCH 5/9] Remove unnecessary initialization --- nixd/lib/Controller/Hover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index 4bc158274..b03a30293 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -156,7 +156,7 @@ void Controller::onHover(const TextDocumentPositionParams &Params, OptionsHoverProvider OHP(*C); std::optional Desc = OHP.resolveHover(Scope, Name); - std::string Docs = ""; + std::string Docs; if (Desc) { if (Desc->Type) { std::string TypeName = Desc->Type->Name.value_or(""); From cc7148fad6244af748775270c4d5919308f0e733 Mon Sep 17 00:00:00 2001 From: Grafcube Date: Wed, 19 Jun 2024 21:50:54 +0530 Subject: [PATCH 6/9] Fix function call --- nixd/lib/Controller/Hover.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index b03a30293..725acd438 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -70,8 +70,7 @@ class NixpkgsHoverProvider { } if (Package.Description) { - OS << "## Description" - << "\n\n"; + OS << "## Description" << "\n\n"; OS << *Package.Description; OS << "\n\n"; @@ -154,8 +153,7 @@ void Controller::onHover(const TextDocumentPositionParams &Params, for (const auto &[_, Client] : Options) { if (AttrSetClient *C = Client->client()) { OptionsHoverProvider OHP(*C); - std::optional Desc = - OHP.resolveHover(Scope, Name); + std::optional Desc = OHP.resolveHover(Scope); std::string Docs; if (Desc) { if (Desc->Type) { From a9a3087212b11ee9cfdaf115da0bbfd5feb466f8 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Sat, 22 Jun 2024 10:59:15 +0800 Subject: [PATCH 7/9] fixup test --- nixd/tools/nixd/test/hover-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixd/tools/nixd/test/hover-options.md b/nixd/tools/nixd/test/hover-options.md index e7abc08d2..626bb2348 100644 --- a/nixd/tools/nixd/test/hover-options.md +++ b/nixd/tools/nixd/test/hover-options.md @@ -64,7 +64,7 @@ CHECK-NEXT: "jsonrpc": "2.0", CHECK-NEXT: "result": { CHECK-NEXT: "contents": { CHECK-NEXT: "kind": "markdown", -CHECK-NEXT: "value": "`Identifer`" +CHECK-NEXT: "value": "? (missing type)" CHECK-NEXT: }, CHECK-NEXT: "range": { CHECK-NEXT: "end": { From f47d13bc20e8e6a73dd322ffc8d7367edd3bf6b6 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Sat, 22 Jun 2024 11:06:03 +0800 Subject: [PATCH 8/9] add option type --- nixd/tools/nixd/test/hover-options.md | 37 ++++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/nixd/tools/nixd/test/hover-options.md b/nixd/tools/nixd/test/hover-options.md index 626bb2348..35583a333 100644 --- a/nixd/tools/nixd/test/hover-options.md +++ b/nixd/tools/nixd/test/hover-options.md @@ -1,5 +1,5 @@ # RUN: nixd --lit-test \ -# RUN: --nixos-options-expr="{ foo.bar = { _type = \"option\"; }; }" \ +# RUN: --nixos-options-expr="{ foo.bar = { _type = \"option\"; description = \"test\"; type.description = \"hello type\"; }; }" \ # RUN: < %s | FileCheck %s @@ -59,23 +59,24 @@ ``` ``` - CHECK: "id": 2, -CHECK-NEXT: "jsonrpc": "2.0", -CHECK-NEXT: "result": { -CHECK-NEXT: "contents": { -CHECK-NEXT: "kind": "markdown", -CHECK-NEXT: "value": "? (missing type)" -CHECK-NEXT: }, -CHECK-NEXT: "range": { -CHECK-NEXT: "end": { -CHECK-NEXT: "character": 9, -CHECK-NEXT: "line": 0 -CHECK-NEXT: }, -CHECK-NEXT: "start": { -CHECK-NEXT: "character": 6, -CHECK-NEXT: "line": 0 -CHECK-NEXT: } -CHECK-NEXT: } + CHECK: "id": 2, +CHECK-NEXT: "jsonrpc": "2.0", +CHECK-NEXT: "result": { +CHECK-NEXT: "contents": { +CHECK-NEXT: "kind": "markdown", +CHECK-NEXT: "value": " (hello type)\ntest" +CHECK-NEXT: }, +CHECK-NEXT: "range": { +CHECK-NEXT: "end": { +CHECK-NEXT: "character": 9, +CHECK-NEXT: "line": 0 +CHECK-NEXT: }, +CHECK-NEXT: "start": { +CHECK-NEXT: "character": 6, +CHECK-NEXT: "line": 0 +CHECK-NEXT: } +CHECK-NEXT: } +CHECK-NEXT: } ``` ```json From 2f8afdbe937d78358bb93000ecae946aa258e270 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Sat, 22 Jun 2024 11:10:54 +0800 Subject: [PATCH 9/9] use two `\n`s to make sure a new line is created in markdown --- nixd/lib/Controller/Hover.cpp | 2 +- nixd/tools/nixd/test/hover-options.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nixd/lib/Controller/Hover.cpp b/nixd/lib/Controller/Hover.cpp index 725acd438..64f5656fa 100644 --- a/nixd/lib/Controller/Hover.cpp +++ b/nixd/lib/Controller/Hover.cpp @@ -164,7 +164,7 @@ void Controller::onHover(const TextDocumentPositionParams &Params, Docs += "? (missing type)"; } if (Desc->Description) { - Docs += "\n" + Desc->Description.value_or(""); + Docs += "\n\n" + Desc->Description.value_or(""); } Reply(Hover{ .contents = diff --git a/nixd/tools/nixd/test/hover-options.md b/nixd/tools/nixd/test/hover-options.md index 35583a333..87e99ec00 100644 --- a/nixd/tools/nixd/test/hover-options.md +++ b/nixd/tools/nixd/test/hover-options.md @@ -64,7 +64,7 @@ CHECK-NEXT: "jsonrpc": "2.0", CHECK-NEXT: "result": { CHECK-NEXT: "contents": { CHECK-NEXT: "kind": "markdown", -CHECK-NEXT: "value": " (hello type)\ntest" +CHECK-NEXT: "value": " (hello type)\n\ntest" CHECK-NEXT: }, CHECK-NEXT: "range": { CHECK-NEXT: "end": {