diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -467,11 +467,10 @@ if (Server) return Reply(llvm::make_error("server already initialized", ErrorCode::InvalidRequest)); - if (const auto &Dir = Params.initializationOptions.compilationDatabasePath) - Opts.CompileCommandsDir = Dir; if (Opts.UseDirBasedCDB) { DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS); - CDBOpts.CompileCommandsDir = Opts.CompileCommandsDir; + if (const auto &Dir = Params.initializationOptions.compilationDatabasePath) + CDBOpts.CompileCommandsDir = Dir; CDBOpts.ContextProvider = Opts.ContextProvider; BaseCDB = std::make_unique(CDBOpts); diff --git a/clang-tools-extra/clangd/test/log.test b/clang-tools-extra/clangd/test/log.test --- a/clang-tools-extra/clangd/test/log.test +++ b/clang-tools-extra/clangd/test/log.test @@ -1,9 +1,9 @@ -# RUN: env CLANGD_FLAGS=-index-file=no-such-index not clangd -lit-test &1 >/dev/null | FileCheck %s +# RUN: env CLANGD_FLAGS=-compile-commands-dir=no-such-dir not clangd -lit-test &1 >/dev/null | FileCheck %s CHECK: I[{{.*}}]{{.*}} clangd version {{.*}} CHECK: Working directory: {{.*}} CHECK: argv[0]: clangd CHECK: argv[1]: -lit-test -CHECK: CLANGD_FLAGS: -index-file=no-such-index -CHECK: E[{{.*}}] Can't open no-such-index +CHECK: CLANGD_FLAGS: -compile-commands-dir=no-such-dir +CHECK: E[{{.*}}] Path specified by --compile-commands-dir does not exist. CHECK: Starting LSP over stdin/stdout diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -8,6 +8,8 @@ #include "ClangdLSPServer.h" #include "CodeComplete.h" +#include "Config.h" +#include "ConfigProvider.h" #include "Features.inc" #include "PathMapping.h" #include "Protocol.h" @@ -43,6 +45,7 @@ #include #include #include +#include #include #ifndef _WIN32 @@ -544,15 +547,55 @@ log("Associating {0} with monolithic index at {1}.", External.MountPoint, External.Location); auto NewIndex = std::make_unique(std::make_unique()); - Tasks.runAsync("Load-index:" + External.Location, - [File = External.Location, PlaceHolder = NewIndex.get()] { - if (auto Idx = loadIndex(File, /*UseDex=*/true)) - PlaceHolder->reset(std::move(Idx)); - }); + auto IndexLoadTask = [File = External.Location, + PlaceHolder = NewIndex.get()] { + if (auto Idx = loadIndex(File, /*UseDex=*/true)) + PlaceHolder->reset(std::move(Idx)); + }; + if (Sync) { + IndexLoadTask(); + } else { + Tasks.runAsync("Load-index:" + External.Location, + std::move(IndexLoadTask)); + } return std::move(NewIndex); } llvm_unreachable("Invalid ExternalIndexKind."); } + +class CommandLineFlagsConfigProvider : public config::Provider { + std::vector + getFragments(const config::Params &, + config::DiagnosticCallback) const override { + config::CompiledFragment Frag = [](const config::Params &, Config &C) { + if (!CompileCommandsDir.empty()) { + C.CompileFlags.CDBSearch = {Config::CDBSearchSpec::FixedDir, + CompileCommandsDir.getValue()}; + } + if (!IndexFile.empty()) { + Config::ExternalIndexSpec Spec; + Spec.Kind = Spec.File; + Spec.Location = IndexFile; + Spec.MountPoint = ""; + C.Index.External = std::move(Spec); + } + if (!RemoteIndexAddress.empty()) { + assert(!ProjectRoot.empty() && IndexFile.empty()); + Config::ExternalIndexSpec Spec; + Spec.Kind = Spec.Server; + Spec.Location = RemoteIndexAddress; + Spec.MountPoint = ProjectRoot; + C.Index.External = std::move(Spec); + C.Index.Background = Config::BackgroundPolicy::Skip; + } + if (!EnableBackgroundIndex) { + C.Index.Background = Config::BackgroundPolicy::Skip; + } + return true; + }; + return {Frag}; + } +}; } // namespace } // namespace clangd } // namespace clang @@ -707,12 +750,17 @@ "--compile-commands-dir to an absolute path: {0}. The argument " "will be ignored.", EC.message()); + CompileCommandsDir.clear(); } else { - Opts.CompileCommandsDir = std::string(Path.str()); + CompileCommandsDir = Path.str().str(); + // FIXME: Still set for clangd --check. Use config in --check workflow + // and get rid of these options? + Opts.CompileCommandsDir = CompileCommandsDir; } } else { elog("Path specified by --compile-commands-dir does not exist. The " "argument will be ignored."); + CompileCommandsDir.clear(); } } @@ -729,18 +777,6 @@ Opts.BuildDynamicSymbolIndex = true; std::vector> IdxStack; std::unique_ptr StaticIdx; - std::future AsyncIndexLoad; // Block exit while loading the index. - if (!IndexFile.empty()) { - // Load the index asynchronously. Meanwhile SwapIndex returns no results. - SwapIndex *Placeholder; - StaticIdx.reset(Placeholder = new SwapIndex(std::make_unique())); - AsyncIndexLoad = runAsync([Placeholder] { - if (auto Idx = loadIndex(IndexFile, /*UseDex=*/true)) - Placeholder->reset(std::move(Idx)); - }); - if (Sync) - AsyncIndexLoad.wait(); - } #if CLANGD_ENABLE_REMOTE if (RemoteIndexAddress.empty() != ProjectRoot.empty()) { llvm::errs() << "remote-index-address and project-path have to be " @@ -750,8 +786,6 @@ if (!RemoteIndexAddress.empty()) { if (IndexFile.empty()) { log("Connecting to remote index at {0}", RemoteIndexAddress); - StaticIdx = remote::getClient(RemoteIndexAddress, ProjectRoot); - EnableBackgroundIndex = false; } else { elog("When enabling remote index, IndexFile should not be specified. " "Only one can be used at time. Remote index will ignored."); @@ -802,12 +836,13 @@ } else { elog("Couldn't determine user config file, not loading"); } - std::vector ProviderPointers; - for (const auto &P : ProviderStack) - ProviderPointers.push_back(P.get()); - Config = config::Provider::combine(std::move(ProviderPointers)); - Opts.ConfigProvider = Config.get(); } + ProviderStack.push_back(std::make_unique()); + std::vector ProviderPointers; + for (const auto &P : ProviderStack) + ProviderPointers.push_back(P.get()); + Config = config::Provider::combine(std::move(ProviderPointers)); + Opts.ConfigProvider = Config.get(); // Create an empty clang-tidy option. TidyProvider ClangTidyOptProvider;