[clang-tools-extra] r314678 - [clangd] Command line arg to specify compile_commands.json path

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 2 08:13:20 PDT 2017


Author: ibiryukov
Date: Mon Oct  2 08:13:20 2017
New Revision: 314678

URL: http://llvm.org/viewvc/llvm-project?rev=314678&view=rev
Log:
[clangd] Command line arg to specify compile_commands.json path

Summary: Adds compileCommands command line argument to specify an absolute path directly to the requested compile_commands.json for flags.

Reviewed By: ilya-biryukov

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

Modified:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdLSPServer.h
    clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
    clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h
    clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=314678&r1=314677&r2=314678&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Mon Oct  2 08:13:20 2017
@@ -196,8 +196,9 @@ void ClangdLSPServer::onSwitchSourceHead
 
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                                  bool SnippetCompletions,
-                                 llvm::Optional<StringRef> ResourceDir)
-    : Out(Out), CDB(/*Logger=*/Out),
+                                 llvm::Optional<StringRef> ResourceDir,
+                                 llvm::Optional<Path> CompileCommandsDir)
+    : Out(Out), CDB(/*Logger=*/Out, std::move(CompileCommandsDir)),
       Server(CDB, /*DiagConsumer=*/*this, FSProvider, AsyncThreadsCount,
              SnippetCompletions, /*Logger=*/Out, ResourceDir) {}
 

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=314678&r1=314677&r2=314678&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Mon Oct  2 08:13:20 2017
@@ -27,9 +27,13 @@ class JSONOutput;
 /// dispatch and ClangdServer together.
 class ClangdLSPServer : private DiagnosticsConsumer, private ProtocolCallbacks {
 public:
+  /// If \p CompileCommandsDir has a value, compile_commands.json will be
+  /// loaded only from \p CompileCommandsDir. Otherwise, clangd will look
+  /// for compile_commands.json in all parent directories of each file.
   ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                   bool SnippetCompletions,
-                  llvm::Optional<StringRef> ResourceDir);
+                  llvm::Optional<StringRef> ResourceDir,
+                  llvm::Optional<Path> CompileCommandsDir);
 
   /// Run LSP server loop, receiving input for it from \p In. \p In must be
   /// opened in binary mode. Output will be written using Out variable passed to

Modified: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp?rev=314678&r1=314677&r2=314678&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp (original)
+++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp Mon Oct  2 08:13:20 2017
@@ -8,10 +8,10 @@
 //===---------------------------------------------------------------------===//
 
 #include "GlobalCompilationDatabase.h"
+#include "Logger.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
-#include "Logger.h"
 
 namespace clang {
 namespace clangd {
@@ -38,8 +38,9 @@ tooling::CompileCommand getDefaultCompil
 }
 
 DirectoryBasedGlobalCompilationDatabase::
-    DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger)
-    : Logger(Logger) {}
+    DirectoryBasedGlobalCompilationDatabase(
+        clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir)
+        : Logger(Logger), CompileCommandsDir(std::move(CompileCommandsDir)) {}
 
 std::vector<tooling::CompileCommand>
 DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) {
@@ -67,31 +68,50 @@ void DirectoryBasedGlobalCompilationData
 }
 
 tooling::CompilationDatabase *
-DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) {
-  std::lock_guard<std::mutex> Lock(Mutex);
+DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) {
 
   namespace path = llvm::sys::path;
+  auto CachedIt = CompilationDatabases.find(File);
 
   assert((path::is_absolute(File, path::Style::posix) ||
           path::is_absolute(File, path::Style::windows)) &&
          "path must be absolute");
 
-  for (auto Path = path::parent_path(File); !Path.empty();
-       Path = path::parent_path(Path)) {
+  if (CachedIt != CompilationDatabases.end())
+    return CachedIt->second.get();
+  std::string Error = "";
+  auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error);
+  if (CDB && Error.empty()) {
+    auto Result = CDB.get();
+    CompilationDatabases.insert(std::make_pair(File, std::move(CDB)));
+    return Result;
+  }
+
+  return nullptr;
+}
 
-    auto CachedIt = CompilationDatabases.find(Path);
-    if (CachedIt != CompilationDatabases.end())
-      return CachedIt->second.get();
+tooling::CompilationDatabase *
+DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  namespace path = llvm::sys::path;
+  if (CompileCommandsDir.hasValue()) {
+    tooling::CompilationDatabase *ReturnValue =
+        tryLoadDatabaseFromPath(CompileCommandsDir.getValue());
+    if (ReturnValue == nullptr)
+      Logger.log("Failed to find compilation database for " + Twine(File) +
+                 "in overriden directory " + CompileCommandsDir.getValue() +
+                 "\n");
+    return ReturnValue;
+  }
 
-    std::string Error;
-    auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);
+  for (auto Path = path::parent_path(File); !Path.empty();
+       Path = path::parent_path(Path)) {
+    auto CDB = tryLoadDatabaseFromPath(Path);
     if (!CDB)
       continue;
-
     // FIXME(ibiryukov): Invalidate cached compilation databases on changes
-    auto Result = CDB.get();
-    CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));
-    return Result;
+    return CDB;
   }
 
   Logger.log("Failed to find compilation database for " + Twine(File) + "\n");

Modified: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h?rev=314678&r1=314677&r2=314678&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h (original)
+++ clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h Mon Oct  2 08:13:20 2017
@@ -47,7 +47,8 @@ public:
 class DirectoryBasedGlobalCompilationDatabase
     : public GlobalCompilationDatabase {
 public:
-  DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger);
+  DirectoryBasedGlobalCompilationDatabase(
+      clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir);
 
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override;
@@ -56,6 +57,7 @@ public:
 
 private:
   tooling::CompilationDatabase *getCompilationDatabase(PathRef File);
+  tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File);
 
   std::mutex Mutex;
   /// Caches compilation databases loaded from directories(keys are
@@ -67,6 +69,9 @@ private:
   llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
   /// Used for logging.
   clangd::Logger &Logger;
+  /// Used for command argument pointing to folder where compile_commands.json
+  /// is located.
+  llvm::Optional<Path> CompileCommandsDir;
 };
 } // namespace clangd
 } // namespace clang

Modified: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp?rev=314678&r1=314677&r2=314678&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp (original)
+++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp Mon Oct  2 08:13:20 2017
@@ -11,8 +11,8 @@
 #include "JSONRPCDispatcher.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
-
 #include <iostream>
 #include <memory>
 #include <string>
@@ -21,6 +21,12 @@
 using namespace clang;
 using namespace clang::clangd;
 
+static llvm::cl::opt<Path> CompileCommandsDir(
+    "compile-commands-dir",
+    llvm::cl::desc("Specify a path to look for compile_commands.json. If path "
+                   "is invalid, clangd will look in the current directory and "
+                   "parent paths of each source file."));
+
 static llvm::cl::opt<unsigned>
     WorkerThreadsCount("j",
                        llvm::cl::desc("Number of async workers used by clangd"),
@@ -56,18 +62,37 @@ int main(int argc, char *argv[]) {
   if (RunSynchronously)
     WorkerThreadsCount = 0;
 
+  /// Validate command line arguments.
   llvm::raw_ostream &Outs = llvm::outs();
   llvm::raw_ostream &Logs = llvm::errs();
   JSONOutput Out(Outs, Logs);
 
-  // Change stdin to binary to not lose \r\n on windows.
-  llvm::sys::ChangeStdinToBinary();
+  // If --compile-commands-dir arg was invoked, check value and override default
+  // path.
+  namespace path = llvm::sys::path;
+  llvm::Optional<Path> CompileCommandsDirPath;
+
+  if (CompileCommandsDir.empty()) {
+    CompileCommandsDirPath = llvm::None;
+  } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) ||
+             !llvm::sys::fs::exists(CompileCommandsDir)) {
+    llvm::errs() << "Path specified by --compile-commands-dir either does not "
+                    "exist or is not an absolute "
+                    "path. The argument will be ignored.\n";
+    CompileCommandsDirPath = llvm::None;
+  } else {
+    CompileCommandsDirPath = CompileCommandsDir;
+  }
 
   llvm::Optional<StringRef> ResourceDirRef = None;
   if (!ResourceDir.empty())
     ResourceDirRef = ResourceDir;
 
+  /// Change stdin to binary to not lose \r\n on windows.
+  llvm::sys::ChangeStdinToBinary();
+
+  /// Initialize and run ClangdLSPServer.
   ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets,
-                            ResourceDirRef);
+                            ResourceDirRef, CompileCommandsDirPath);
   LSPServer.run(std::cin);
 }




More information about the cfe-commits mailing list