Skip to content

Commit

Permalink
nixd/Controller: handle UTF-16 code units for locations
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Aug 11, 2024
1 parent 2f515e0 commit cc9e61d
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 96 deletions.
6 changes: 4 additions & 2 deletions nixd/lib/Controller/CodeAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ void Controller::onCodeAction(const lspserver::CodeActionParams &Params,
std::string File(Params.textDocument.uri.file());
Range Range = Params.range;
auto Action = [Reply = std::move(Reply), File, Range, this]() mutable {
auto Draft = Store.getDraft(File)->Contents;
auto Src = llvm::StringRef(*Draft);
if (auto TU = getTU(File, Reply)) {
std::vector<nixf::Diagnostic> Diagnostics = TU->diagnostics();
std::vector<CodeAction> Actions;
Actions.reserve(Diagnostics.size());
for (const nixf::Diagnostic &D : Diagnostics) {
auto DRange = toLSPRange(D.range());
auto DRange = toLSPRange(Src, D.range());
if (!Range.overlap(DRange))
continue;

Expand All @@ -34,7 +36,7 @@ void Controller::onCodeAction(const lspserver::CodeActionParams &Params,
Edits.reserve(F.edits().size());
for (const nixf::TextEdit &TE : F.edits()) {
Edits.emplace_back(TextEdit{
.range = toLSPRange(TE.oldRange()),
.range = toLSPRange(Src, TE.oldRange()),
.newText = std::string(TE.newText()),
});
}
Expand Down
29 changes: 16 additions & 13 deletions nixd/lib/Controller/Convert.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "Convert.h"

#include "nixf/Basic/Diagnostic.h"

using namespace lspserver;
#include "lspserver/SourceCode.h"

namespace nixd {
#include <llvm/ADT/StringRef.h>

int getLSPSeverity(nixf::Diagnostic::DiagnosticKind Kind) {
using namespace lspserver;

int nixd::getLSPSeverity(nixf::Diagnostic::DiagnosticKind Kind) {
switch (nixf::Diagnostic::severity(Kind)) {
case nixf::Diagnostic::DS_Fatal:
case nixf::Diagnostic::DS_Error:
Expand All @@ -21,25 +24,27 @@ int getLSPSeverity(nixf::Diagnostic::DiagnosticKind Kind) {
__builtin_unreachable();
}

lspserver::Position toLSPPosition(const nixf::LexerCursor &P) {
return lspserver::Position{static_cast<int>(P.line()),
static_cast<int>(P.column())};
lspserver::Position nixd::toLSPPosition(llvm::StringRef Code,
const nixf::LexerCursor &P) {
return lspserver::offsetToPosition(Code, P.offset());
}

nixf::Position toNixfPosition(const lspserver::Position &P) {
nixf::Position nixd::toNixfPosition(const lspserver::Position &P) {
return {P.line, P.character};
}

nixf::PositionRange toNixfRange(const lspserver::Range &P) {
nixf::PositionRange nixd::toNixfRange(const lspserver::Range &P) {
return {toNixfPosition(P.start), toNixfPosition(P.end)};
}

lspserver::Range toLSPRange(const nixf::LexerCursorRange &R) {
return lspserver::Range{toLSPPosition(R.lCur()), toLSPPosition(R.rCur())};
lspserver::Range nixd::toLSPRange(llvm::StringRef Code,
const nixf::LexerCursorRange &R) {
return lspserver::Range{toLSPPosition(Code, R.lCur()),
toLSPPosition(Code, R.rCur())};
}

llvm::SmallVector<lspserver::DiagnosticTag, 1>
toLSPTags(const std::vector<nixf::DiagnosticTag> &Tags) {
nixd::toLSPTags(const std::vector<nixf::DiagnosticTag> &Tags) {
llvm::SmallVector<lspserver::DiagnosticTag, 1> Result;
Result.reserve(Tags.size());
for (const nixf::DiagnosticTag &Tag : Tags) {
Expand All @@ -54,5 +59,3 @@ toLSPTags(const std::vector<nixf::DiagnosticTag> &Tags) {
}
return Result;
}

} // namespace nixd
6 changes: 4 additions & 2 deletions nixd/lib/Controller/Convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@

namespace nixd {

lspserver::Position toLSPPosition(const nixf::LexerCursor &P);
lspserver::Position toLSPPosition(llvm::StringRef Code,
const nixf::LexerCursor &P);

nixf::Position toNixfPosition(const lspserver::Position &P);

nixf::PositionRange toNixfRange(const lspserver::Range &P);

lspserver::Range toLSPRange(const nixf::LexerCursorRange &R);
lspserver::Range toLSPRange(llvm::StringRef Code,
const nixf::LexerCursorRange &R);

int getLSPSeverity(nixf::Diagnostic::DiagnosticKind Kind);

Expand Down
19 changes: 11 additions & 8 deletions nixd/lib/Controller/Definition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ const Definition &findVarDefinition(const ExprVar &Var,
}

/// \brief Convert nixf::Definition to lspserver::Location
Location convertToLocation(const Definition &Def, URIForFile URI) {
Location convertToLocation(llvm::StringRef Src, const Definition &Def,
URIForFile URI) {
return Location{
.uri = std::move(URI),
.range = toLSPRange(Def.syntax()->range()),
.range = toLSPRange(Src, Def.syntax()->range()),
};
}

Expand Down Expand Up @@ -280,9 +281,9 @@ Locations defineSelect(const ExprSelect &Sel, const VariableLookupAnalysis &VLA,
}

Locations defineVarStatic(const ExprVar &Var, const VariableLookupAnalysis &VLA,
const URIForFile &URI) {
const URIForFile &URI, llvm::StringRef Src) {
const Definition &Def = findVarDefinition(Var, VLA);
return {convertToLocation(Def, URI)};
return {convertToLocation(Src, Def, URI)};
}

template <class T>
Expand All @@ -293,9 +294,9 @@ std::vector<T> mergeVec(std::vector<T> A, const std::vector<T> &B) {

Locations defineVar(const ExprVar &Var, const VariableLookupAnalysis &VLA,
const ParentMapAnalysis &PM, AttrSetClient &NixpkgsClient,
const URIForFile &URI) {
const URIForFile &URI, llvm::StringRef Src) {
try {
Locations StaticLocs = defineVarStatic(Var, VLA, URI);
Locations StaticLocs = defineVarStatic(Var, VLA, URI, Src);

// Nixpkgs locations.
try {
Expand Down Expand Up @@ -353,6 +354,8 @@ void Controller::onDefinition(const TextDocumentPositionParams &Params,
auto Action = [Reply = std::move(Reply), URI = Params.textDocument.uri,
Pos = toNixfPosition(Params.position), this]() mutable {
std::string File(URI.file());
auto Draft = Store.getDraft(File)->Contents;
auto Src = llvm::StringRef(*Draft);
if (std::shared_ptr<NixTU> TU = getTU(File, Reply)) [[likely]] {
if (std::shared_ptr<Node> AST = getAST(*TU, Reply)) [[likely]] {
const VariableLookupAnalysis &VLA = *TU->variableLookup();
Expand All @@ -374,12 +377,12 @@ void Controller::onDefinition(const TextDocumentPositionParams &Params,
return Reply(squash([&]() -> llvm::Expected<Locations> {
// Special case for inherited names.
if (const ExprVar *Var = findInheritVar(N, PM, VLA))
return defineVar(*Var, VLA, PM, *nixpkgsClient(), URI);
return defineVar(*Var, VLA, PM, *nixpkgsClient(), URI, Src);

switch (UpExpr.kind()) {
case Node::NK_ExprVar: {
const auto &Var = static_cast<const ExprVar &>(UpExpr);
return defineVar(Var, VLA, PM, *nixpkgsClient(), URI);
return defineVar(Var, VLA, PM, *nixpkgsClient(), URI, Src);
}
case Node::NK_ExprSelect: {
const auto &Sel = static_cast<const ExprSelect &>(UpExpr);
Expand Down
8 changes: 5 additions & 3 deletions nixd/lib/Controller/Diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ void Controller::publishDiagnostics(
const std::vector<nixf::Diagnostic> &Diagnostics) {
std::vector<Diagnostic> LSPDiags;
LSPDiags.reserve(Diagnostics.size());
auto Draft = Store.getDraft(File)->Contents;
auto Src = llvm::StringRef(*Draft);
for (const nixf::Diagnostic &D : Diagnostics) {
// Before actually doing anything,
// let's check if the diagnostic is suppressed.
Expand All @@ -67,7 +69,7 @@ void Controller::publishDiagnostics(
}

Diagnostic &Diag = LSPDiags.emplace_back(Diagnostic{
.range = toLSPRange(D.range()),
.range = toLSPRange(Src, D.range()),
.severity = getLSPSeverity(D.kind()),
.code = D.sname(),
.source = "nixf",
Expand All @@ -83,7 +85,7 @@ void Controller::publishDiagnostics(
.location =
Location{
.uri = URIForFile::canonicalize(File, File),
.range = toLSPRange(N.range()),
.range = toLSPRange(Src, N.range()),
},
.message = N.format(),
});
Expand All @@ -93,7 +95,7 @@ void Controller::publishDiagnostics(

for (const nixf::Note &N : Notes) {
LSPDiags.emplace_back(Diagnostic{
.range = toLSPRange(N.range()),
.range = toLSPRange(Src, N.range()),
.severity = 4,
.code = N.sname(),
.source = "nixf",
Expand Down
11 changes: 7 additions & 4 deletions nixd/lib/Controller/DocumentHighlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace {
std::vector<DocumentHighlight> highlight(const nixf::Node &Desc,
const ParentMapAnalysis &PMA,
const VariableLookupAnalysis &VLA,
const URIForFile &URI) {
const URIForFile &URI,
llvm::StringRef Src) {
// Find "definition"
auto Def = findDefinition(Desc, PMA, VLA);

Expand All @@ -34,14 +35,14 @@ std::vector<DocumentHighlight> highlight(const nixf::Node &Desc,
for (const auto *Use : Def.uses()) {
assert(Use);
Highlights.emplace_back(DocumentHighlight{
.range = toLSPRange(Use->range()),
.range = toLSPRange(Src, Use->range()),
.kind = DocumentHighlightKind::Read,
});
}
if (Def.syntax()) {
const Node &Syntax = *Def.syntax();
Highlights.emplace_back(DocumentHighlight{
.range = toLSPRange(Syntax.range()),
.range = toLSPRange(Src, Syntax.range()),
.kind = DocumentHighlightKind::Write,
});
}
Expand All @@ -57,6 +58,8 @@ void Controller::onDocumentHighlight(
auto Action = [Reply = std::move(Reply), URI = Params.textDocument.uri,
Pos = toNixfPosition(Params.position), this]() mutable {
std::string File(URI.file());
auto Draft = Store.getDraft(File)->Contents;
auto Src = llvm::StringRef(*Draft);
if (std::shared_ptr<NixTU> TU = getTU(File, Reply)) [[likely]] {
if (std::shared_ptr<nixf::Node> AST = getAST(*TU, Reply)) [[likely]] {
const nixf::Node *Desc = AST->descend({Pos, Pos});
Expand All @@ -67,7 +70,7 @@ void Controller::onDocumentHighlight(
try {
const auto &PM = *TU->parentMap();
const auto &VLA = *TU->variableLookup();
return Reply(highlight(*Desc, PM, VLA, URI));
return Reply(highlight(*Desc, PM, VLA, URI, Src));
} catch (std::exception &E) {
elog("textDocument/documentHighlight failed: {0}", E.what());
return Reply(std::vector<DocumentHighlight>{});
Expand Down
10 changes: 6 additions & 4 deletions nixd/lib/Controller/DocumentLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ std::optional<std::string> resolveExprPath(const std::string &BasePath,
}

void dfs(const Node *N, const std::string &BasePath,
std::vector<DocumentLink> &Links) {
std::vector<DocumentLink> &Links, llvm::StringRef Src) {
if (!N)
return;

Expand All @@ -59,7 +59,7 @@ void dfs(const Node *N, const std::string &BasePath,
// Provide literal path linking.
if (auto Link = resolveExprPath(BasePath, Path.parts().literal())) {
Links.emplace_back(
DocumentLink{.range = toLSPRange(N->range()),
DocumentLink{.range = toLSPRange(Src, N->range()),
.target = URIForFile::canonicalize(*Link, *Link)});
}
}
Expand All @@ -71,7 +71,7 @@ void dfs(const Node *N, const std::string &BasePath,

// Traverse on all children
for (const Node *Ch : N->children()) {
dfs(Ch, BasePath, Links);
dfs(Ch, BasePath, Links, Src);
}
}

Expand All @@ -82,11 +82,13 @@ void Controller::onDocumentLink(
lspserver::Callback<std::vector<DocumentLink>> Reply) {
auto Action = [File = Params.textDocument.uri.file().str(),
Reply = std::move(Reply), this]() mutable {
auto Draft = Store.getDraft(File)->Contents;
auto Src = llvm::StringRef(*Draft);
if (std::shared_ptr<NixTU> TU = getTU(File, Reply)) [[likely]] {
if (std::shared_ptr<nixf::Node> AST = getAST(*TU, Reply)) [[likely]] {
// Traverse the AST, provide the links
std::vector<DocumentLink> Links;
dfs(AST.get(), File, Links);
dfs(AST.get(), File, Links, Src);
Reply(std::move(Links));
}
}
Expand Down
Loading

0 comments on commit cc9e61d

Please sign in to comment.