nixd
Loading...
Searching...
No Matches
Diagnostics.cpp
Go to the documentation of this file.
1/// \file
2/// \brief Implementation of [PublishDiagnostics Notification].
3/// [PublishDiagnostics Notification]:
4/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics
5
6#include "Convert.h"
7
9
11
12#include <mutex>
13#include <optional>
14
15using namespace nixd;
16using namespace llvm::json;
17using namespace lspserver;
18
19void Controller::updateSuppressed(const std::vector<std::string> &Sup) {
20 // Acquire the lock because the set needs to be written.
21 std::lock_guard _(SuppressedDiagnosticsLock);
22 // Clear the set, just construct a new one.
23 SuppressedDiagnostics.clear();
24
25 // For each element, see if the name matches some declared name.
26 // If so, insert the set.
27 for (const auto &Name : Sup) {
28 if (auto DK = nixf::Diagnostic::parseKind(Name)) {
29 SuppressedDiagnostics.insert(*DK);
30 } else {
31 // The name is not listed in knwon names. Log error here
32 lspserver::elog("diagnostic suppressing sname {0} is unknown", Name);
33 }
34 }
35}
36
37bool Controller::isSuppressed(nixf::Diagnostic::DiagnosticKind Kind) {
38 std::lock_guard _(SuppressedDiagnosticsLock);
39 return SuppressedDiagnostics.contains(Kind);
40}
41
42void Controller::publishDiagnostics(
43 PathRef File, std::optional<int64_t> Version, std::string_view Src,
44 const std::vector<nixf::Diagnostic> &Diagnostics) {
45 std::vector<Diagnostic> LSPDiags;
46 LSPDiags.reserve(Diagnostics.size());
47 for (const nixf::Diagnostic &D : Diagnostics) {
48 // Before actually doing anything,
49 // let's check if the diagnostic is suppressed.
50 // If suppressed, just skip it.
51 if (isSuppressed(D.kind()))
52 continue;
53
54 // Format the message.
55 std::string Message = D.format();
56
57 // Add fix information.
58 if (!D.fixes().empty()) {
59 Message += " (";
60 if (D.fixes().size() == 1) {
61 Message += "fix available";
62 } else {
63 Message += std::to_string(D.fixes().size());
64 Message += " fixes available";
65 }
66 Message += ")";
67 }
68
69 Diagnostic &Diag = LSPDiags.emplace_back(Diagnostic{
70 .range = toLSPRange(Src, D.range()),
71 .severity = getLSPSeverity(D.kind()),
72 .code = D.sname(),
73 .source = "nixf",
74 .message = Message,
75 .tags = toLSPTags(D.tags()),
76 .relatedInformation = std::vector<DiagnosticRelatedInformation>{},
77 });
78
79 assert(Diag.relatedInformation && "Must be initialized");
80 Diag.relatedInformation->reserve(D.notes().size());
81 for (const nixf::Note &N : D.notes()) {
82 Diag.relatedInformation->emplace_back(DiagnosticRelatedInformation{
83 .location =
86 .range = toLSPRange(Src, N.range()),
87 },
88 .message = N.format(),
89 });
90 }
91 auto Notes = D.notes();
92 auto DRange = Diag.range;
93
94 for (const nixf::Note &N : Notes) {
95 LSPDiags.emplace_back(Diagnostic{
96 .range = toLSPRange(Src, N.range()),
97 .severity = 4,
98 .code = N.sname(),
99 .source = "nixf",
100 .message = N.format(),
101 .tags = toLSPTags(N.tags()),
102 .relatedInformation =
103 std::vector<DiagnosticRelatedInformation>{
105 .location =
106 Location{
108 .range = DRange,
109 },
110 .message = "original diagnostic",
111 }},
112 });
113 }
114 }
115 PublishDiagnostic({
117 .diagnostics = std::move(LSPDiags),
118 .version = Version,
119 });
120}
Convert between LSP and nixf types.
Diagnostic::DiagnosticKind DK
Definition Lexer.cpp:39
static std::optional< Diagnostic::DiagnosticKind > parseKind(std::string_view SName)
Parse diagnostic "cname" to diagnostic id.
Whether current platform treats paths case insensitively.
Definition Connection.h:11
void elog(const char *Fmt, Ts &&...Vals)
Definition Logger.h:52
llvm::StringRef PathRef
Definition Path.h:27
int getLSPSeverity(nixf::Diagnostic::DiagnosticKind Kind)
Definition Convert.cpp:11
bool fromJSON(const llvm::json::Value &Params, Configuration::Diagnostic &R, llvm::json::Path P)
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
Definition Convert.cpp:40
llvm::SmallVector< lspserver::DiagnosticTag, 1 > toLSPTags(const std::vector< nixf::DiagnosticTag > &Tags)
Definition Convert.cpp:47
Location location
The location of this related diagnostic information.
URIForFile uri
The text document's URI.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)