Nebiroth updated this revision to Diff 114654.
Nebiroth added a comment.

Simpilified a pointer return value.


https://reviews.llvm.org/D37150

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/GlobalCompilationDatabase.cpp
  clangd/GlobalCompilationDatabase.h
  clangd/tool/ClangdMain.cpp

Index: clangd/tool/ClangdMain.cpp
===================================================================
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -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>
@@ -25,16 +25,43 @@
                      llvm::cl::desc("parse on main thread"),
                      llvm::cl::init(false), llvm::cl::Hidden);
 
+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."));
+
 int main(int argc, char *argv[]) {
   llvm::cl::ParseCommandLineOptions(argc, argv, "clangd");
 
   llvm::raw_ostream &Outs = llvm::outs();
   llvm::raw_ostream &Logs = llvm::errs();
   JSONOutput Out(Outs, Logs);
 
+  // If --compile-commands-dir arg was invoked, check value and override default
+  // path.
+  namespace path = llvm::sys::path;
+
+  if (!llvm::sys::path::is_absolute(CompileCommandsDir)) {
+    Out.log("Path specified by --compile-commands-dir must be an absolute "
+            "path. The argument will be ignored.\n");
+    CompileCommandsDir = "";
+  }
+
+  if (!llvm::sys::fs::exists(CompileCommandsDir)) {
+    Out.log("Path specified by --compile-commands-dir. The argument will be "
+            "ignored.\n");
+    CompileCommandsDir = "";
+  }
+  llvm::Optional<Path> CompileCommandsDirPath;
+
   // Change stdin to binary to not lose \r\n on windows.
   llvm::sys::ChangeStdinToBinary();
+  if (CompileCommandsDir.empty())
+    CompileCommandsDirPath = llvm::None;
+  else
+    CompileCommandsDirPath = CompileCommandsDir;
 
-  ClangdLSPServer LSPServer(Out, RunSynchronously);
+  ClangdLSPServer LSPServer(Out, RunSynchronously, CompileCommandsDirPath);
   LSPServer.run(std::cin);
 }
Index: clangd/GlobalCompilationDatabase.h
===================================================================
--- clangd/GlobalCompilationDatabase.h
+++ clangd/GlobalCompilationDatabase.h
@@ -45,13 +45,18 @@
 class DirectoryBasedGlobalCompilationDatabase
     : public GlobalCompilationDatabase {
 public:
+  DirectoryBasedGlobalCompilationDatabase(
+      llvm::Optional<Path> NewCompileCommandsDir)
+      : CompileCommandsDir(NewCompileCommandsDir.getValue()) {}
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override;
 
   void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);
 
 private:
   tooling::CompilationDatabase *getCompilationDatabase(PathRef File);
+  Path CompileCommandsDir;
+  tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File);
 
   std::mutex Mutex;
   /// Caches compilation databases loaded from directories(keys are
Index: clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clangd/GlobalCompilationDatabase.cpp
+++ clangd/GlobalCompilationDatabase.cpp
@@ -62,43 +62,52 @@
 }
 
 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);
+  std::string Error = "";
 
   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)) {
-
-    auto CachedIt = CompilationDatabases.find(Path);
-    if (CachedIt != CompilationDatabases.end())
-      return CachedIt->second.get();
-    std::string Error;
-    auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);
-    if (!CDB) {
-      if (!Error.empty()) {
-        // FIXME(ibiryukov): logging
-        // Output.log("Error when trying to load compilation database from " +
-        //            Twine(Path) + ": " + Twine(Error) + "\n");
-      }
-      continue;
-    }
+  if (CachedIt != CompilationDatabases.end())
+    return (CachedIt->second.get());
+  auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error);
+  if (CDB && Error.empty()) {
+    auto result = CDB.get();
+    CompilationDatabases.insert(std::make_pair(File, std::move(CDB)));
 
     // FIXME(ibiryukov): Invalidate cached compilation databases on changes
-    auto result = CDB.get();
-    CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));
     return result;
   }
-
   // FIXME(ibiryukov): logging
   // Output.log("Failed to find compilation database for " + Twine(File) +
   // "\n");
   return nullptr;
 }
 
+tooling::CompilationDatabase *
+DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  namespace path = llvm::sys::path;
+  if (!CompileCommandsDir.empty()) {
+    auto CDB = tryLoadDatabaseFromPath(CompileCommandsDir);    
+    return CDB;    
+  }
+
+  for (auto Path = path::parent_path(File); !Path.empty();
+       Path = path::parent_path(Path)) {
+    auto CDB = tryLoadDatabaseFromPath(Path);
+    if (!CDB)
+      continue;
+
+    return CDB;
+  }
+
+  return nullptr;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -273,16 +273,16 @@
   return DumpFuture.get();
 }
 
-Tagged<std::vector<Location>>
-ClangdServer::findDefinitions(PathRef File, Position Pos) {
+Tagged<std::vector<Location>> ClangdServer::findDefinitions(PathRef File,
+                                                            Position Pos) {
   auto FileContents = DraftMgr.getDraft(File);
-  assert(FileContents.Draft && "findDefinitions is called for non-added document");
+  assert(FileContents.Draft &&
+         "findDefinitions is called for non-added document");
 
   std::vector<Location> Result;
   auto TaggedFS = FSProvider.getTaggedFileSystem(File);
-  Units.runOnUnit(File, *FileContents.Draft, ResourceDir, CDB, PCHs,
-      TaggedFS.Value, [&](ClangdUnit &Unit) {
-        Result = Unit.findDefinitions(Pos);
-      });
+  Units.runOnUnit(
+      File, *FileContents.Draft, ResourceDir, CDB, PCHs, TaggedFS.Value,
+      [&](ClangdUnit &Unit) { Result = Unit.findDefinitions(Pos); });
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -25,7 +25,8 @@
 /// dispatch and ClangdServer together.
 class ClangdLSPServer {
 public:
-  ClangdLSPServer(JSONOutput &Out, bool RunSynchronously);
+  ClangdLSPServer(JSONOutput &Out, bool RunSynchronously,
+                  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
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -70,7 +70,7 @@
   void onCompletion(TextDocumentPositionParams Params, StringRef ID,
                     JSONOutput &Out) override;
   void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID,
-                            JSONOutput &Out) override;
+                        JSONOutput &Out) override;
 
 private:
   ClangdLSPServer &LangServer;
@@ -181,9 +181,11 @@
 void ClangdLSPServer::LSPProtocolCallbacks::onCompletion(
     TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) {
 
-  auto Items = LangServer.Server.codeComplete(
-      Params.textDocument.uri.file,
-      Position{Params.position.line, Params.position.character}).Value;
+  auto Items = LangServer.Server
+                   .codeComplete(Params.textDocument.uri.file,
+                                 Position{Params.position.line,
+                                          Params.position.character})
+                   .Value;
 
   std::string Completions;
   for (const auto &Item : Items) {
@@ -200,9 +202,11 @@
 void ClangdLSPServer::LSPProtocolCallbacks::onGoToDefinition(
     TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) {
 
-  auto Items = LangServer.Server.findDefinitions(
-      Params.textDocument.uri.file,
-      Position{Params.position.line, Params.position.character}).Value;
+  auto Items = LangServer.Server
+                   .findDefinitions(Params.textDocument.uri.file,
+                                    Position{Params.position.line,
+                                             Params.position.character})
+                   .Value;
 
   std::string Locations;
   for (const auto &Item : Items) {
@@ -216,8 +220,9 @@
       R"(,"result":[)" + Locations + R"(]})");
 }
 
-ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, bool RunSynchronously)
-    : Out(Out), DiagConsumer(*this),
+ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, bool RunSynchronously,
+                                 llvm::Optional<Path> CompileCommandsDir)
+    : Out(Out), CDB(CompileCommandsDir), DiagConsumer(*this),
       Server(CDB, DiagConsumer, FSProvider, RunSynchronously) {}
 
 void ClangdLSPServer::run(std::istream &In) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to