[clang-tools-extra] 32626bc - [clangd] Add ClangdServer::customAction() extension point

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 13 03:26:45 PDT 2020


Author: Sam McCall
Date: 2020-08-13T12:26:32+02:00
New Revision: 32626bcc0b9b1180db7eebc46c45faff7905bd05

URL: https://github.com/llvm/llvm-project/commit/32626bcc0b9b1180db7eebc46c45faff7905bd05
DIFF: https://github.com/llvm/llvm-project/commit/32626bcc0b9b1180db7eebc46c45faff7905bd05.diff

LOG: [clangd] Add ClangdServer::customAction() extension point

This lets basic AST-consuming actions be defined outside clangdserver.
(it essentially exposes TUScheduler::runWithAST).

Two use cases for now:
 - replace ClangdServer::dumpAST, which doesn't really belong in the public
   interface (a followup patch will do this)
 - allow embedders to add/experiment with extra features
   (e.g. I know some who want to try crazy AST+ML code completion...)

Maybe in the future we should use this sort of mechanism to make ClangdServer
less of a monolith, but that's not in scope for now.
This would probably require a richer and more carefully-thought-out API.

Differential Revision: https://reviews.llvm.org/D85883

Added: 
    

Modified: 
    clang-tools-extra/clangd/ClangdServer.cpp
    clang-tools-extra/clangd/ClangdServer.h
    clang-tools-extra/clangd/unittests/ClangdTests.cpp
    clang-tools-extra/clangd/unittests/SyncAPI.cpp
    clang-tools-extra/clangd/unittests/SyncAPI.h

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index ec4855659501..919d59ab09d0 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -754,6 +754,11 @@ void ClangdServer::semanticHighlights(
                            TUScheduler::InvalidateOnUpdate);
 }
 
+void ClangdServer::customAction(PathRef File, llvm::StringRef Name,
+                                Callback<InputsAndAST> Action) {
+  WorkScheduler.runWithAST(Name, File, std::move(Action));
+}
+
 llvm::StringMap<TUScheduler::FileStats> ClangdServer::fileStats() const {
   return WorkScheduler.fileStats();
 }

diff  --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index 3529e5050aa3..7aed7d4f3d85 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -317,6 +317,13 @@ class ClangdServer {
   void semanticHighlights(PathRef File,
                           Callback<std::vector<HighlightingToken>>);
 
+  /// Runs an arbitrary action that has access to the AST of the specified file.
+  /// The action will execute on one of ClangdServer's internal threads.
+  /// The AST is only valid for the duration of the callback.
+  /// As with other actions, the file must have been opened.
+  void customAction(PathRef File, llvm::StringRef Name,
+                    Callback<InputsAndAST> Action);
+
   /// Returns estimated memory usage and other statistics for each of the
   /// currently open files.
   /// Overall memory usage of clangd may be significantly more than reported

diff  --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
index c21719d58bd6..585fabe60ab7 100644
--- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
@@ -15,6 +15,7 @@
 #include "Matchers.h"
 #include "SyncAPI.h"
 #include "TestFS.h"
+#include "TestTU.h"
 #include "URI.h"
 #include "support/Path.h"
 #include "support/Threading.h"
@@ -28,6 +29,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
+#include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <algorithm>
@@ -1141,6 +1143,21 @@ TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
                                 Field(&CodeCompletion::Scope, "ns::"))));
 }
 
+TEST(ClangdServerTest, CustomAction) {
+  OverlayCDB CDB(/*Base=*/nullptr);
+  MockFS FS;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  Server.addDocument(testPath("foo.cc"), "void x();");
+  Decl::Kind XKind = Decl::TranslationUnit;
+  EXPECT_THAT_ERROR(runCustomAction(Server, testPath("foo.cc"),
+                                    [&](InputsAndAST AST) {
+                                      XKind = findDecl(AST.AST, "x").getKind();
+                                    }),
+                    llvm::Succeeded());
+  EXPECT_EQ(XKind, Decl::Function);
+}
+
 // Tests fails when built with asan due to stack overflow. So skip running the
 // test as a workaround.
 #if !defined(__has_feature) || !__has_feature(address_sanitizer)

diff  --git a/clang-tools-extra/clangd/unittests/SyncAPI.cpp b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
index 36b028bd4d87..c356fb08d5dd 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -154,5 +154,20 @@ runSwitchHeaderSource(ClangdServer &Server, PathRef File) {
   return std::move(*Result);
 }
 
+llvm::Error runCustomAction(ClangdServer &Server, PathRef File,
+                            llvm::function_ref<void(InputsAndAST)> Action) {
+  llvm::Error Result = llvm::Error::success();
+  Notification Done;
+  Server.customAction(File, "Custom", [&](llvm::Expected<InputsAndAST> AST) {
+    if (!AST)
+      Result = AST.takeError();
+    else
+      Action(*AST);
+    Done.notify();
+  });
+  Done.wait();
+  return Result;
+}
+
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/unittests/SyncAPI.h b/clang-tools-extra/clangd/unittests/SyncAPI.h
index e16b9d8ff19b..63a128d4ddcd 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.h
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -60,6 +60,9 @@ runSemanticRanges(ClangdServer &Server, PathRef File,
 llvm::Expected<llvm::Optional<clangd::Path>>
 runSwitchHeaderSource(ClangdServer &Server, PathRef File);
 
+llvm::Error runCustomAction(ClangdServer &Server, PathRef File,
+                            llvm::function_ref<void(InputsAndAST)>);
+
 } // namespace clangd
 } // namespace clang
 


        


More information about the cfe-commits mailing list