https://github.com/Fil-Den updated https://github.com/llvm/llvm-project/pull/214951
>From 92c6aef642d9cedbee379f0d71e4102c28a35af8 Mon Sep 17 00:00:00 2001 From: Fil-Den <[email protected]> Date: Sat, 11 Jul 2026 18:46:03 +0300 Subject: [PATCH] Clangd-indexer respects .clangd files --- clang-tools-extra/clangd/ConfigProvider.cpp | 27 ++++++++++++++ clang-tools-extra/clangd/ConfigProvider.h | 10 +++++ .../clangd/indexer/IndexerMain.cpp | 37 ++++++++++++++++++- .../clangd/test/indexer-clangd-config.test | 25 +++++++++++++ clang-tools-extra/clangd/tool/ClangdMain.cpp | 24 ++---------- 5 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 clang-tools-extra/clangd/test/indexer-clangd-config.test diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp b/clang-tools-extra/clangd/ConfigProvider.cpp index ac437ee8b6eb1..e26509d8b1c8b 100644 --- a/clang-tools-extra/clangd/ConfigProvider.cpp +++ b/clang-tools-extra/clangd/ConfigProvider.cpp @@ -10,10 +10,12 @@ #include "Config.h" #include "ConfigFragment.h" #include "support/FileCache.h" +#include "support/Logger.h" #include "support/Path.h" #include "support/ThreadsafeFS.h" #include "support/Trace.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Path.h" @@ -166,6 +168,31 @@ Provider::combine(std::vector<const Provider *> Providers) { return std::make_unique<CombinedProvider>(std::move(Providers)); } +std::vector<std::unique_ptr<Provider>> +Provider::createDefaultProviders(const ThreadsafeFS &TFS) { + std::vector<std::unique_ptr<Provider>> Providers; + Providers.push_back(fromAncestorRelativeYAMLFiles(".clangd", TFS)); + llvm::SmallString<256> UserConfig; + if (llvm::sys::path::user_config_directory(UserConfig)) { + llvm::sys::path::append(UserConfig, "clangd", "config.yaml"); + vlog("User config file is {0}", UserConfig); + Providers.push_back( + fromYAMLFile(UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true)); + } else { + elog("Couldn't determine user config file, not loading"); + } + return Providers; +} + +const char *const Provider::EnableConfigFlagDesc = + "Read user and project configuration from YAML files.\n" + "Project config is from a .clangd file in the project directory.\n" + "User config is from clangd/config.yaml in the following directories:\n" + "\tWindows: %USERPROFILE%\\AppData\\Local\n" + "\tMac OS: ~/Library/Preferences/\n" + "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n" + "Configuration is documented at https://clangd.llvm.org/config.html"; + Config Provider::getConfig(const Params &P, DiagnosticCallback DC) const { trace::Span Tracer("getConfig"); if (!P.Path.empty()) diff --git a/clang-tools-extra/clangd/ConfigProvider.h b/clang-tools-extra/clangd/ConfigProvider.h index f268edb1df2a5..e1a52604e7de8 100644 --- a/clang-tools-extra/clangd/ConfigProvider.h +++ b/clang-tools-extra/clangd/ConfigProvider.h @@ -84,9 +84,19 @@ class Provider { /// Order is preserved; later providers take precedence over earlier ones. static std::unique_ptr<Provider> combine(std::vector<const Provider *>); + /// Returns providers for the configuration files that clangd tools read by + /// default: project config (ancestor `.clangd` files) and the user's + /// global config file. + static std::vector<std::unique_ptr<Provider>> + createDefaultProviders(const ThreadsafeFS &); + /// Build a config based on this provider. Config getConfig(const Params &, DiagnosticCallback) const; + /// Help text for the --enable-config flag, shared by clangd tools that + /// expose createDefaultProviders() on the command line. + static const char *const EnableConfigFlagDesc; + private: /// Provide fragments that may be relevant to the file. /// The configuration provider is not responsible for testing conditions. diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp b/clang-tools-extra/clangd/indexer/IndexerMain.cpp index 94db860f0b9b5..c330be298a87a 100644 --- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp +++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp @@ -10,21 +10,29 @@ // //===----------------------------------------------------------------------===// +#include "ClangdServer.h" #include "CompileCommands.h" #include "Compiler.h" +#include "ConfigProvider.h" #include "index/IndexAction.h" #include "index/Merge.h" #include "index/Ref.h" #include "index/Serialization.h" #include "index/Symbol.h" #include "index/SymbolCollector.h" +#include "support/Context.h" #include "support/Logger.h" +#include "support/ThreadsafeFS.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/Execution.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Signals.h" +#include <memory> #include <utility> +#include <vector> namespace clang { namespace clangd { @@ -48,6 +56,12 @@ static llvm::cl::list<std::string> QueryDriverGlobs{ llvm::cl::CommaSeparated, }; +static llvm::cl::opt<bool> EnableConfig{ + "enable-config", + llvm::cl::desc(config::Provider::EnableConfigFlagDesc), + llvm::cl::init(true), +}; + class IndexActionFactory : public tooling::FrontendActionFactory { public: IndexActionFactory(IndexFileIn &Result) : Result(Result) {} @@ -152,6 +166,20 @@ int main(int argc, const char **argv) { return 1; } + clang::clangd::RealThreadsafeFS TFS; + std::vector<std::unique_ptr<clang::clangd::config::Provider>> ProviderStack; + if (clang::clangd::EnableConfig) + ProviderStack = + clang::clangd::config::Provider::createDefaultProviders(TFS); + std::vector<const clang::clangd::config::Provider *> ProviderPointers; + for (const auto &P : ProviderStack) + ProviderPointers.push_back(P.get()); + auto ConfigProvider = + clang::clangd::config::Provider::combine(std::move(ProviderPointers)); + auto ContextProvider = + clang::clangd::ClangdServer::createConfiguredContextProvider( + ConfigProvider.get(), /*Callbacks=*/nullptr); + // Collect symbols found in each translation unit, merging as we go. clang::clangd::IndexFileIn Data; auto Mangler = std::make_shared<clang::clangd::CommandMangler>( @@ -162,8 +190,13 @@ int main(int argc, const char **argv) { auto Err = Executor->get()->execute( std::make_unique<clang::clangd::IndexActionFactory>(Data), clang::tooling::ArgumentsAdjuster( - [Mangler = std::move(Mangler)](const std::vector<std::string> &Args, - llvm::StringRef File) { + [Mangler = std::move(Mangler), + ContextProvider = std::move(ContextProvider)]( + const std::vector<std::string> &Args, llvm::StringRef File) { + llvm::SmallString<256> AbsFile(File); + llvm::sys::fs::make_absolute(AbsFile); + clang::clangd::WithContext WithCfg(ContextProvider(AbsFile)); + clang::tooling::CompileCommand Cmd; Cmd.CommandLine = Args; Mangler->operator()(Cmd, File); diff --git a/clang-tools-extra/clangd/test/indexer-clangd-config.test b/clang-tools-extra/clangd/test/indexer-clangd-config.test new file mode 100644 index 0000000000000..f99f2db410ee3 --- /dev/null +++ b/clang-tools-extra/clangd/test/indexer-clangd-config.test @@ -0,0 +1,25 @@ +# Test that clangd-indexer respects CompileFlags + +# RUN: rm -rf %t.dir && mkdir -p %t.dir +# RUN: split-file %s %t.dir + +# By default config is enabled, so the .clangd file's CompileFlags.Add should +# define FROM_CLANGD_FILE, and the #error below must not fire. +# RUN: clangd-indexer %t.dir/test.cpp 2>&1 | FileCheck --check-prefix=ENABLED %s +# ENABLED-NOT: error: "FROM_CLANGD_FILE not defined + +# With config disabled, the macro isn't defined by the .clangd file, so the +# #error must fire. +# RUN: clangd-indexer --enable-config=0 %t.dir/test.cpp 2>&1 \ +# RUN: | FileCheck --check-prefix=DISABLED %s +# DISABLED: error: "FROM_CLANGD_FILE not defined - .clangd file was not applied" + +#--- .clangd +CompileFlags: + Add: [-DFROM_CLANGD_FILE=1] + +#--- test.cpp +#ifndef FROM_CLANGD_FILE +#error "FROM_CLANGD_FILE not defined - .clangd file was not applied" +#endif +int foo() { return 0; } diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 13fe4d3911731..f95e2dbf5eb38 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -489,14 +489,7 @@ opt<bool> PrettyPrint{ opt<bool> EnableConfig{ "enable-config", cat(Misc), - desc( - "Read user and project configuration from YAML files.\n" - "Project config is from a .clangd file in the project directory.\n" - "User config is from clangd/config.yaml in the following directories:\n" - "\tWindows: %USERPROFILE%\\AppData\\Local\n" - "\tMac OS: ~/Library/Preferences/\n" - "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n" - "Configuration is documented at https://clangd.llvm.org/config.html"), + desc(config::Provider::EnableConfigFlagDesc), init(true), }; @@ -998,19 +991,8 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var RealThreadsafeFS TFS; std::vector<std::unique_ptr<config::Provider>> ProviderStack; std::unique_ptr<config::Provider> Config; - if (EnableConfig) { - ProviderStack.push_back( - config::Provider::fromAncestorRelativeYAMLFiles(".clangd", TFS)); - llvm::SmallString<256> UserConfig; - if (llvm::sys::path::user_config_directory(UserConfig)) { - llvm::sys::path::append(UserConfig, "clangd", "config.yaml"); - vlog("User config file is {0}", UserConfig); - ProviderStack.push_back(config::Provider::fromYAMLFile( - UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true)); - } else { - elog("Couldn't determine user config file, not loading"); - } - } + if (EnableConfig) + ProviderStack = config::Provider::createDefaultProviders(TFS); ProviderStack.push_back(std::make_unique<FlagsConfigProvider>()); std::vector<const config::Provider *> ProviderPointers; for (const auto &P : ProviderStack) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
