nixd
Loading...
Searching...
No Matches
DocumentHighlight.cpp
Go to the documentation of this file.
1/// \file
2/// \brief This implements [Document Highlight].
3/// [Document Highlight]:
4/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight
5
6#include "Convert.h"
7#include "Definition.h"
8
10
11#include <boost/asio/post.hpp>
12#include <lspserver/Protocol.h>
13#include <nixf/Sema/ParentMap.h>
15
16#include <exception>
17
18using namespace lspserver;
19using namespace nixd;
20using namespace llvm;
21using namespace nixf;
22
23namespace {
24
25std::vector<DocumentHighlight> highlight(const nixf::Node &Desc,
26 const ParentMapAnalysis &PMA,
27 const VariableLookupAnalysis &VLA,
28 const URIForFile &URI,
29 llvm::StringRef Src) {
30 // Find "definition"
31 auto Def = findDefinition(Desc, PMA, VLA);
32
33 std::vector<DocumentHighlight> Highlights;
34 // OK, iterate all uses.
35 for (const auto *Use : Def.uses()) {
36 assert(Use);
37 Highlights.emplace_back(DocumentHighlight{
38 .range = toLSPRange(Src, Use->range()),
39 .kind = DocumentHighlightKind::Read,
40 });
41 }
42 if (Def.syntax()) {
43 const Node &Syntax = *Def.syntax();
44 Highlights.emplace_back(DocumentHighlight{
45 .range = toLSPRange(Src, Syntax.range()),
46 .kind = DocumentHighlightKind::Write,
47 });
48 }
49
50 return Highlights;
51}
52
53} // namespace
54
55void Controller::onDocumentHighlight(
57 Callback<std::vector<DocumentHighlight>> Reply) {
58 auto Action = [Reply = std::move(Reply), URI = Params.textDocument.uri,
59 Pos = toNixfPosition(Params.position), this]() mutable {
60 std::string File(URI.file());
61 if (std::shared_ptr<NixTU> TU = getTU(File, Reply)) [[likely]] {
62 if (std::shared_ptr<nixf::Node> AST = getAST(*TU, Reply)) [[likely]] {
63 const nixf::Node *Desc = AST->descend({Pos, Pos});
64 if (!Desc) {
65 Reply(error("cannot find corresponding node on given position"));
66 return;
67 }
68 try {
69 const auto &PM = *TU->parentMap();
70 const auto &VLA = *TU->variableLookup();
71 return Reply(highlight(*Desc, PM, VLA, URI, TU->src()));
72 } catch (std::exception &E) {
73 elog("textDocument/documentHighlight failed: {0}", E.what());
74 return Reply(std::vector<DocumentHighlight>{});
75 }
76 }
77 }
78 };
79 boost::asio::post(Pool, std::move(Action));
80}
Convert between LSP and nixf types.
Lookup variable names, from it's parent scope.
const Node * descend(PositionRange Range) const
Descendant node that contains the given range.
Definition Basic.h:49
LexerCursorRange range() const
Definition Basic.h:35
ParentMap analysis.
Whether current platform treats paths case insensitively.
Definition Connection.h:11
llvm::unique_function< void(llvm::Expected< T >)> Callback
Definition Function.h:14
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&...Vals)
Definition Logger.h:70
void elog(const char *Fmt, Ts &&...Vals)
Definition Logger.h:52
bool fromJSON(const llvm::json::Value &Params, Configuration::Diagnostic &R, llvm::json::Path P)
nixf::Position toNixfPosition(const lspserver::Position &P)
Definition Convert.cpp:32
const nixf::Definition & findDefinition(const nixf::Node &N, const nixf::ParentMapAnalysis &PMA, const nixf::VariableLookupAnalysis &VLA)
Heuristically find definition on some node.
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
Definition Convert.cpp:40
Range range
The range this highlight applies to.