diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -10,6 +10,7 @@ #include "../clang-tidy/ClangTidyCheck.h" #include "../clang-tidy/ClangTidyDiagnosticConsumer.h" #include "../clang-tidy/ClangTidyModuleRegistry.h" +#include "../clang-tidy/GlobList.h" #include "AST.h" #include "Compiler.h" #include "Config.h" @@ -282,6 +283,41 @@ } } +std::vector> +buildChecks(tidy::ClangTidyContext *Context) { + using FactoryFunc = std::function( + llvm::StringRef, tidy::ClangTidyContext *)>; + const llvm::Optional &CheckGlob = Context->getOptions().Checks; + if (!CheckGlob || CheckGlob->empty()) + return {}; + thread_local std::pair>> + Cached; + static std::atomic CacheMiss, CacheAccess; + ++CacheAccess; + if (*CheckGlob != Cached.first) { + ++CacheMiss; + vlog("ClangTidyCheck factory cache miss '{0:P2}%'\n" + "Rebuilding ClangTidyChecks factory with new glob '{1}'", + static_cast(CacheMiss) / CacheAccess, *CheckGlob); + Cached.first.assign(CheckGlob->data(), CheckGlob->size()); + Cached.second.clear(); + tidy::ClangTidyCheckFactories CTFactories; + for (const auto &E : tidy::ClangTidyModuleRegistry::entries()) + E.instantiate()->addCheckFactories(CTFactories); + tidy::GlobList Glob(*CheckGlob); + for (const auto &Check : CTFactories) { + if (Glob.contains(Check.getKey())) + Cached.second.emplace_back(Check.getKey(), Check.getValue()); + } + } + std::vector> Result; + Result.reserve(Cached.second.size()); + for (auto &Factory : Cached.second) { + Result.push_back(Factory.second(Factory.first, Context)); + } + return Result; +} } // namespace llvm::Optional @@ -410,15 +446,12 @@ // diagnostics. if (PreserveDiags) { trace::Span Tracer("ClangTidyInit"); - tidy::ClangTidyCheckFactories CTFactories; - for (const auto &E : tidy::ClangTidyModuleRegistry::entries()) - E.instantiate()->addCheckFactories(CTFactories); CTContext.emplace(std::make_unique( tidy::ClangTidyGlobalOptions(), ClangTidyOpts)); CTContext->setDiagnosticsEngine(&Clang->getDiagnostics()); CTContext->setASTContext(&Clang->getASTContext()); CTContext->setCurrentFile(Filename); - CTChecks = CTFactories.createChecks(CTContext.getPointer()); + CTChecks = buildChecks(CTContext.getPointer()); llvm::erase_if(CTChecks, [&](const auto &Check) { return !Check->isLanguageVersionSupported(CTContext->getLangOpts()); });