Skip to content

Commit

Permalink
Use DiagnosticRelatedInformation if client supports publishDiagnostic…
Browse files Browse the repository at this point in the history
…s.relatedInformation (#276)

In clients that support DiagnosticRelatedInformation, display
clang notes as these nested diagnostics rather than appending
them to the parent diagnostic's message. Behaviour for clients
that don't support related information should be unchanged.
  • Loading branch information
LeszekSwirski authored and MaskRay committed Oct 24, 2019
1 parent 136639c commit 7313bf6
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 22 deletions.
6 changes: 4 additions & 2 deletions src/config.hh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ struct Config {
} clang;

struct ClientCapability {
// TextDocumentClientCapabilities.publishDiagnostics.relatedInformation
bool diagnosticsRelatedInformation = true;
// TextDocumentClientCapabilities.documentSymbol.hierarchicalDocumentSymbolSupport
bool hierarchicalDocumentSymbolSupport = true;
// TextDocumentClientCapabilities.definition.linkSupport
Expand Down Expand Up @@ -287,8 +289,8 @@ REFLECT_STRUCT(Config::ServerCap, documentOnTypeFormattingProvider,
foldingRangeProvider, workspace);
REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings,
resourceDir);
REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport,
linkSupport, snippetSupport);
REFLECT_STRUCT(Config::ClientCapability, diagnosticsRelatedInformation,
hierarchicalDocumentSymbolSupport, linkSupport, snippetSupport);
REFLECT_STRUCT(Config::CodeLens, localVariables);
REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize,
suffixWhitelist, whitelist);
Expand Down
6 changes: 6 additions & 0 deletions src/lsp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,18 @@ struct WorkspaceFolder {
enum class MessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 };
REFLECT_UNDERLYING(MessageType)

struct DiagnosticRelatedInformation {
Location location;
std::string message;
};

struct Diagnostic {
lsRange range;
int severity = 0;
int code = 0;
std::string source = "ccls";
std::string message;
std::vector<DiagnosticRelatedInformation> relatedInformation;
std::vector<TextEdit> fixits_;
};

Expand Down
3 changes: 2 additions & 1 deletion src/message_handler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ REFLECT_STRUCT(TextDocumentIdentifier, uri);
REFLECT_STRUCT(TextDocumentItem, uri, languageId, version, text);
REFLECT_STRUCT(TextEdit, range, newText);
REFLECT_STRUCT(VersionedTextDocumentIdentifier, uri, version);
REFLECT_STRUCT(Diagnostic, range, severity, code, source, message);
REFLECT_STRUCT(DiagnosticRelatedInformation, location, message);
REFLECT_STRUCT(Diagnostic, range, severity, code, source, message, relatedInformation);
REFLECT_STRUCT(ShowMessageParam, type, message);
REFLECT_UNDERLYING_B(LanguageId);

Expand Down
9 changes: 8 additions & 1 deletion src/messages/initialize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ struct TextDocumentClientCap {
struct DocumentSymbol {
bool hierarchicalDocumentSymbolSupport = false;
} documentSymbol;

struct PublishDiagnostics {
bool relatedInformation = false;
} publishDiagnostics;
};

REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
Expand All @@ -167,7 +171,8 @@ REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
hierarchicalDocumentSymbolSupport);
REFLECT_STRUCT(TextDocumentClientCap::LinkSupport, linkSupport);
REFLECT_STRUCT(TextDocumentClientCap, completion, definition, documentSymbol);
REFLECT_STRUCT(TextDocumentClientCap::PublishDiagnostics, relatedInformation);
REFLECT_STRUCT(TextDocumentClientCap, completion, definition, documentSymbol, publishDiagnostics);

struct ClientCap {
WorkspaceClientCap workspace;
Expand Down Expand Up @@ -294,6 +299,8 @@ void Initialize(MessageHandler *m, InitializeParam &param, ReplyOnce &reply) {
capabilities.textDocument.definition.linkSupport;
g_config->client.snippetSupport &=
capabilities.textDocument.completion.completionItem.snippetSupport;
g_config->client.diagnosticsRelatedInformation &=
capabilities.textDocument.publishDiagnostics.relatedInformation;
didChangeWatchedFiles =
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration;

Expand Down
49 changes: 31 additions & 18 deletions src/sema_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) {
}
}

void printDiag(llvm::raw_string_ostream &OS, const DiagBase &d) {
void PrintDiag(llvm::raw_string_ostream &OS, const DiagBase &d) {
if (d.concerned)
OS << llvm::sys::path::filename(d.file);
else
Expand Down Expand Up @@ -600,27 +600,40 @@ void *DiagnosticMain(void *manager_) {
for (auto &d : diags) {
if (!d.concerned)
continue;
std::string buf;
llvm::raw_string_ostream OS(buf);
Diagnostic &ls_diag = ls_diags.emplace_back();
Fill(d, ls_diag);
ls_diag.fixits_ = d.edits;
OS << d.message;
for (auto &n : d.notes) {
OS << "\n\n";
printDiag(OS, n);
}
OS.flush();
ls_diag.message = std::move(buf);
for (auto &n : d.notes) {
if (!n.concerned)
continue;
Diagnostic &ls_diag1 = ls_diags.emplace_back();
Fill(n, ls_diag1);
OS << n.message << "\n\n";
printDiag(OS, d);
if (g_config->client.diagnosticsRelatedInformation) {
ls_diag.message = d.message;
for (const Note &n : d.notes) {
SmallString<256> Str(n.file);
llvm::sys::path::remove_dots(Str, true);
Location loc{DocumentUri::FromPath(Str.str()),
lsRange{{n.range.start.line, n.range.start.column},
{n.range.end.line, n.range.end.column}}};
ls_diag.relatedInformation.push_back({loc, n.message});
}
} else {
std::string buf;
llvm::raw_string_ostream OS(buf);
OS << d.message;
for (const Note &n : d.notes) {
OS << "\n\n";
PrintDiag(OS, n);
}
OS.flush();
ls_diag1.message = std::move(buf);
ls_diag.message = std::move(buf);
for (const Note &n : d.notes) {
if (!n.concerned)
continue;
Diagnostic &ls_diag1 = ls_diags.emplace_back();
Fill(n, ls_diag1);
buf.clear();
OS << n.message << "\n\n";
PrintDiag(OS, d);
OS.flush();
ls_diag1.message = std::move(buf);
}
}
}

Expand Down

0 comments on commit 7313bf6

Please sign in to comment.