Skip to content

Commit

Permalink
nixd/hover: hover documentation for options (#526)
Browse files Browse the repository at this point in the history
Closes #174

This patch implements hover documentation for options.

---------

Co-authored-by: Yingchi Long <[email protected]>
  • Loading branch information
Grafcube and inclyc authored Jun 22, 2024
1 parent 6811dcf commit dc19271
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 2 deletions.
62 changes: 60 additions & 2 deletions nixd/lib/Controller/Hover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ using namespace lspserver;

namespace {

class OptionsHoverProvider {
AttrSetClient &Client;

public:
OptionsHoverProvider(AttrSetClient &Client) : Client(Client) {}
std::optional<OptionDescription>
resolveHover(const std::vector<std::string> &Scope) {
std::binary_semaphore Ready(0);
std::optional<OptionDescription> Desc;
auto OnReply = [&Ready, &Desc](llvm::Expected<OptionInfoResponse> Resp) {
if (Resp)
Desc = *Resp;
else
elog("options hover: {0}", Resp.takeError());
Ready.release();
};

Client.optionInfo(Scope, std::move(OnReply));
Ready.acquire();

return Desc;
}
};

/// \brief Provide package information, library information ... , from nixpkgs.
class NixpkgsHoverProvider {
AttrSetClient &NixpkgsClient;
Expand All @@ -46,8 +70,7 @@ class NixpkgsHoverProvider {
}

if (Package.Description) {
OS << "## Description"
<< "\n\n";
OS << "## Description" << "\n\n";
OS << *Package.Description;
OS << "\n\n";

Expand Down Expand Up @@ -122,6 +145,41 @@ void Controller::onHover(const TextDocumentPositionParams &Params,
return;
}
}

std::vector<std::string> 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<OptionDescription> Desc = OHP.resolveHover(Scope);
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\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{
Expand Down
84 changes: 84 additions & 0 deletions nixd/tools/nixd/test/hover-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# RUN: nixd --lit-test \
# RUN: --nixos-options-expr="{ foo.bar = { _type = \"option\"; description = \"test\"; type.description = \"hello type\"; }; }" \
# 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": " (hello type)\n\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
{"jsonrpc":"2.0","method":"exit"}
```

0 comments on commit dc19271

Please sign in to comment.