Skip to content

Commit

Permalink
nixd-next: basic diagnostics support in the Controller
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Jan 20, 2024
1 parent 64d34ee commit 412892a
Showing 1 changed file with 65 additions and 8 deletions.
73 changes: 65 additions & 8 deletions nixd-next/tools/nixd/src/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,77 @@
/// \brief Controller. The process interacting with users.
#include "nixd-config.h"

#include "nixf/Basic/Diagnostic.h"
#include "nixf/Parse/Parser.h"

#include "lspserver/DraftStore.h"
#include "lspserver/LSPServer.h"
#include "lspserver/Path.h"
#include "lspserver/Protocol.h"
#include "lspserver/SourceCode.h"

#include <llvm/Support/JSON.h>

#include <sstream>

namespace {

using namespace lspserver;
using namespace llvm::json;

Position toLSPPosition(const nixf::Point &P) {
return Position{static_cast<int>(P.line()), static_cast<int>(P.column())};
}

Range toLSPRange(const nixf::RangeTy &R) {
return Range{toLSPPosition(R.begin()), toLSPPosition(R.end())};
}

std::string simpleFormat(const char *Fmt,
const std::vector<std::string> &Args) {
std::stringstream SS;
std::size_t ArgIdx = 0;
for (const char *Cur = Fmt; *Cur;) {
if (*Cur == '{' && *(Cur + 1) == '}') {
SS << Args[ArgIdx++];
Cur += 2;
} else {
SS << *Cur;
++Cur;
}
}
return SS.str();
}

class Controller : public LSPServer {
DraftStore Store;

void addDocument(PathRef File, llvm::StringRef Contents,
llvm::StringRef Version) {
Store.addDraft(File, Version, Contents);
llvm::unique_function<void(const lspserver::PublishDiagnosticsParams &)>
PublishDiagnostic;

/// Action right after a document is added (including updates).
void actOnDocumentAdd(PathRef File, std::optional<int64_t> Version) {
auto Draft = Store.getDraft(File);
assert(Draft && "Added document is not in the store?");
std::vector<nixf::Diagnostic> Diagnostics;
nixf::parse(*Draft->Contents, Diagnostics);

std::vector<Diagnostic> LSPDiags;
LSPDiags.reserve(Diagnostics.size());
for (const nixf::Diagnostic &D : Diagnostics) {
LSPDiags.emplace_back(Diagnostic{
.range = toLSPRange(D.range()),
.severity = 0,
.code = D.sname(),
.source = "nixf",
.message = simpleFormat(D.message(), D.args()),
});
}
PublishDiagnostic({
.uri = URIForFile::canonicalize(File, File),
.diagnostics = std::move(LSPDiags),
.version = Version,
});
}

void removeDocument(PathRef File) { Store.removeDraft(File); }
Expand Down Expand Up @@ -48,14 +101,18 @@ class Controller : public LSPServer {
}};

Reply(std::move(Result));

PublishDiagnostic = mkOutNotifiction<lspserver::PublishDiagnosticsParams>(
"textDocument/publishDiagnostics");
}
void onInitialized([[maybe_unused]] const InitializedParams &Params) {}

void onDocumentDidOpen(const DidOpenTextDocumentParams &Params) {
PathRef File = Params.textDocument.uri.file();
const std::string &Contents = Params.textDocument.text;
addDocument(File, Contents,
DraftStore::encodeVersion(Params.textDocument.version));
std::optional<int64_t> Version = Params.textDocument.version;
Store.addDraft(File, DraftStore::encodeVersion(Version), Contents);
actOnDocumentAdd(File, Version);
}

void onDocumentDidChange(const DidChangeTextDocumentParams &Params) {
Expand All @@ -76,9 +133,9 @@ class Controller : public LSPServer {
return;
}
}
std::string Version =
DraftStore::encodeVersion(Params.textDocument.version);
addDocument(File, NewCode, Version);
std::optional<int64_t> Version = Params.textDocument.version;
Store.addDraft(File, DraftStore::encodeVersion(Version), NewCode);
actOnDocumentAdd(File, Version);
}

void onDocumentDidClose(const DidCloseTextDocumentParams &Params) {
Expand Down

0 comments on commit 412892a

Please sign in to comment.