ilya-biryukov created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ioeric.

A prototype that I made a while ago and never landed.
Not suppossed to be a final solution and will probably merge-conflict now,
publishing to not loose it.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53941

Files:
  clangd/ClangdLSPServer.cpp
  clangd/Diagnostics.cpp
  clangd/Diagnostics.h
  clangd/Protocol.cpp
  clangd/Protocol.h

Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -155,6 +155,7 @@
     return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);
   }
 };
+bool fromJSON(const llvm::json::Value&, Location &);
 llvm::json::Value toJSON(const Location &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Location &);
 
@@ -304,11 +305,20 @@
 };
 bool fromJSON(const llvm::json::Value &, WorkspaceClientCapabilities &);
 
+struct PublishDiagnosticsClientCapabilities {
+  /// Whether the clients accepts diagnostics with related information.
+  bool relatedInformation = false;
+};
+bool fromJSON(const llvm::json::Value &, PublishDiagnosticsClientCapabilities &);
+
 // FIXME: most of the capabilities are missing from this struct. Only the ones
 // used by clangd are currently there.
 struct TextDocumentClientCapabilities {
   /// Capabilities specific to the `textDocument/completion`
   CompletionClientCapabilities completion;
+
+  /// Capabilities specific to `textDocument/publishDiagnostics`.
+  PublishDiagnosticsClientCapabilities publishDiagnostics;
 };
 bool fromJSON(const llvm::json::Value &, TextDocumentClientCapabilities &);
 
@@ -485,6 +495,15 @@
 };
 bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &);
 
+struct DiagnosticRelatedInformation {
+	/// The location of this related diagnostic information.
+	Location location;
+	/// The message of this related diagnostic information.
+	std::string message;
+};
+bool fromJSON(const llvm::json::Value &, DiagnosticRelatedInformation &);
+llvm::json::Value toJSON(const DiagnosticRelatedInformation &);
+
 struct Diagnostic {
   /// The range at which the message applies.
   Range range;
@@ -504,6 +523,10 @@
 
   /// The diagnostic's message.
   std::string message;
+
+  /// An array of related diagnostic information, e.g. when symbol-names within
+  /// a scope collide all definitions can be marked via this property.
+  std::vector<DiagnosticRelatedInformation> relatedInformation; 
 };
 
 /// A LSP-specific comparator used to find diagnostic in a container like
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -100,6 +100,11 @@
   return OS << R.start << '-' << R.end;
 }
 
+bool fromJSON(const llvm::json::Value& Params, Location &P) {
+  json::ObjectMapper O(Params);
+  return O && O.map("uri", P.uri) && O.map("range", P.range);
+}
+
 json::Value toJSON(const Location &P) {
   return json::Object{
       {"uri", P.uri},
@@ -235,11 +240,17 @@
   return O && O.map("symbol", R.symbol);
 }
 
+bool fromJSON(const json::Value &Params, PublishDiagnosticsClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("symbol", R.relatedInformation);
+}
+
 bool fromJSON(const json::Value &Params, TextDocumentClientCapabilities &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
   O.map("completion", R.completion);
+  O.map("publishDiagnostics", R.publishDiagnostics);
   return true;
 }
 
@@ -349,11 +360,21 @@
   return O && O.map("textDocument", R.textDocument);
 }
 
+bool fromJSON(const llvm::json::Value &Params, DiagnosticRelatedInformation &I) {
+  json::ObjectMapper O(Params);
+  return O && O.map("location", I.location) && O.map("message", I.message);
+}
+
+llvm::json::Value toJSON(const DiagnosticRelatedInformation &I) {
+  return json::Object{{"location", I.location}, {"message", I.message}};
+}
+
 bool fromJSON(const json::Value &Params, Diagnostic &R) {
   json::ObjectMapper O(Params);
   if (!O || !O.map("range", R.range) || !O.map("message", R.message))
     return false;
   O.map("severity", R.severity);
+  O.map("relatedInformation", R.relatedInformation);
   return true;
 }
 
Index: clangd/Diagnostics.h
===================================================================
--- clangd/Diagnostics.h
+++ clangd/Diagnostics.h
@@ -12,11 +12,13 @@
 
 #include "Path.h"
 #include "Protocol.h"
+#include "URI.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Optional.h"
 #include <cassert>
 #include <string>
 
@@ -29,6 +31,7 @@
   // Intended to be used only in error messages.
   // May be relative, absolute or even artifically constructed.
   std::string File;
+  llvm::Optional<std::string> AbsPath;
   clangd::Range Range;
   DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note;
   // Since File is only descriptive, we store a separate flag to distinguish
Index: clangd/Diagnostics.cpp
===================================================================
--- clangd/Diagnostics.cpp
+++ clangd/Diagnostics.cpp
@@ -231,19 +231,19 @@
     return Res;
   };
 
-  {
-    clangd::Diagnostic Main = FillBasicFields(D);
-    Main.message = mainMessage(D);
-    OutFn(std::move(Main), D.Fixes);
-  }
-
+  clangd::Diagnostic Main = FillBasicFields(D);
+  Main.message = D.Message;
+  Main.relatedInformation.reserve(D.Notes.size());
   for (auto &Note : D.Notes) {
-    if (!Note.InsideMainFile)
-      continue;
-    clangd::Diagnostic Res = FillBasicFields(Note);
-    Res.message = noteMessage(D, Note);
-    OutFn(std::move(Res), llvm::ArrayRef<Fix>());
+    log("Note {0}", Note.Message);
+    DiagnosticRelatedInformation NoteInfo;
+    NoteInfo.location = clangd::Location{
+        clangd::URIForFile(), Note.Range};
+    NoteInfo.message = Note.Message;
+
+    Main.relatedInformation.push_back(std::move(NoteInfo));
   }
+  OutFn(std::move(Main), D.Fixes);
 }
 
 int getSeverity(DiagnosticsEngine::Level L) {
@@ -285,14 +285,20 @@
   }
 
   bool InsideMainFile = isInsideMainFile(Info);
+  const SourceManager &SrcMgr = Info.getSourceManager();
 
   auto FillDiagBase = [&](DiagBase &D) {
     D.Range = diagnosticRange(Info, *LangOpts);
     llvm::SmallString<64> Message;
     Info.FormatDiagnostic(Message);
     D.Message = Message.str();
     D.InsideMainFile = InsideMainFile;
-    D.File = Info.getSourceManager().getFilename(Info.getLocation());
+
+    D.File = SrcMgr.getFilename(Info.getLocation());
+    const FileID FID =
+        SrcMgr.getFileID(Info.getLocation());
+    const FileEntry *FE = SrcMgr.getFileEntryForID(FID);
+    D.AbsPath = getAbsoluteFilePath(FE, SrcMgr);
     D.Severity = DiagLevel;
     return D;
   };
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -466,6 +466,7 @@
           {"range", Diag.range},
           {"severity", Diag.severity},
           {"message", Diag.message},
+          {"relatedInformation", json::Array(Diag.relatedInformation)}
       });
 
       auto &FixItsForDiagnostic = LocalFixIts[Diag];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to