malaperle updated this revision to Diff 187783.
malaperle added a comment.

Address comments.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55250/new/

https://reviews.llvm.org/D55250

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/XRefs.cpp
  unittests/clangd/XRefsTests.cpp

Index: unittests/clangd/XRefsTests.cpp
===================================================================
--- unittests/clangd/XRefsTests.cpp
+++ unittests/clangd/XRefsTests.cpp
@@ -648,7 +648,25 @@
             #define MACRO 2
             #undef macro
           )cpp",
-          "#define MACRO",
+          "#define MACRO 1",
+      },
+      {
+          R"cpp(// Macro
+            #define MACRO 0
+            #define MACRO2 ^MACRO
+          )cpp",
+          "#define MACRO 0",
+      },
+      {
+          R"cpp(// Macro
+            #define MACRO {\
+              return 0;\
+            }
+            int main() ^MACRO
+          )cpp",
+          R"cpp(#define MACRO {\
+              return 0;\
+            })cpp",
       },
       {
           R"cpp(// Forward class declaration
Index: clangd/XRefs.cpp
===================================================================
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -537,13 +537,30 @@
   return H;
 }
 
-/// Generate a \p Hover object given the macro \p MacroInf.
-static Hover getHoverContents(llvm::StringRef MacroName) {
-  Hover H;
-
-  H.contents.value = "#define ";
-  H.contents.value += MacroName;
+/// Generate a \p Hover object given the macro \p MacroDecl.
+static Hover getHoverContents(MacroDecl Decl, ParsedAST &AST) {
+  SourceManager &SM = AST.getASTContext().getSourceManager();
+  std::string Definition = Decl.Name;
+
+  // Try to get the full definition, not just the name
+  SourceLocation StartLoc = Decl.Info->getDefinitionLoc();
+  SourceLocation EndLoc = Decl.Info->getDefinitionEndLoc();
+  if (EndLoc.isValid()) {
+    EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM,
+                                        AST.getASTContext().getLangOpts());
+    bool Invalid;
+    StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
+    if (!Invalid) {
+      unsigned StartOffset = SM.getFileOffset(StartLoc);
+      unsigned EndOffset = SM.getFileOffset(EndLoc);
+      if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
+        Definition = Buffer.substr(StartOffset, EndOffset - StartOffset).str();
+    }
+  }
 
+  Hover H;
+  H.contents.kind = MarkupKind::PlainText;
+  H.contents.value = "#define " + Definition;
   return H;
 }
 
@@ -667,7 +684,7 @@
   auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
 
   if (!Symbols.Macros.empty())
-    return getHoverContents(Symbols.Macros[0].Name);
+    return getHoverContents(Symbols.Macros[0], AST);
 
   if (!Symbols.Decls.empty())
     return getHoverContents(Symbols.Decls[0].D);
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -362,6 +362,10 @@
   /// Client supports CodeAction return value for textDocument/codeAction.
   /// textDocument.codeAction.codeActionLiteralSupport.
   bool CodeActionStructure = false;
+
+  /// The supported set of MarkupKinds for hover.
+  /// textDocument.hover.contentFormat.
+  bool HoverSupportsMarkdown = false;
 };
 bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
 
@@ -822,6 +826,7 @@
   PlainText,
   Markdown,
 };
+bool fromJSON(const llvm::json::Value &, MarkupKind &);
 
 struct MarkupContent {
   MarkupKind kind = MarkupKind::PlainText;
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -245,6 +245,24 @@
               DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
         R.HierarchicalDocumentSymbol = *HierarchicalSupport;
     }
+    if (auto *Hover = TextDocument->getObject("hover")) {
+      if (auto HoverMarkupKinds = Hover->get("contentFormat")) {
+        auto *A = HoverMarkupKinds->getAsArray();
+        if (!A) {
+          return false;
+        }
+
+        for (size_t I = 0; I < A->size(); ++I) {
+          MarkupKind KindOut;
+          if (fromJSON((*A)[I], KindOut)) {
+            if (KindOut == MarkupKind::Markdown) {
+              R.HoverSupportsMarkdown = true;
+              break;
+            }
+          }
+        }
+      }
+    }
   }
   if (auto *Workspace = O->getObject("workspace")) {
     if (auto *Symbol = Workspace->getObject("symbol")) {
@@ -616,6 +634,19 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value &E, MarkupKind &Out) {
+  if (auto T = E.getAsString()) {
+    if (*T == "plaintext")
+      Out = MarkupKind::PlainText;
+    else if (*T == "markdown")
+      Out = MarkupKind::Markdown;
+    else
+      return false;
+    return true;
+  }
+  return false;
+}
+
 llvm::json::Value toJSON(const Hover &H) {
   llvm::json::Object Result{{"contents", toJSON(H.contents)}};
 
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -146,6 +146,9 @@
   bool SupportsHierarchicalDocumentSymbol = false;
   /// Whether the client supports showing file status.
   bool SupportFileStatus = false;
+  /// From capabilities of textDocument/hover.
+  bool HoverSupportsMarkdown = false;
+
   // Store of the current versions of the open documents.
   DraftStore DraftMgr;
 
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -331,6 +331,8 @@
   SupportsHierarchicalDocumentSymbol =
       Params.capabilities.HierarchicalDocumentSymbol;
   SupportFileStatus = Params.initializationOptions.FileStatus;
+  HoverSupportsMarkdown = Params.capabilities.HoverSupportsMarkdown;
+
   Reply(llvm::json::Object{
       {{"capabilities",
         llvm::json::Object{
@@ -802,8 +804,24 @@
 
 void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
                               Callback<llvm::Optional<Hover>> Reply) {
-  Server->findHover(Params.textDocument.uri.file(), Params.position,
-                    std::move(Reply));
+
+  Server->findHover(
+      Params.textDocument.uri.file(), Params.position,
+      Bind(
+          [this](decltype(Reply) Reply, Expected<Optional<Hover>> H) {
+            if (!H)
+              return Reply(H.takeError());
+
+            // If the client supports Markdown, convert from plaintext here.
+            if (*H && HoverSupportsMarkdown) {
+              (*H)->contents.kind = MarkupKind::Markdown;
+              (*H)->contents.value =
+                  llvm::formatv("```\n{0}\n```", (*H)->contents.value);
+            }
+
+            Reply(std::move(*H));
+          },
+          std::move(Reply)));
 }
 
 void ClangdLSPServer::applyConfiguration(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to