Skip to content

Commit

Permalink
nixd/Controller: handle UTF-16 code units for locations (#580)
Browse files Browse the repository at this point in the history
<img width="843" alt="截屏2024-08-11 00 02 30"
src="https://github.com/user-attachments/assets/137e17de-b0b9-4161-bccd-dbe4e5c952ca">

Handle LSP spec (UTF16) character length for locations.
  • Loading branch information
inclyc authored Aug 11, 2024
1 parent 2f515e0 commit 9b9ba70
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 106 deletions.
2 changes: 1 addition & 1 deletion nixd/include/nixd/Controller/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class Controller : public lspserver::LSPServer {
/// Determine whether or not this diagnostic is suppressed.
bool isSuppressed(nixf::Diagnostic::DiagnosticKind Kind);
void publishDiagnostics(lspserver::PathRef File,
std::optional<int64_t> Version,
std::optional<int64_t> Version, std::string_view Src,
const std::vector<nixf::Diagnostic> &Diagnostics);

void onRename(const lspserver::RenameParams &Params,
Expand Down
6 changes: 5 additions & 1 deletion nixd/include/nixd/Controller/NixTU.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ class NixTU {
std::optional<util::OwnedRegion> ASTByteCode;
std::unique_ptr<nixf::VariableLookupAnalysis> VLA;
std::unique_ptr<nixf::ParentMapAnalysis> PMA;
std::shared_ptr<const std::string> Src;

public:
NixTU() = default;
NixTU(std::vector<nixf::Diagnostic> Diagnostics,
std::shared_ptr<nixf::Node> AST,
std::optional<util::OwnedRegion> ASTByteCode,
std::unique_ptr<nixf::VariableLookupAnalysis> VLA);
std::unique_ptr<nixf::VariableLookupAnalysis> VLA,
std::shared_ptr<const std::string> Src);

[[nodiscard]] const std::vector<nixf::Diagnostic> &diagnostics() const {
return Diagnostics;
Expand All @@ -43,6 +45,8 @@ class NixTU {
[[nodiscard]] const nixf::VariableLookupAnalysis *variableLookup() const {
return VLA.get();
}

[[nodiscard]] std::string_view src() const { return *Src; }
};

} // namespace nixd
4 changes: 2 additions & 2 deletions nixd/lib/Controller/CodeAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void Controller::onCodeAction(const lspserver::CodeActionParams &Params,
std::vector<CodeAction> Actions;
Actions.reserve(Diagnostics.size());
for (const nixf::Diagnostic &D : Diagnostics) {
auto DRange = toLSPRange(D.range());
auto DRange = toLSPRange(TU->src(), D.range());
if (!Range.overlap(DRange))
continue;

Expand All @@ -34,7 +34,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(TU->src(), TE.oldRange()),
.newText = std::string(TE.newText()),
});
}
Expand Down
2 changes: 1 addition & 1 deletion nixd/lib/Controller/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void Controller::updateConfig(Configuration NewConfig) {
// After all, notify all AST modules the diagnostic set has been updated.
std::lock_guard TUsGuard(TUsLock);
for (const auto &[File, TU] : TUs) {
publishDiagnostics(File, std::nullopt, TU->diagnostics());
publishDiagnostics(File, std::nullopt, TU->src(), TU->diagnostics());
}
}

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
17 changes: 9 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 @@ -374,12 +375,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, TU->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, TU->src());
}
case Node::NK_ExprSelect: {
const auto &Sel = static_cast<const ExprSelect &>(UpExpr);
Expand Down
8 changes: 4 additions & 4 deletions nixd/lib/Controller/Diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bool Controller::isSuppressed(nixf::Diagnostic::DiagnosticKind Kind) {
}

void Controller::publishDiagnostics(
PathRef File, std::optional<int64_t> Version,
PathRef File, std::optional<int64_t> Version, std::string_view Src,
const std::vector<nixf::Diagnostic> &Diagnostics) {
std::vector<Diagnostic> LSPDiags;
LSPDiags.reserve(Diagnostics.size());
Expand All @@ -67,7 +67,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 +83,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 +93,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
9 changes: 5 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 @@ -67,7 +68,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, TU->src()));
} catch (std::exception &E) {
elog("textDocument/documentHighlight failed: {0}", E.what());
return Reply(std::vector<DocumentHighlight>{});
Expand Down
8 changes: 4 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 @@ -86,7 +86,7 @@ void Controller::onDocumentLink(
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, TU->src());
Reply(std::move(Links));
}
}
Expand Down
Loading

0 comments on commit 9b9ba70

Please sign in to comment.