diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -500,6 +500,11 @@ StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } /// Returns the language options from the context. const LangOptions &getLangOpts() const { return Context->getLangOpts(); } + /// Returns the options if clang-tidy had been ran on \p Filename. + OptionsView getOptionsForFile(StringRef Filename) const; + /// Returns true if this check would be enabled if clang-tidy had been ran on + /// \p Filename. + bool isCheckEnabledForFile(StringRef Filename) const; }; /// Read a named option from the ``Context`` and parse it as a bool. diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ClangTidyCheck.h" +#include "GlobList.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -233,5 +234,17 @@ return llvm::None; } +ClangTidyCheck::OptionsView +ClangTidyCheck::getOptionsForFile(StringRef Filename) const { + return OptionsView(CheckName, + Context->getOptionsForFile(Filename).CheckOptions); +} + +bool ClangTidyCheck::isCheckEnabledForFile(StringRef Filename) const { + auto Checks = Context->getOptionsForFile(Filename).Checks; + if (!Checks) + return false; + return GlobList(*Checks).contains(CheckName); +} } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -136,7 +136,7 @@ /// Returns options for \c File. Does not change or depend on /// \c CurrentFile. - ClangTidyOptions getOptionsForFile(StringRef File) const; + const ClangTidyOptions &getOptionsForFile(StringRef File) const; /// Returns \c ClangTidyStats containing issued and ignored diagnostic /// counters. @@ -190,6 +190,8 @@ std::unique_ptr CheckFilter; std::unique_ptr WarningAsErrorFilter; + mutable llvm::StringMap CachedDirectoryOptions; + LangOptions LangOpts; ClangTidyStats Stats; diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -202,11 +202,20 @@ return CurrentOptions; } -ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const { +const ClangTidyOptions & +ClangTidyContext::getOptionsForFile(StringRef File) const { // Merge options on top of getDefaults() as a safeguard against options with // unset values. - return ClangTidyOptions::getDefaults().merge( - OptionsProvider->getOptions(File), 0); + StringRef Directory = llvm::sys::path::parent_path(File); + auto Iter = CachedDirectoryOptions.find(Directory); + bool Inserted; + if (Iter == CachedDirectoryOptions.end()) { + std::tie(Iter, Inserted) = CachedDirectoryOptions.insert_or_assign( + Directory, ClangTidyOptions::getDefaults().merge( + OptionsProvider->getOptions(File), 0)); + assert(Inserted); + } + return Iter->getValue(); } void ClangTidyContext::setEnableProfiling(bool P) { Profile = P; } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -102,9 +102,7 @@ /// StyleKind, for a given directory. mutable llvm::StringMap NamingStylesCache; FileStyle *MainFileStyle; - ClangTidyContext *const Context; - const std::string CheckName; - const bool GetConfigPerFile; + const bool UsePerFileConfig; const bool IgnoreFailedSplit; }; diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -170,8 +170,8 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context) - : RenamerClangTidyCheck(Name, Context), Context(Context), CheckName(Name), - GetConfigPerFile(Options.get("GetConfigPerFile", true)), + : RenamerClangTidyCheck(Name, Context), + UsePerFileConfig(Options.getLocalOrGlobal("UsePerFileConfig", true)), IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) { auto IterAndInserted = NamingStylesCache.try_emplace( @@ -209,7 +209,7 @@ Options.store(Opts, StyleString, *Styles[I]->Case); } } - Options.store(Opts, "GetConfigPerFile", GetConfigPerFile); + Options.store(Opts, "UsePerFileConfig", UsePerFileConfig); Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit); Options.store(Opts, "IgnoreMainLikeFunctions", MainFileStyle->isIgnoringMainLikeFunction()); @@ -763,17 +763,16 @@ const IdentifierNamingCheck::FileStyle & IdentifierNamingCheck::getStyleForFile(StringRef FileName) const { - if (!GetConfigPerFile) + if (!UsePerFileConfig) return *MainFileStyle; StringRef Parent = llvm::sys::path::parent_path(FileName); auto Iter = NamingStylesCache.find(Parent); if (Iter != NamingStylesCache.end()) return Iter->getValue(); - ClangTidyOptions Options = Context->getOptionsForFile(FileName); - if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) { + if (isCheckEnabledForFile(FileName)) { auto It = NamingStylesCache.try_emplace( - Parent, getFileStyleFromOptions({CheckName, Options.CheckOptions})); + Parent, getFileStyleFromOptions(getOptionsForFile(FileName))); assert(It.second); return It.first->getValue(); } diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" #include "llvm/Support/VirtualFileSystem.h" +#include #include namespace clang { @@ -159,6 +160,13 @@ llvm::StringRef) { if (Opts.Checks && !Opts.Checks->empty()) Opts.Checks->append(DisableList); + + // Force any tidy check that uses UsePreFileConfig to disable it. We only + // care about diagnostics in the main file so looking for configs in other + // files is redundant. + Opts.CheckOptions.insert_or_assign( + "UsePerFileConfig", tidy::ClangTidyOptions::ClangTidyValue( + "false", std::numeric_limits::max())); }; } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -140,7 +140,7 @@ - Improved :doc:`readability-identifier-naming ` check. - Added an option `GetConfigPerFile` to support including files which use + Added an option `UsePerFileConfig` to support including files which use different naming styles. Now renames overridden virtual methods if the method they override has a diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst --- a/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst @@ -51,7 +51,6 @@ - :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`, :option:`EnumIgnoredRegexp` - :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, :option:`EnumConstantSuffix`, :option:`EnumConstantIgnoredRegexp` - :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`, :option:`FunctionIgnoredRegexp` - - :option:`GetConfigPerFile` - :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, :option:`GlobalConstantSuffix`, :option:`GlobalConstantIgnoredRegexp` - :option:`GlobalConstantPointerCase`, :option:`GlobalConstantPointerPrefix`, :option:`GlobalConstantPointerSuffix`, :option:`GlobalConstantPointerIgnoredRegexp` - :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, :option:`GlobalFunctionSuffix`, :option:`GlobalFunctionIgnoredRegexp` @@ -86,6 +85,7 @@ - :option:`TypedefCase`, :option:`TypedefPrefix`, :option:`TypedefSuffix`, :option:`TypedefIgnoredRegexp` - :option:`TypeTemplateParameterCase`, :option:`TypeTemplateParameterPrefix`, :option:`TypeTemplateParameterSuffix`, :option:`TypeTemplateParameterIgnoredRegexp` - :option:`UnionCase`, :option:`UnionPrefix`, :option:`UnionSuffix`, :option:`UnionIgnoredRegexp` + - :option:`UsePerFileConfig` - :option:`ValueTemplateParameterCase`, :option:`ValueTemplateParameterPrefix`, :option:`ValueTemplateParameterSuffix`, :option:`ValueTemplateParameterIgnoredRegexp` - :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`, :option:`VariableIgnoredRegexp` - :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, :option:`VirtualMethodSuffix`, :option:`VirtualMethodIgnoredRegexp` @@ -790,13 +790,6 @@ char pre_my_function_string_post(); -.. option:: GetConfigPerFile - - When `true` the check will look for the configuration for where an - identifier is declared. Useful for when included header files use a - different style. - Default value is `true`. - .. option:: GlobalConstantCase When defined, the check will ensure global constant names conform to the @@ -2210,6 +2203,13 @@ char b; }; +.. option:: UsePerFileConfig + + When `true` the check will look for the configuration for where an + identifier is declared. Useful for when included header files use a + different style. + Default value is `true`. + .. option:: ValueTemplateParameterCase When defined, the check will ensure value template parameter names conform to the diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-multiple-styles.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-multiple-styles.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-multiple-styles.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-multiple-styles.cpp @@ -14,7 +14,7 @@ // RUN: -config='{ InheritParentConfig: true, CheckOptions: [ \ // RUN: {key: readability-identifier-naming.FunctionCase, value: camelBack}, \ // RUN: {key: readability-identifier-naming.ParameterCase, value: CamelCase}, \ -// RUN: {key: readability-identifier-naming.GetConfigPerFile, value: true} \ +// RUN: {key: readability-identifier-naming.UsePerFileConfig, value: true} \ // RUN: ]}' -header-filter='.*' -- -I%theaders // On DISABLED run, everything should be made 'camelBack'. @@ -25,7 +25,7 @@ // RUN: -config='{ InheritParentConfig: false, CheckOptions: [ \ // RUN: {key: readability-identifier-naming.FunctionCase, value: camelBack}, \ // RUN: {key: readability-identifier-naming.ParameterCase, value: CamelCase}, \ -// RUN: {key: readability-identifier-naming.GetConfigPerFile, value: false} \ +// RUN: {key: readability-identifier-naming.UsePerFileConfig, value: false} \ // RUN: ]}' -header-filter='.*' -- -I%theaders #include "global-style1/header.h"