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

Reply via email to