forked from OSchip/llvm-project
[clang-tidy] Extend InheritParentConfig to CommandLineConfig
Extend the `InheritParentConfig` support introduced in D75184 for the command line option `--config`. The current behaviour of `--config` is to when set, disable looking for `.clang-tidy` configuration files. This new behaviour lets you set `InheritParentConfig` to true in the command line to then look for `.clang-tidy` configuration files to be merged with what's been specified on the command line. Reviewed By: DmitryPolukhin Differential Revision: https://reviews.llvm.org/D81949
This commit is contained in:
parent
63a3c5925d
commit
4836188ad9
|
@ -194,14 +194,27 @@ ConfigOptionsProvider::ConfigOptionsProvider(
|
|||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &ConfigOptions,
|
||||
const ClangTidyOptions &OverrideOptions)
|
||||
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
|
||||
ConfigOptions(ConfigOptions), OverrideOptions(OverrideOptions) {}
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
|
||||
: FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions,
|
||||
FS),
|
||||
ConfigOptions(ConfigOptions) {}
|
||||
|
||||
std::vector<OptionsSource>
|
||||
ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) {
|
||||
std::vector<OptionsSource> RawOptions =
|
||||
DefaultOptionsProvider::getRawOptions(FileName);
|
||||
if (ConfigOptions.InheritParentConfig.getValueOr(false)) {
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< "Getting options for file " << FileName << "...\n");
|
||||
assert(FS && "FS must be set.");
|
||||
|
||||
llvm::SmallString<128> AbsoluteFilePath(FileName);
|
||||
|
||||
if (!FS->makeAbsolute(AbsoluteFilePath)) {
|
||||
addRawFileOptions(AbsoluteFilePath, RawOptions);
|
||||
}
|
||||
}
|
||||
RawOptions.emplace_back(ConfigOptions,
|
||||
OptionsSourceTypeConfigCommandLineOption);
|
||||
RawOptions.emplace_back(OverrideOptions,
|
||||
|
@ -209,7 +222,7 @@ ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) {
|
|||
return RawOptions;
|
||||
}
|
||||
|
||||
FileOptionsProvider::FileOptionsProvider(
|
||||
FileOptionsBaseProvider::FileOptionsBaseProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
|
@ -221,36 +234,21 @@ FileOptionsProvider::FileOptionsProvider(
|
|||
ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
|
||||
}
|
||||
|
||||
FileOptionsProvider::FileOptionsProvider(
|
||||
FileOptionsBaseProvider::FileOptionsBaseProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
const FileOptionsProvider::ConfigFileHandlers &ConfigHandlers)
|
||||
const FileOptionsBaseProvider::ConfigFileHandlers &ConfigHandlers)
|
||||
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
|
||||
OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {}
|
||||
|
||||
// FIXME: This method has some common logic with clang::format::getStyle().
|
||||
// Consider pulling out common bits to a findParentFileWithName function or
|
||||
// similar.
|
||||
std::vector<OptionsSource>
|
||||
FileOptionsProvider::getRawOptions(StringRef FileName) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Getting options for file " << FileName
|
||||
<< "...\n");
|
||||
assert(FS && "FS must be set.");
|
||||
void FileOptionsBaseProvider::addRawFileOptions(
|
||||
llvm::StringRef AbsolutePath, std::vector<OptionsSource> &CurOptions) {
|
||||
auto CurSize = CurOptions.size();
|
||||
|
||||
llvm::SmallString<128> AbsoluteFilePath(FileName);
|
||||
|
||||
if (FS->makeAbsolute(AbsoluteFilePath))
|
||||
return {};
|
||||
|
||||
std::vector<OptionsSource> RawOptions =
|
||||
DefaultOptionsProvider::getRawOptions(AbsoluteFilePath.str());
|
||||
OptionsSource CommandLineOptions(OverrideOptions,
|
||||
OptionsSourceTypeCheckCommandLineOption);
|
||||
size_t FirstFileConfig = RawOptions.size();
|
||||
// Look for a suitable configuration file in all parent directories of the
|
||||
// file. Start with the immediate parent directory and move up.
|
||||
StringRef Path = llvm::sys::path::parent_path(AbsoluteFilePath.str());
|
||||
StringRef Path = llvm::sys::path::parent_path(AbsolutePath);
|
||||
for (StringRef CurrentPath = Path; !CurrentPath.empty();
|
||||
CurrentPath = llvm::sys::path::parent_path(CurrentPath)) {
|
||||
llvm::Optional<OptionsSource> Result;
|
||||
|
@ -273,21 +271,58 @@ FileOptionsProvider::getRawOptions(StringRef FileName) {
|
|||
}
|
||||
CachedOptions[Path] = *Result;
|
||||
|
||||
RawOptions.push_back(*Result);
|
||||
if (!Result->first.InheritParentConfig ||
|
||||
!*Result->first.InheritParentConfig)
|
||||
CurOptions.push_back(*Result);
|
||||
if (!Result->first.InheritParentConfig.getValueOr(false))
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Reverse order of file configs because closer configs should have higher
|
||||
// priority.
|
||||
std::reverse(RawOptions.begin() + FirstFileConfig, RawOptions.end());
|
||||
std::reverse(CurOptions.begin() + CurSize, CurOptions.end());
|
||||
}
|
||||
|
||||
FileOptionsProvider::FileOptionsProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
|
||||
: FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions,
|
||||
VFS){};
|
||||
|
||||
FileOptionsProvider::FileOptionsProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
const FileOptionsBaseProvider::ConfigFileHandlers &ConfigHandlers)
|
||||
: FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions,
|
||||
ConfigHandlers) {}
|
||||
|
||||
// FIXME: This method has some common logic with clang::format::getStyle().
|
||||
// Consider pulling out common bits to a findParentFileWithName function or
|
||||
// similar.
|
||||
std::vector<OptionsSource>
|
||||
FileOptionsProvider::getRawOptions(StringRef FileName) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Getting options for file " << FileName
|
||||
<< "...\n");
|
||||
assert(FS && "FS must be set.");
|
||||
|
||||
llvm::SmallString<128> AbsoluteFilePath(FileName);
|
||||
|
||||
if (FS->makeAbsolute(AbsoluteFilePath))
|
||||
return {};
|
||||
|
||||
std::vector<OptionsSource> RawOptions =
|
||||
DefaultOptionsProvider::getRawOptions(AbsoluteFilePath.str());
|
||||
addRawFileOptions(AbsoluteFilePath, RawOptions);
|
||||
OptionsSource CommandLineOptions(OverrideOptions,
|
||||
OptionsSourceTypeCheckCommandLineOption);
|
||||
|
||||
RawOptions.push_back(CommandLineOptions);
|
||||
return RawOptions;
|
||||
}
|
||||
|
||||
llvm::Optional<OptionsSource>
|
||||
FileOptionsProvider::tryReadConfigFile(StringRef Directory) {
|
||||
FileOptionsBaseProvider::tryReadConfigFile(StringRef Directory) {
|
||||
assert(!Directory.empty());
|
||||
|
||||
if (!llvm::sys::fs::is_directory(Directory)) {
|
||||
|
|
|
@ -121,10 +121,13 @@ struct ClangTidyOptions {
|
|||
/// Add extra compilation arguments to the start of the list.
|
||||
llvm::Optional<ArgList> ExtraArgsBefore;
|
||||
|
||||
/// Only used in the FileOptionsProvider. If true, FileOptionsProvider will
|
||||
/// take a configuration file in the parent directory (if any exists) and
|
||||
/// apply this config file on top of the parent one. If false or missing,
|
||||
/// only this configuration file will be used.
|
||||
/// 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<bool> InheritParentConfig;
|
||||
|
||||
/// Use colors in diagnostics. If missing, it will be auto detected.
|
||||
|
@ -180,30 +183,7 @@ private:
|
|||
ClangTidyOptions DefaultOptions;
|
||||
};
|
||||
|
||||
/// Implementation of ClangTidyOptions interface, which is used for
|
||||
/// '-config' command-line option.
|
||||
class ConfigOptionsProvider : public DefaultOptionsProvider {
|
||||
public:
|
||||
ConfigOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &ConfigOptions,
|
||||
const ClangTidyOptions &OverrideOptions);
|
||||
std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
|
||||
|
||||
private:
|
||||
ClangTidyOptions ConfigOptions;
|
||||
ClangTidyOptions OverrideOptions;
|
||||
};
|
||||
|
||||
/// Implementation of the \c ClangTidyOptionsProvider interface, which
|
||||
/// tries to find a configuration file in the closest parent directory of each
|
||||
/// source file.
|
||||
///
|
||||
/// By default, files named ".clang-tidy" will be considered, and the
|
||||
/// \c clang::tidy::parseConfiguration function will be used for parsing, but a
|
||||
/// custom set of configuration file names and parsing functions can be
|
||||
/// specified using the appropriate constructor.
|
||||
class FileOptionsProvider : public DefaultOptionsProvider {
|
||||
class FileOptionsBaseProvider : public DefaultOptionsProvider {
|
||||
public:
|
||||
// A pair of configuration file base name and a function parsing
|
||||
// configuration from text in the corresponding format.
|
||||
|
@ -230,6 +210,57 @@ public:
|
|||
/// take precedence over ".clang-tidy" if both reside in the same directory.
|
||||
typedef std::vector<ConfigFileHandler> ConfigFileHandlers;
|
||||
|
||||
FileOptionsBaseProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
|
||||
|
||||
FileOptionsBaseProvider(const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
const ConfigFileHandlers &ConfigHandlers);
|
||||
|
||||
protected:
|
||||
void addRawFileOptions(llvm::StringRef AbsolutePath,
|
||||
std::vector<OptionsSource> &CurOptions);
|
||||
|
||||
/// Try to read configuration files from \p Directory using registered
|
||||
/// \c ConfigHandlers.
|
||||
llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory);
|
||||
|
||||
llvm::StringMap<OptionsSource> CachedOptions;
|
||||
ClangTidyOptions OverrideOptions;
|
||||
ConfigFileHandlers ConfigHandlers;
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
|
||||
};
|
||||
|
||||
/// Implementation of ClangTidyOptions interface, which is used for
|
||||
/// '-config' command-line option.
|
||||
class ConfigOptionsProvider : public FileOptionsBaseProvider {
|
||||
public:
|
||||
ConfigOptionsProvider(
|
||||
const ClangTidyGlobalOptions &GlobalOptions,
|
||||
const ClangTidyOptions &DefaultOptions,
|
||||
const ClangTidyOptions &ConfigOptions,
|
||||
const ClangTidyOptions &OverrideOptions,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
|
||||
std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
|
||||
|
||||
private:
|
||||
ClangTidyOptions ConfigOptions;
|
||||
};
|
||||
|
||||
/// Implementation of the \c ClangTidyOptionsProvider interface, which
|
||||
/// tries to find a configuration file in the closest parent directory of each
|
||||
/// source file.
|
||||
///
|
||||
/// By default, files named ".clang-tidy" will be considered, and the
|
||||
/// \c clang::tidy::parseConfiguration function will be used for parsing, but a
|
||||
/// custom set of configuration file names and parsing functions can be
|
||||
/// specified using the appropriate constructor.
|
||||
class FileOptionsProvider : public FileOptionsBaseProvider {
|
||||
public:
|
||||
/// Initializes the \c FileOptionsProvider instance.
|
||||
///
|
||||
/// \param GlobalOptions are just stored and returned to the caller of
|
||||
|
@ -269,16 +300,6 @@ public:
|
|||
const ConfigFileHandlers &ConfigHandlers);
|
||||
|
||||
std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
|
||||
|
||||
protected:
|
||||
/// Try to read configuration files from \p Directory using registered
|
||||
/// \c ConfigHandlers.
|
||||
llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory);
|
||||
|
||||
llvm::StringMap<OptionsSource> CachedOptions;
|
||||
ClangTidyOptions OverrideOptions;
|
||||
ConfigFileHandlers ConfigHandlers;
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
|
||||
};
|
||||
|
||||
/// Parses LineFilter from JSON and stores it to the \p Options.
|
||||
|
|
|
@ -310,7 +310,7 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
|
|||
return std::make_unique<ConfigOptionsProvider>(
|
||||
GlobalOptions,
|
||||
ClangTidyOptions::getDefaults().mergeWith(DefaultOptions, 0),
|
||||
*ParsedConfig, OverrideOptions);
|
||||
*ParsedConfig, OverrideOptions, std::move(FS));
|
||||
} else {
|
||||
llvm::errs() << "Error: invalid configuration specified.\n"
|
||||
<< ParsedConfig.getError().message() << "\n";
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// RUN: clang-tidy -dump-config %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD4
|
||||
// CHECK-CHILD4: Checks: {{.*}}modernize-loop-convert,modernize-use-using,llvm-qualified-auto
|
||||
// CHECK-CHILD4: - key: llvm-qualified-auto.AddConstToQualified
|
||||
// CHECK-CHILD4-NEXT: value: '1
|
||||
// CHECK-CHILD4-NEXT: value: '1'
|
||||
// CHECK-CHILD4: - key: modernize-loop-convert.MaxCopySize
|
||||
// CHECK-CHILD4-NEXT: value: '20'
|
||||
// CHECK-CHILD4: - key: modernize-loop-convert.MinConfidence
|
||||
|
@ -30,3 +30,23 @@
|
|||
// CHECK-EXPLAIN: 'llvm-qualified-auto' is enabled in the {{.*}}{{[/\\]}}Inputs{{[/\\]}}config-files{{[/\\]}}4{{[/\\]}}44{{[/\\]}}.clang-tidy.
|
||||
// CHECK-EXPLAIN: 'modernize-loop-convert' is enabled in the {{.*}}{{[/\\]}}Inputs{{[/\\]}}config-files{{[/\\]}}4{{[/\\]}}.clang-tidy.
|
||||
// CHECK-EXPLAIN: 'modernize-use-using' is enabled in the {{.*}}{{[/\\]}}Inputs{{[/\\]}}config-files{{[/\\]}}4{{[/\\]}}.clang-tidy.
|
||||
|
||||
// RUN: clang-tidy -dump-config \
|
||||
// RUN: --config='{InheritParentConfig: true, \
|
||||
// RUN: Checks: -llvm-qualified-auto, \
|
||||
// RUN: CheckOptions: [{key: modernize-loop-convert.MaxCopySize, value: 21}]}' \
|
||||
// RUN: %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD5
|
||||
// CHECK-CHILD5: Checks: {{.*}}modernize-loop-convert,modernize-use-using,llvm-qualified-auto,-llvm-qualified-auto
|
||||
// CHECK-CHILD5: - key: modernize-loop-convert.MaxCopySize
|
||||
// CHECK-CHILD5-NEXT: value: '21'
|
||||
// CHECK-CHILD5: - key: modernize-loop-convert.MinConfidence
|
||||
// CHECK-CHILD5-NEXT: value: reasonable
|
||||
// CHECK-CHILD5: - key: modernize-use-using.IgnoreMacros
|
||||
// CHECK-CHILD5-NEXT: value: '0'
|
||||
|
||||
// RUN: clang-tidy -dump-config \
|
||||
// RUN: --config='{InheritParentConfig: false, \
|
||||
// RUN: Checks: -llvm-qualified-auto}' \
|
||||
// RUN: %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD6
|
||||
// CHECK-CHILD6: Checks: {{.*}}-llvm-qualified-auto
|
||||
// CHECK-CHILD6-NOT: - key: modernize-use-using.IgnoreMacros
|
||||
|
|
Loading…
Reference in New Issue