sammccall created this revision. sammccall added reviewers: adamcz, kadircet. Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous. Herald added a project: clang. sammccall requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85883 Files: 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
Index: clang-tools-extra/clangd/unittests/SyncAPI.h =================================================================== --- clang-tools-extra/clangd/unittests/SyncAPI.h +++ clang-tools-extra/clangd/unittests/SyncAPI.h @@ -60,6 +60,9 @@ llvm::Expected<llvm::Optional<clangd::Path>> runSwitchHeaderSource(ClangdServer &Server, PathRef File); +llvm::Error runCustomAction(ClangdServer &Server, PathRef File, + llvm::function_ref<void(ParsedAST *)>); + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SyncAPI.cpp +++ clang-tools-extra/clangd/unittests/SyncAPI.cpp @@ -154,5 +154,20 @@ return std::move(*Result); } +llvm::Error runCustomAction(ClangdServer &Server, PathRef File, + llvm::function_ref<void(ParsedAST *)> Action) { + llvm::Error Result = llvm::Error::success(); + Notification Done; + Server.customAction(File, "Custom", [&](llvm::Expected<ParsedAST *> AST) { + if (!AST) + Result = AST.takeError(); + else + Action(*AST); + Done.notify(); + }); + Done.wait(); + return Result; +} + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/unittests/ClangdTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/ClangdTests.cpp +++ 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 @@ 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"), + [&](ParsedAST *AST) { + XKind = findDecl(*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) Index: clang-tools-extra/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/clangd/ClangdServer.h +++ clang-tools-extra/clangd/ClangdServer.h @@ -317,6 +317,13 @@ 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<ParsedAST *> 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 Index: clang-tools-extra/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdServer.cpp +++ clang-tools-extra/clangd/ClangdServer.cpp @@ -754,6 +754,17 @@ TUScheduler::InvalidateOnUpdate); } +void ClangdServer::customAction(PathRef File, llvm::StringRef Name, + Callback<ParsedAST *> Action) { + auto A = [Action = std::move(Action)]( + llvm::Expected<InputsAndAST> InpAST) mutable { + if (!InpAST) + return Action(InpAST.takeError()); + Action(&InpAST->AST); + }; + WorkScheduler.runWithAST(Name, File, std::move(A)); +} + llvm::StringMap<TUScheduler::FileStats> ClangdServer::fileStats() const { return WorkScheduler.fileStats(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits