Index: clangd/GlobalCompilationDatabase.cpp =================================================================== --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -11,6 +11,24 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +static cl::opt CompileCommands("compileCommands", + cl::desc("Start with absolute path to compile_commands.json")); +} namespace clang { namespace clangd { @@ -36,6 +54,8 @@ /*Output=*/""); } + + std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { std::vector Commands; @@ -64,35 +84,62 @@ tooling::CompilationDatabase * DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { std::lock_guard Lock(Mutex); - namespace path = llvm::sys::path; + // if --compileCommands arg was invoked, check value and override default path + std::size_t found = CompileCommands.find_first_of("/"); + std::string TempString = CompileCommands; + if (found != std::string::npos) + { + File = TempString; + } + + std::string Error; + bool badPath = false; + File = path::parent_path(File); + auto CachedIt = CompilationDatabases.find(File); + if (CachedIt != CompilationDatabases.end()) + return CachedIt->second.get(); + auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error); + if (!CDB) { + if (!Error.empty()) { + badPath = true; + } + } 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(); + if (badPath) + { + 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; + } } // FIXME(ibiryukov): Invalidate cached compilation databases on changes auto result = CDB.get(); CompilationDatabases.insert(std::make_pair(Path, std::move(CDB))); return result; + } } + else + { + auto result = CDB.get(); + CompilationDatabases.insert(std::make_pair(File, std::move(CDB))); + return result; + } + // FIXME(ibiryukov): logging // Output.log("Failed to find compilation database for " + Twine(File) +