nridge created this revision.
nridge added reviewers: sammccall, ilya-biryukov, hokein.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.
nridge added a comment.

This patch adds server-side support for greying out code in inactive 
preprocessor branches (issue #132 
<https://github.com/clangd/clangd/issues/132>).

I didn't write test yet. I wanted to post the patch for feedback first, to see 
if the general approach is ok.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67536

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Compiler.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/SemanticHighlighting.h

Index: clang-tools-extra/clangd/SemanticHighlighting.h
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.h
+++ clang-tools-extra/clangd/SemanticHighlighting.h
@@ -85,6 +85,10 @@
 diffHighlightings(ArrayRef<HighlightingToken> New,
                   ArrayRef<HighlightingToken> Old);
 
+// Returns all inactive regions from an AST. Only generates inactive regions
+// for the main AST.
+std::vector<Range> getInactiveRegions(ParsedAST &AST);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -479,5 +479,18 @@
   llvm_unreachable("unhandled HighlightingKind");
 }
 
+std::vector<Range> getInactiveRegions(ParsedAST &AST) {
+  std::vector<Range> Result;
+  const SourceManager &SM = AST.getSourceManager();
+  for (const SourceRange &R :
+       AST.getPreprocessor().getPreprocessingRecord()->getSkippedRanges()) {
+    if (isInsideMainFile(R.getBegin(), SM)) {
+      Result.push_back({sourceLocToPosition(SM, R.getBegin()),
+                        sourceLocToPosition(SM, R.getEnd())});
+    }
+  }
+  return Result;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1222,6 +1222,15 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+/// Parameters for the inactive regions (server-side) push notification.
+struct InactiveRegionsParams {
+  /// The textdocument these inactive regions belong to.
+  TextDocumentIdentifier TextDocument;
+  /// The inactive regions that should be sent.
+  std::vector<Range> InactiveRegions;
+};
+llvm::json::Value toJSON(const InactiveRegionsParams &InactiveRegions);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -1073,5 +1073,11 @@
   };
 }
 
+llvm::json::Value toJSON(const InactiveRegionsParams &InactiveRegions) {
+  return llvm::json::Object{
+      {"textDocument", InactiveRegions.TextDocument},
+      {"regions", std::move(InactiveRegions.InactiveRegions)}};
+}
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Compiler.cpp
===================================================================
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -63,6 +63,7 @@
   // createInvocationFromCommandLine sets DisableFree.
   CI->getFrontendOpts().DisableFree = false;
   CI->getLangOpts()->CommentOpts.ParseAllComments = true;
+  CI->getPreprocessorOpts().DetailedRecord = true;
   return CI;
 }
 
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -52,11 +52,13 @@
   virtual void onFileUpdated(PathRef File, const TUStatus &Status){};
 
   /// Called by ClangdServer when some \p Highlightings for \p File are ready.
-  /// \p NumLines are the number of lines in the file where the highlightings
-  /// where generated from.
   virtual void
   onHighlightingsReady(PathRef File,
                        std::vector<HighlightingToken> Highlightings) {}
+
+  /// Called by ClangdServer when some \p InactiveRegions for \p File are ready.
+  virtual void onInactiveRegionsReady(PathRef File,
+                                      std::vector<Range> InactiveRegions) {}
 };
 
 /// When set, used by ClangdServer to get clang-tidy options for each particular
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -53,9 +53,10 @@
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer,
-                       bool SemanticHighlighting)
+                       bool SemanticHighlighting, bool CollectInactiveRegions)
       : FIndex(FIndex), DiagConsumer(DiagConsumer),
-        SemanticHighlighting(SemanticHighlighting) {}
+        SemanticHighlighting(SemanticHighlighting),
+        CollectInactiveRegions(CollectInactiveRegions) {}
 
   void onPreambleAST(PathRef Path, ASTContext &Ctx,
                      std::shared_ptr<clang::Preprocessor> PP,
@@ -70,13 +71,18 @@
 
     std::vector<Diag> Diagnostics = AST.getDiagnostics();
     std::vector<HighlightingToken> Highlightings;
+    std::vector<Range> InactiveRegions;
     if (SemanticHighlighting)
       Highlightings = getSemanticHighlightings(AST);
+    if (CollectInactiveRegions)
+      InactiveRegions = getInactiveRegions(AST);
 
     Publish([&]() {
       DiagConsumer.onDiagnosticsReady(Path, std::move(Diagnostics));
       if (SemanticHighlighting)
         DiagConsumer.onHighlightingsReady(Path, std::move(Highlightings));
+      if (CollectInactiveRegions)
+        DiagConsumer.onInactiveRegionsReady(Path, std::move(InactiveRegions));
     });
   }
 
@@ -93,6 +99,7 @@
   FileIndex *FIndex;
   DiagnosticsConsumer &DiagConsumer;
   bool SemanticHighlighting;
+  bool CollectInactiveRegions;
 };
 } // namespace
 
@@ -124,7 +131,9 @@
       WorkScheduler(
           CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
           std::make_unique<UpdateIndexCallbacks>(
-              DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
+              DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting,
+              /*CollectInactiveRegions=*/true), // TODO(nridge): allow proper
+                                                // configuration
           Opts.UpdateDebounce, Opts.RetentionPolicy) {
   // Adds an index to the stack, at higher priority than existing indexes.
   auto AddIndex = [&](SymbolIndex *Idx) {
Index: clang-tools-extra/clangd/ClangdLSPServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.h
+++ clang-tools-extra/clangd/ClangdLSPServer.h
@@ -58,6 +58,8 @@
   void
   onHighlightingsReady(PathRef File,
                        std::vector<HighlightingToken> Highlightings) override;
+  void onInactiveRegionsReady(PathRef File,
+                              std::vector<Range> InactiveRegions) override;
 
   // LSP methods. Notifications have signature void(const Params&).
   // Calls have signature void(const Params&, Callback<Response>).
@@ -125,6 +127,9 @@
   /// Sends a "publishSemanticHighlighting" notification to the LSP client.
   void publishSemanticHighlighting(SemanticHighlightingParams Params);
 
+  /// Sends a "publishInactiveRegions" notification to the LSP client.
+  void publishInactiveRegions(InactiveRegionsParams Params);
+
   /// Sends a "publishDiagnostics" notification to the LSP client.
   void publishDiagnostics(const URIForFile &File,
                           std::vector<clangd::Diagnostic> Diagnostics);
Index: clang-tools-extra/clangd/ClangdLSPServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -1056,6 +1056,10 @@
   notify("textDocument/semanticHighlighting", Params);
 }
 
+void ClangdLSPServer::publishInactiveRegions(InactiveRegionsParams Params) {
+  notify("textDocument/inactiveRegions", Params);
+}
+
 void ClangdLSPServer::publishDiagnostics(
     const URIForFile &File, std::vector<clangd::Diagnostic> Diagnostics) {
   // Publish diagnostics.
@@ -1211,6 +1215,12 @@
        toSemanticHighlightingInformation(Diffed)});
 }
 
+void ClangdLSPServer::onInactiveRegionsReady(
+    PathRef File, std::vector<Range> InactiveRegions) {
+  publishInactiveRegions(
+      {{URIForFile::canonicalize(File, /*TUPath=*/File)}, InactiveRegions});
+}
+
 void ClangdLSPServer::onDiagnosticsReady(PathRef File,
                                          std::vector<Diag> Diagnostics) {
   auto URI = URIForFile::canonicalize(File, /*TUPath=*/File);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to