[clang-tools-extra] r267683 - [ClangTidy] Add an 'explain-checks' option to diagnose where each checks comes from.
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 27 02:15:01 PDT 2016
Author: hokein
Date: Wed Apr 27 04:15:01 2016
New Revision: 267683
URL: http://llvm.org/viewvc/llvm-project?rev=267683&view=rev
Log:
[ClangTidy] Add an 'explain-checks' option to diagnose where each checks comes from.
Reviewers: alexfh
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D18694
Added:
clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/
clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/.clang-tidy
clang-tools-extra/trunk/test/clang-tidy/explain-checks.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp
clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h
clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp?rev=267683&r1=267682&r2=267683&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp Wed Apr 27 04:15:01 2016
@@ -23,6 +23,7 @@
using clang::tidy::ClangTidyOptions;
using clang::tidy::FileFilter;
+using OptionsSource = clang::tidy::ClangTidyOptionsProvider::OptionsSource;
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
@@ -151,6 +152,48 @@ ClangTidyOptions::mergeWith(const ClangT
return Result;
}
+const char ClangTidyOptionsProvider::OptionsSourceTypeDefaultBinary[] =
+ "clang-tidy binary";
+const char ClangTidyOptionsProvider::OptionsSourceTypeCheckCommandLineOption[] =
+ "command-line option '-checks'";
+const char
+ ClangTidyOptionsProvider::OptionsSourceTypeConfigCommandLineOption[] =
+ "command-line option '-config'";
+
+ClangTidyOptions
+ClangTidyOptionsProvider::getOptions(llvm::StringRef FileName) {
+ ClangTidyOptions Result;
+ for (const auto &Source : getRawOptions(FileName))
+ Result = Result.mergeWith(Source.first);
+ return Result;
+}
+
+std::vector<OptionsSource>
+DefaultOptionsProvider::getRawOptions(llvm::StringRef FileName) {
+ std::vector<OptionsSource> Result;
+ Result.emplace_back(DefaultOptions, OptionsSourceTypeDefaultBinary);
+ return Result;
+}
+
+ConfigOptionsProvider::ConfigOptionsProvider(
+ const ClangTidyGlobalOptions &GlobalOptions,
+ const ClangTidyOptions &DefaultOptions,
+ const ClangTidyOptions &ConfigOptions,
+ const ClangTidyOptions &OverrideOptions)
+ : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
+ ConfigOptions(ConfigOptions), OverrideOptions(OverrideOptions) {}
+
+std::vector<OptionsSource>
+ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) {
+ std::vector<OptionsSource> RawOptions =
+ DefaultOptionsProvider::getRawOptions(FileName);
+ RawOptions.emplace_back(ConfigOptions,
+ OptionsSourceTypeConfigCommandLineOption);
+ RawOptions.emplace_back(OverrideOptions,
+ OptionsSourceTypeCheckCommandLineOption);
+ return RawOptions;
+}
+
FileOptionsProvider::FileOptionsProvider(
const ClangTidyGlobalOptions &GlobalOptions,
const ClangTidyOptions &DefaultOptions,
@@ -158,7 +201,6 @@ FileOptionsProvider::FileOptionsProvider
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
OverrideOptions(OverrideOptions) {
ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
- CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
}
FileOptionsProvider::FileOptionsProvider(
@@ -168,13 +210,13 @@ FileOptionsProvider::FileOptionsProvider
const FileOptionsProvider::ConfigFileHandlers &ConfigHandlers)
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {
- CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
}
// FIXME: This method has some common logic with clang::format::getStyle().
// Consider pulling out common bits to a findParentFileWithName function or
// similar.
-ClangTidyOptions FileOptionsProvider::getOptions(StringRef FileName) {
+std::vector<OptionsSource>
+FileOptionsProvider::getRawOptions(StringRef FileName) {
DEBUG(llvm::dbgs() << "Getting options for file " << FileName << "...\n");
SmallString<256> FilePath(FileName);
@@ -186,19 +228,23 @@ ClangTidyOptions FileOptionsProvider::ge
FileName = FilePath;
}
+ std::vector<OptionsSource> RawOptions =
+ DefaultOptionsProvider::getRawOptions(FileName);
+ OptionsSource CommandLineOptions(OverrideOptions,
+ OptionsSourceTypeCheckCommandLineOption);
// 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(FileName);
- for (StringRef CurrentPath = Path;;
+ for (StringRef CurrentPath = Path; !CurrentPath.empty();
CurrentPath = llvm::sys::path::parent_path(CurrentPath)) {
- llvm::Optional<ClangTidyOptions> Result;
+ llvm::Optional<OptionsSource> Result;
auto Iter = CachedOptions.find(CurrentPath);
if (Iter != CachedOptions.end())
Result = Iter->second;
if (!Result)
- Result = TryReadConfigFile(CurrentPath);
+ Result = tryReadConfigFile(CurrentPath);
if (Result) {
// Store cached value for all intermediate directories.
@@ -208,13 +254,18 @@ ClangTidyOptions FileOptionsProvider::ge
CachedOptions[Path] = *Result;
Path = llvm::sys::path::parent_path(Path);
}
- return CachedOptions[Path] = *Result;
+ CachedOptions[Path] = *Result;
+
+ RawOptions.push_back(*Result);
+ break;
}
}
+ RawOptions.push_back(CommandLineOptions);
+ return RawOptions;
}
-llvm::Optional<ClangTidyOptions>
-FileOptionsProvider::TryReadConfigFile(StringRef Directory) {
+llvm::Optional<OptionsSource>
+FileOptionsProvider::tryReadConfigFile(StringRef Directory) {
assert(!Directory.empty());
if (!llvm::sys::fs::is_directory(Directory)) {
@@ -255,10 +306,7 @@ FileOptionsProvider::TryReadConfigFile(S
<< ParsedOptions.getError().message() << "\n";
continue;
}
-
- return DefaultOptionsProvider::getOptions(Directory)
- .mergeWith(*ParsedOptions)
- .mergeWith(OverrideOptions);
+ return OptionsSource(*ParsedOptions, ConfigFile.c_str());
}
return llvm::None;
}
Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h?rev=267683&r1=267682&r2=267683&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h Wed Apr 27 04:15:01 2016
@@ -99,14 +99,33 @@ struct ClangTidyOptions {
/// \brief Abstract interface for retrieving various ClangTidy options.
class ClangTidyOptionsProvider {
public:
+ static const char OptionsSourceTypeDefaultBinary[];
+ static const char OptionsSourceTypeCheckCommandLineOption[];
+ static const char OptionsSourceTypeConfigCommandLineOption[];
+
virtual ~ClangTidyOptionsProvider() {}
/// \brief Returns global options, which are independent of the file.
virtual const ClangTidyGlobalOptions &getGlobalOptions() = 0;
+ /// \brief ClangTidyOptions and its source.
+ //
+ /// clang-tidy has 3 types of the sources in order of increasing priority:
+ /// * clang-tidy binary.
+ /// * '-config' commandline option or a specific configuration file. If the
+ /// commandline option is specified, clang-tidy will ignore the
+ /// configuration file.
+ /// * '-checks' commandline option.
+ typedef std::pair<ClangTidyOptions, std::string> OptionsSource;
+
+ /// \brief Returns an ordered vector of OptionsSources, in order of increasing
+ /// priority.
+ virtual std::vector<OptionsSource>
+ getRawOptions(llvm::StringRef FileName) = 0;
+
/// \brief Returns options applying to a specific translation unit with the
/// specified \p FileName.
- virtual ClangTidyOptions getOptions(llvm::StringRef FileName) = 0;
+ ClangTidyOptions getOptions(llvm::StringRef FileName);
};
/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which
@@ -119,15 +138,28 @@ public:
const ClangTidyGlobalOptions &getGlobalOptions() override {
return GlobalOptions;
}
- ClangTidyOptions getOptions(llvm::StringRef /*FileName*/) override {
- return DefaultOptions;
- }
+ std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
private:
ClangTidyGlobalOptions GlobalOptions;
ClangTidyOptions DefaultOptions;
};
+/// \brief 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;
+};
+
/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which
/// tries to find a configuration file in the closest parent directory of each
/// source file.
@@ -198,14 +230,14 @@ public:
const ClangTidyOptions &OverrideOptions,
const ConfigFileHandlers &ConfigHandlers);
- ClangTidyOptions getOptions(llvm::StringRef FileName) override;
+ std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
protected:
/// \brief Try to read configuration files from \p Directory using registered
/// \c ConfigHandlers.
- llvm::Optional<ClangTidyOptions> TryReadConfigFile(llvm::StringRef Directory);
+ llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory);
- llvm::StringMap<ClangTidyOptions> CachedOptions;
+ llvm::StringMap<OptionsSource> CachedOptions;
ClangTidyOptions OverrideOptions;
ConfigFileHandlers ConfigHandlers;
};
Modified: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp?rev=267683&r1=267682&r2=267683&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp Wed Apr 27 04:15:01 2016
@@ -128,6 +128,12 @@ List all enabled checks and exit. Use wi
)"),
cl::init(false), cl::cat(ClangTidyCategory));
+static cl::opt<bool> ExplainConfig("explain-config", cl::desc(R"(
+for each enabled check explains, where it is enabled, i.e. in clang-tidy binary,
+command line or a specific configuration file.
+)"),
+ cl::init(false), cl::cat(ClangTidyCategory));
+
static cl::opt<std::string> Config("config", cl::desc(R"(
Specifies a configuration in YAML/JSON format:
-config="{Checks: '*',
@@ -280,11 +286,10 @@ static std::unique_ptr<ClangTidyOptionsP
if (!Config.empty()) {
if (llvm::ErrorOr<ClangTidyOptions> ParsedConfig =
parseConfiguration(Config)) {
- return llvm::make_unique<DefaultOptionsProvider>(
- GlobalOptions, ClangTidyOptions::getDefaults()
- .mergeWith(DefaultOptions)
- .mergeWith(*ParsedConfig)
- .mergeWith(OverrideOptions));
+ return llvm::make_unique<ConfigOptionsProvider>(
+ GlobalOptions,
+ ClangTidyOptions::getDefaults().mergeWith(DefaultOptions),
+ *ParsedConfig, OverrideOptions);
} else {
llvm::errs() << "Error: invalid configuration specified.\n"
<< ParsedConfig.getError().message() << "\n";
@@ -311,6 +316,22 @@ static int clangTidyMain(int argc, const
ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FileName);
std::vector<std::string> EnabledChecks = getCheckNames(EffectiveOptions);
+ if (ExplainConfig) {
+ //FIXME: Show other ClangTidyOptions' fields, like ExtraArg.
+ std::vector<clang::tidy::ClangTidyOptionsProvider::OptionsSource>
+ RawOptions = OptionsProvider->getRawOptions(FileName);
+ for (const std::string &Check : EnabledChecks) {
+ for (auto It = RawOptions.rbegin(); It != RawOptions.rend(); ++It) {
+ if (It->first.Checks && GlobList(*It->first.Checks).contains(Check)) {
+ llvm::outs() << "'" << Check << "' is enabled in the " << It->second
+ << ".\n";
+ break;
+ }
+ }
+ }
+ return 0;
+ }
+
if (ListChecks) {
llvm::outs() << "Enabled checks:";
for (auto CheckName : EnabledChecks)
Added: clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/.clang-tidy
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/.clang-tidy?rev=267683&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/.clang-tidy (added)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/explain-config/.clang-tidy Wed Apr 27 04:15:01 2016
@@ -0,0 +1 @@
+Checks: '-*,modernize-use-nullptr'
Added: clang-tools-extra/trunk/test/clang-tidy/explain-checks.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/explain-checks.cpp?rev=267683&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/explain-checks.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/explain-checks.cpp Wed Apr 27 04:15:01 2016
@@ -0,0 +1,14 @@
+// RUN: clang-tidy -checks=-*,modernize-use-nullptr -explain-config | FileCheck --check-prefix=CHECK-MESSAGE1 %s
+// RUN: clang-tidy -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE2 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE3 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,-modernize-use-nullptr'}" %S/Inputs/explain-config/a.cc -explain-config | FileCheck --check-prefix=CHECK-MESSAGE4 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-*'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE5 %s
+// RUN: clang-tidy -config="{Checks: 'modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE6 %s
+// RUN: clang-tidy -explain-config %S/Inputs/explain-config/a.cc | grep "'modernize-use-nullptr' is enabled in the %S/Inputs/explain-config/.clang-tidy."
+
+// CHECK-MESSAGE1: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE2: 'modernize-use-nullptr' is enabled in the command-line option '-config'.
+// CHECK-MESSAGE3: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE4: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE5: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE6: 'clang-analyzer-unix.API' is enabled in the clang-tidy binary.
More information about the cfe-commits
mailing list