nridge created this revision. nridge added a reviewer: ilya-biryukov. Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay. Herald added a project: clang.
This is useful for multi-project setups where each project has its own compilation database, and particularly in cases where such databases are located outside of the respective source directories (for example, in build directories). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D65625 Files: clang-tools-extra/clangd/ClangdLSPServer.cpp clang-tools-extra/clangd/GlobalCompilationDatabase.cpp clang-tools-extra/clangd/GlobalCompilationDatabase.h clang-tools-extra/clangd/Protocol.cpp clang-tools-extra/clangd/Protocol.h clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
Index: clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp +++ clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp @@ -39,7 +39,7 @@ using ::testing::UnorderedElementsAre; TEST(GlobalCompilationDatabaseTest, FallbackCommand) { - DirectoryBasedGlobalCompilationDatabase DB(None); + DirectoryBasedGlobalCompilationDatabase DB(None, None); auto Cmd = DB.getFallbackCommand(testPath("foo/bar.cc")); EXPECT_EQ(Cmd.Directory, testPath("foo")); EXPECT_THAT(Cmd.CommandLine, @@ -241,7 +241,7 @@ // Note that gen2.cc goes missing with our following model, not sure this // happens in practice though. { - DirectoryBasedGlobalCompilationDatabase DB(llvm::None); + DirectoryBasedGlobalCompilationDatabase DB(llvm::None, llvm::None); std::vector<std::string> DiscoveredFiles; auto Sub = DB.watch([&DiscoveredFiles](const std::vector<std::string> Changes) { @@ -263,7 +263,7 @@ // With a custom compile commands dir. { - DirectoryBasedGlobalCompilationDatabase DB(FS.Root.str().str()); + DirectoryBasedGlobalCompilationDatabase DB(FS.Root.str().str(), llvm::None); std::vector<std::string> DiscoveredFiles; auto Sub = DB.watch([&DiscoveredFiles](const std::vector<std::string> Changes) { Index: clang-tools-extra/clangd/Protocol.h =================================================================== --- clang-tools-extra/clangd/Protocol.h +++ clang-tools-extra/clangd/Protocol.h @@ -23,6 +23,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H +#include "Path.h" #include "URI.h" #include "index/SymbolID.h" #include "clang/Index/IndexSymbol.h" @@ -448,6 +449,14 @@ }; bool fromJSON(const llvm::json::Value &, ConfigurationSettings &); +struct CompilationDatabasePath { + Path sourceDir; + Path dbPath; +}; +bool fromJSON(const llvm::json::Value &, CompilationDatabasePath &); + +using CompilationDatabaseMap = std::vector<CompilationDatabasePath>; + /// Clangd extension: parameters configurable at `initialize` time. /// LSP defines this type as `any`. struct InitializationOptions { @@ -455,7 +464,12 @@ // also set through the initialize request (initializationOptions field). ConfigurationSettings ConfigSettings; - llvm::Optional<std::string> compilationDatabasePath; + llvm::Optional<Path> compilationDatabasePath; + + // A map from source directories to directories containing compilation + // database files. Paths must be absolute. + llvm::Optional<CompilationDatabaseMap> compilationDatabaseMap; + // Additional flags to be included in the "fallback command" used when // the compilation database doesn't describe an opened file. // The command used will be approximately `clang $FILE $fallbackFlags`. Index: clang-tools-extra/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/clangd/Protocol.cpp +++ clang-tools-extra/clangd/Protocol.cpp @@ -931,6 +931,16 @@ return true; } +bool fromJSON(const llvm::json::Value &Params, CompilationDatabasePath &P) { + llvm::json::ObjectMapper O(Params); + if (!O) + return true; // 'any' type in LSP. + + O.map("sourceDir", P.sourceDir); + O.map("dbPath", P.dbPath); + return true; +} + bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts) { llvm::json::ObjectMapper O(Params); if (!O) @@ -938,6 +948,7 @@ fromJSON(Params, Opts.ConfigSettings); O.map("compilationDatabasePath", Opts.compilationDatabasePath); + O.map("compilationDatabaseMap", Opts.compilationDatabaseMap); O.map("fallbackFlags", Opts.fallbackFlags); O.map("clangdFileStatus", Opts.FileStatus); return true; Index: clang-tools-extra/clangd/GlobalCompilationDatabase.h =================================================================== --- clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -11,6 +11,7 @@ #include "Function.h" #include "Path.h" +#include "Protocol.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" @@ -66,7 +67,8 @@ : public GlobalCompilationDatabase { public: DirectoryBasedGlobalCompilationDatabase( - llvm::Optional<Path> CompileCommandsDir); + llvm::Optional<Path> CompileCommandsDir, + llvm::Optional<CompilationDatabaseMap> CDBMap); ~DirectoryBasedGlobalCompilationDatabase() override; /// Scans File's parents looking for compilation databases. @@ -109,6 +111,8 @@ /// Used for command argument pointing to folder where compile_commands.json /// is located. llvm::Optional<Path> CompileCommandsDir; + + llvm::Optional<CompilationDatabaseMap> CDBMap; }; /// Extracts system include search path from drivers matching QueryDriverGlobs Index: clang-tools-extra/clangd/GlobalCompilationDatabase.cpp =================================================================== --- clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -92,8 +92,10 @@ DirectoryBasedGlobalCompilationDatabase:: DirectoryBasedGlobalCompilationDatabase( - llvm::Optional<Path> CompileCommandsDir) - : CompileCommandsDir(std::move(CompileCommandsDir)) {} + llvm::Optional<Path> CompileCommandsDir, + llvm::Optional<CompilationDatabaseMap> CDBMap) + : CompileCommandsDir(std::move(CompileCommandsDir)), + CDBMap(std::move(CDBMap)) {} DirectoryBasedGlobalCompilationDatabase:: ~DirectoryBasedGlobalCompilationDatabase() = default; @@ -168,6 +170,13 @@ CachedCDB *Entry = nullptr; if (CompileCommandsDir) { Entry = &getCDBInDirLocked(*CompileCommandsDir); + } else if (CDBMap) { + for (const auto &MapEntry : *CDBMap) { + if (StringRef(Request.FileName).startswith(MapEntry.sourceDir)) { + Entry = &getCDBInDirLocked(MapEntry.dbPath); + break; + } + } } else { // Traverse the canonical version to prevent false positives. i.e.: // src/build/../a.cc can detect a CDB in /src/build if not canonicalized. Index: clang-tools-extra/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -353,7 +353,8 @@ CompileCommandsDir = Dir; if (UseDirBasedCDB) { BaseCDB = llvm::make_unique<DirectoryBasedGlobalCompilationDatabase>( - CompileCommandsDir); + CompileCommandsDir, + Params.initializationOptions.compilationDatabaseMap); BaseCDB = getQueryDriverDatabase( llvm::makeArrayRef(ClangdServerOpts.QueryDriverGlobs), std::move(BaseCDB));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits