diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -124,19 +124,14 @@ /// Add extra compilation arguments to the start of the list. llvm::Optional ExtraArgsBefore; - /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true - /// and using a FileOptionsProvider, it will take a configuration file in the - /// parent directory (if any exists) and apply this config file on top of the - /// parent one. IF true and using a ConfigOptionsProvider, it will apply this - /// config on top of any configuation file it finds in the directory using the - /// same logic as FileOptionsProvider. If false or missing, only this - /// configuration file will be used. - llvm::Optional InheritParentConfig; - /// Use colors in diagnostics. If missing, it will be auto detected. llvm::Optional UseColor; }; +struct ClangTidyInheritableOptions : public ClangTidyOptions { + bool Inherit = false; +}; + /// Abstract interface for retrieving various ClangTidy options. class ClangTidyOptionsProvider { public: @@ -190,10 +185,14 @@ public: // A pair of configuration file base name and a function parsing // configuration from text in the corresponding format. - typedef std::pair( - llvm::StringRef)>> + typedef std::pair( + llvm::StringRef)>> ConfigFileHandler; + using InheritableOptionsSource = + std::pair; + /// Configuration file handlers listed in the order of priority. /// /// Custom configuration file formats can be supported by constructing the @@ -230,9 +229,10 @@ /// Try to read configuration files from \p Directory using registered /// \c ConfigHandlers. - llvm::Optional tryReadConfigFile(llvm::StringRef Directory); + llvm::Optional + tryReadConfigFile(llvm::StringRef Directory); - llvm::StringMap CachedOptions; + llvm::StringMap CachedOptions; ClangTidyOptions OverrideOptions; ConfigFileHandlers ConfigHandlers; llvm::IntrusiveRefCntPtr FS; @@ -245,13 +245,13 @@ ConfigOptionsProvider( const ClangTidyGlobalOptions &GlobalOptions, const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, + const ClangTidyInheritableOptions &ConfigOptions, const ClangTidyOptions &OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); std::vector getRawOptions(llvm::StringRef FileName) override; private: - ClangTidyOptions ConfigOptions; + ClangTidyInheritableOptions ConfigOptions; }; /// Implementation of the \c ClangTidyOptionsProvider interface, which @@ -309,9 +309,10 @@ std::error_code parseLineFilter(llvm::StringRef LineFilter, ClangTidyGlobalOptions &Options); -/// Parses configuration from JSON and returns \c ClangTidyOptions or an -/// error. -llvm::ErrorOr parseConfiguration(llvm::StringRef Config); +/// Parses configuration from JSON and returns \c ClangTidyOptions and a bool +/// indicating if we should inherit from a parent config or an error. +llvm::ErrorOr +parseConfiguration(llvm::StringRef Config); /// Serializes configuration to a YAML-encoded string. std::string configurationAsText(const ClangTidyOptions &Options); diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -95,11 +95,17 @@ IO.mapOptional("CheckOptions", NOpts->Options); IO.mapOptional("ExtraArgs", Options.ExtraArgs); IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore); - IO.mapOptional("InheritParentConfig", Options.InheritParentConfig); IO.mapOptional("UseColor", Options.UseColor); } }; +template <> struct MappingTraits { + static void mapping(IO &IO, clang::tidy::ClangTidyInheritableOptions &Opts) { + MappingTraits::mapping(IO, Opts); + IO.mapOptional("InheritParentConfig", Opts.Inherit, false); + } +}; + } // namespace yaml } // namespace llvm @@ -197,7 +203,7 @@ ConfigOptionsProvider::ConfigOptionsProvider( const ClangTidyGlobalOptions &GlobalOptions, const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, + const ClangTidyInheritableOptions &ConfigOptions, const ClangTidyOptions &OverrideOptions, llvm::IntrusiveRefCntPtr FS) : FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions, @@ -208,7 +214,7 @@ ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) { std::vector RawOptions = DefaultOptionsProvider::getRawOptions(FileName); - if (ConfigOptions.InheritParentConfig.getValueOr(false)) { + if (ConfigOptions.Inherit) { LLVM_DEBUG(llvm::dbgs() << "Getting options for file " << FileName << "...\n"); assert(FS && "FS must be set."); @@ -255,7 +261,7 @@ StringRef Path = llvm::sys::path::parent_path(AbsolutePath); for (StringRef CurrentPath = Path; !CurrentPath.empty(); CurrentPath = llvm::sys::path::parent_path(CurrentPath)) { - llvm::Optional Result; + llvm::Optional Result; auto Iter = CachedOptions.find(CurrentPath); if (Iter != CachedOptions.end()) @@ -275,8 +281,10 @@ } CachedOptions[Path] = *Result; - CurOptions.push_back(*Result); - if (!Result->first.InheritParentConfig.getValueOr(false)) + bool Inherit = Result->first.Inherit; + + CurOptions.push_back(std::move(*Result)); + if (!Inherit) break; } } @@ -325,7 +333,7 @@ return RawOptions; } -llvm::Optional +llvm::Optional FileOptionsBaseProvider::tryReadConfigFile(StringRef Directory) { assert(!Directory.empty()); @@ -359,7 +367,7 @@ // redirection. if ((*Text)->getBuffer().empty()) continue; - llvm::ErrorOr ParsedOptions = + llvm::ErrorOr ParsedOptions = ConfigHandler.second((*Text)->getBuffer()); if (!ParsedOptions) { if (ParsedOptions.getError()) @@ -367,7 +375,8 @@ << ParsedOptions.getError().message() << "\n"; continue; } - return OptionsSource(*ParsedOptions, std::string(ConfigFile)); + return InheritableOptionsSource(std::move(*ParsedOptions), + std::string(ConfigFile)); } return llvm::None; } @@ -380,9 +389,10 @@ return Input.error(); } -llvm::ErrorOr parseConfiguration(StringRef Config) { +llvm::ErrorOr +parseConfiguration(StringRef Config) { llvm::yaml::Input Input(Config); - ClangTidyOptions Options; + ClangTidyInheritableOptions Options; Input >> Options; if (Input.error()) return Input.error(); diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -314,7 +314,7 @@ auto LoadConfig = [&](StringRef Configuration) -> std::unique_ptr { - llvm::ErrorOr ParsedConfig = + llvm::ErrorOr ParsedConfig = parseConfiguration(Configuration); if (ParsedConfig) return std::make_unique( 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 @@ -31,7 +31,7 @@ *Checks = llvm::join_items(",", *Checks, List); } -static llvm::Optional +static llvm::Optional tryReadConfigFile(llvm::vfs::FileSystem *FS, llvm::StringRef Directory) { assert(!Directory.empty()); // We guaranteed that child directories of Directory exist, so this assert @@ -57,7 +57,7 @@ // redirection. if ((*Text)->getBuffer().empty()) return llvm::None; - llvm::ErrorOr ParsedOptions = + llvm::ErrorOr ParsedOptions = tidy::parseConfiguration((*Text)->getBuffer()); if (!ParsedOptions) { if (ParsedOptions.getError()) @@ -177,7 +177,7 @@ TidyProvider provideClangTidyFiles(ThreadsafeFS &TFS) { return [&TFS](tidy::ClangTidyOptions &Opts, llvm::StringRef Filename) { - llvm::SmallVector OptionStack; + llvm::SmallVector OptionStack; auto FS(TFS.view(llvm::None)); llvm::SmallString<256> AbsolutePath(Filename); @@ -205,7 +205,7 @@ continue; OptionStack.push_back(std::move(*ConfigFile)); // Should we search for a parent config to merge - if (!OptionStack.back().InheritParentConfig.getValueOr(false)) + if (!OptionStack.back().Inherit) break; } unsigned Order = 1U;