Implemented clang-tidy-check-specific options.
Summary: Each check can implement readOptions and storeOptions methods to read and store custom options. Each check's options are stored in a local namespace to avoid name collisions and provide some sort of context to the user. Reviewers: bkramer, klimek Reviewed By: klimek Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D5296 llvm-svn: 217661
This commit is contained in:
parent
313f5e2f29
commit
6e0cbc8947
|
@ -214,13 +214,11 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
|
||||||
Context.setASTContext(&Compiler.getASTContext());
|
Context.setASTContext(&Compiler.getASTContext());
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
|
||||||
GlobList &Filter = Context.getChecksFilter();
|
CheckFactories->createChecks(&Context, Checks);
|
||||||
CheckFactories->createChecks(Filter, Checks);
|
|
||||||
|
|
||||||
std::unique_ptr<ast_matchers::MatchFinder> Finder(
|
std::unique_ptr<ast_matchers::MatchFinder> Finder(
|
||||||
new ast_matchers::MatchFinder);
|
new ast_matchers::MatchFinder);
|
||||||
for (auto &Check : Checks) {
|
for (auto &Check : Checks) {
|
||||||
Check->setContext(&Context);
|
|
||||||
Check->registerMatchers(&*Finder);
|
Check->registerMatchers(&*Finder);
|
||||||
Check->registerPPCallbacks(Compiler);
|
Check->registerPPCallbacks(Compiler);
|
||||||
}
|
}
|
||||||
|
@ -235,6 +233,7 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
|
||||||
AnalyzerOptions->Config["cfg-temporary-dtors"] =
|
AnalyzerOptions->Config["cfg-temporary-dtors"] =
|
||||||
Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false";
|
Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false";
|
||||||
|
|
||||||
|
GlobList &Filter = Context.getChecksFilter();
|
||||||
AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter);
|
AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter);
|
||||||
if (!AnalyzerOptions->CheckersControlList.empty()) {
|
if (!AnalyzerOptions->CheckersControlList.empty()) {
|
||||||
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
|
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
|
||||||
|
@ -251,9 +250,9 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
|
||||||
std::move(Consumers), std::move(Finder), std::move(Checks));
|
std::move(Consumers), std::move(Finder), std::move(Checks));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
|
||||||
ClangTidyASTConsumerFactory::getCheckNames(GlobList &Filter) {
|
|
||||||
std::vector<std::string> CheckNames;
|
std::vector<std::string> CheckNames;
|
||||||
|
GlobList &Filter = Context.getChecksFilter();
|
||||||
for (const auto &CheckFactory : *CheckFactories) {
|
for (const auto &CheckFactory : *CheckFactories) {
|
||||||
if (Filter.contains(CheckFactory.first))
|
if (Filter.contains(CheckFactory.first))
|
||||||
CheckNames.push_back(CheckFactory.first);
|
CheckNames.push_back(CheckFactory.first);
|
||||||
|
@ -266,6 +265,15 @@ ClangTidyASTConsumerFactory::getCheckNames(GlobList &Filter) {
|
||||||
return CheckNames;
|
return CheckNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
|
||||||
|
ClangTidyOptions::OptionMap Options;
|
||||||
|
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
|
||||||
|
CheckFactories->createChecks(&Context, Checks);
|
||||||
|
for (const auto &Check : Checks)
|
||||||
|
Check->storeOptions(Options);
|
||||||
|
return Options;
|
||||||
|
}
|
||||||
|
|
||||||
ClangTidyASTConsumerFactory::CheckersList
|
ClangTidyASTConsumerFactory::CheckersList
|
||||||
ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) {
|
ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) {
|
||||||
CheckersList List;
|
CheckersList List;
|
||||||
|
@ -307,9 +315,25 @@ void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
|
||||||
check(Result);
|
check(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangTidyCheck::setName(StringRef Name) {
|
OptionsView::OptionsView(StringRef CheckName,
|
||||||
assert(CheckName.empty());
|
const ClangTidyOptions::OptionMap &CheckOptions)
|
||||||
CheckName = Name.str();
|
: NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
|
||||||
|
|
||||||
|
std::string OptionsView::get(StringRef LocalName, std::string Default) const {
|
||||||
|
const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
|
||||||
|
if (Iter != CheckOptions.end())
|
||||||
|
return Iter->second;
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsView::store(ClangTidyOptions::OptionMap &Options,
|
||||||
|
StringRef LocalName, StringRef Value) const {
|
||||||
|
Options[NamePrefix + LocalName.str()] = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsView::store(ClangTidyOptions::OptionMap &Options,
|
||||||
|
StringRef LocalName, int64_t Value) const {
|
||||||
|
store(Options, LocalName, llvm::itostr(Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
|
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
|
||||||
|
@ -317,7 +341,15 @@ std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
|
||||||
llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
|
llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
|
||||||
Options));
|
Options));
|
||||||
ClangTidyASTConsumerFactory Factory(Context);
|
ClangTidyASTConsumerFactory Factory(Context);
|
||||||
return Factory.getCheckNames(Context.getChecksFilter());
|
return Factory.getCheckNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options) {
|
||||||
|
clang::tidy::ClangTidyContext Context(
|
||||||
|
llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
|
||||||
|
Options));
|
||||||
|
ClangTidyASTConsumerFactory Factory(Context);
|
||||||
|
return Factory.getCheckOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangTidyStats
|
ClangTidyStats
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Tooling/Refactoring.h"
|
#include "clang/Tooling/Refactoring.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
@ -28,6 +31,55 @@ class CompilationDatabase;
|
||||||
|
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
|
||||||
|
/// \brief Provides access to the \c ClangTidyCheck options via check-local
|
||||||
|
/// names.
|
||||||
|
///
|
||||||
|
/// Methods of this class prepend <tt>CheckName + "."</tt> to translate
|
||||||
|
/// check-local option names to global option names.
|
||||||
|
class OptionsView {
|
||||||
|
public:
|
||||||
|
/// \brief Initializes the instance using \p CheckName + "." as a prefix.
|
||||||
|
OptionsView(StringRef CheckName,
|
||||||
|
const ClangTidyOptions::OptionMap &CheckOptions);
|
||||||
|
|
||||||
|
/// \brief Read a named option from the \c Context.
|
||||||
|
///
|
||||||
|
/// Reads the option with the check-local name \p LocalName from the
|
||||||
|
/// \c CheckOptions. If the corresponding key is not present, returns
|
||||||
|
/// \p Default.
|
||||||
|
std::string get(StringRef LocalName, std::string Default) const;
|
||||||
|
|
||||||
|
/// \brief Read a named option from the \c Context and parse it as an integral
|
||||||
|
/// type \c T.
|
||||||
|
///
|
||||||
|
/// Reads the option with the check-local name \p LocalName from the
|
||||||
|
/// \c CheckOptions. If the corresponding key is not present, returns
|
||||||
|
/// \p Default.
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||||
|
get(StringRef LocalName, T Default) const {
|
||||||
|
std::string Value = get(LocalName, "");
|
||||||
|
T Result = Default;
|
||||||
|
if (!Value.empty())
|
||||||
|
StringRef(Value).getAsInteger(10, Result);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Stores an option with the check-local name \p LocalName with string
|
||||||
|
/// value \p Value to \p Options.
|
||||||
|
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
|
||||||
|
StringRef Value) const;
|
||||||
|
|
||||||
|
/// \brief Stores an option with the check-local name \p LocalName with
|
||||||
|
/// \c int64_t value \p Value to \p Options.
|
||||||
|
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
|
||||||
|
int64_t Value) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string NamePrefix;
|
||||||
|
const ClangTidyOptions::OptionMap &CheckOptions;
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief Base class for all clang-tidy checks.
|
/// \brief Base class for all clang-tidy checks.
|
||||||
///
|
///
|
||||||
/// To implement a \c ClangTidyCheck, write a subclass and overwrite some of the
|
/// To implement a \c ClangTidyCheck, write a subclass and overwrite some of the
|
||||||
|
@ -49,6 +101,18 @@ namespace tidy {
|
||||||
/// useful/necessary.
|
/// useful/necessary.
|
||||||
class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
|
class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
|
/// \brief Initializes the check with \p CheckName and \p Context.
|
||||||
|
///
|
||||||
|
/// Derived classes must implement the constructor with this signature or
|
||||||
|
/// delegate it. If a check needs to read options, it can do this in the
|
||||||
|
/// constructor using the Options.get() methods below.
|
||||||
|
ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
|
||||||
|
: CheckName(CheckName), Context(Context),
|
||||||
|
Options(CheckName, Context->getOptions().CheckOptions) {
|
||||||
|
assert(Context != nullptr);
|
||||||
|
assert(!CheckName.empty());
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~ClangTidyCheck() {}
|
virtual ~ClangTidyCheck() {}
|
||||||
|
|
||||||
/// \brief Overwrite this to register \c PPCallbacks with \c Compiler.
|
/// \brief Overwrite this to register \c PPCallbacks with \c Compiler.
|
||||||
|
@ -75,21 +139,24 @@ public:
|
||||||
/// work in here.
|
/// work in here.
|
||||||
virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
|
virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
|
||||||
|
|
||||||
/// \brief The infrastructure sets the context to \p Ctx with this function.
|
|
||||||
void setContext(ClangTidyContext *Ctx) { Context = Ctx; }
|
|
||||||
|
|
||||||
/// \brief Add a diagnostic with the check's name.
|
/// \brief Add a diagnostic with the check's name.
|
||||||
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
|
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
|
||||||
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
|
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
|
||||||
|
|
||||||
/// \brief Sets the check name. Intended to be used by the clang-tidy
|
/// \brief Should store all options supported by this check with their
|
||||||
/// framework. Can be called only once.
|
/// current values or default values for options that haven't been overridden.
|
||||||
void setName(StringRef Name);
|
///
|
||||||
|
/// The check should use \c Options.store() to store each option it supports
|
||||||
|
/// whether it has the default value or it has been overridden.
|
||||||
|
virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
ClangTidyContext *Context;
|
|
||||||
std::string CheckName;
|
std::string CheckName;
|
||||||
|
ClangTidyContext *Context;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OptionsView Options;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangTidyCheckFactories;
|
class ClangTidyCheckFactories;
|
||||||
|
@ -103,10 +170,13 @@ public:
|
||||||
CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
|
CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
|
||||||
|
|
||||||
/// \brief Get the list of enabled checks.
|
/// \brief Get the list of enabled checks.
|
||||||
std::vector<std::string> getCheckNames(GlobList &Filter);
|
std::vector<std::string> getCheckNames();
|
||||||
|
|
||||||
|
/// \brief Get the union of options from all checks.
|
||||||
|
ClangTidyOptions::OptionMap getCheckOptions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<std::pair<std::string, bool> > CheckersList;
|
typedef std::vector<std::pair<std::string, bool>> CheckersList;
|
||||||
CheckersList getCheckersControlList(GlobList &Filter);
|
CheckersList getCheckersControlList(GlobList &Filter);
|
||||||
|
|
||||||
ClangTidyContext &Context;
|
ClangTidyContext &Context;
|
||||||
|
@ -117,6 +187,14 @@ private:
|
||||||
/// filters are applied.
|
/// filters are applied.
|
||||||
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
|
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
|
||||||
|
|
||||||
|
/// \brief Returns the effective check-specific options.
|
||||||
|
///
|
||||||
|
/// The method configures ClangTidy with the specified \p Options and collects
|
||||||
|
/// effective options from all created checks. The returned set of options
|
||||||
|
/// includes default check-specific options for all keys not overridden by \p
|
||||||
|
/// Options.
|
||||||
|
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options);
|
||||||
|
|
||||||
/// \brief Run a set of clang-tidy checks on a set of files.
|
/// \brief Run a set of clang-tidy checks on a set of files.
|
||||||
ClangTidyStats
|
ClangTidyStats
|
||||||
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
|
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
|
||||||
|
|
|
@ -16,19 +16,18 @@
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
|
||||||
void ClangTidyCheckFactories::registerCheckFactory(
|
void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
|
||||||
StringRef Name, std::function<ClangTidyCheck *()> Factory) {
|
CheckFactory Factory) {
|
||||||
Factories[Name] = Factory;
|
Factories[Name] = Factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangTidyCheckFactories::createChecks(
|
void ClangTidyCheckFactories::createChecks(
|
||||||
GlobList &Filter, std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
|
ClangTidyContext *Context,
|
||||||
|
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
|
||||||
|
GlobList &Filter = Context->getChecksFilter();
|
||||||
for (const auto &Factory : Factories) {
|
for (const auto &Factory : Factories) {
|
||||||
if (Filter.contains(Factory.first)) {
|
if (Filter.contains(Factory.first))
|
||||||
ClangTidyCheck *Check = Factory.second();
|
Checks.emplace_back(Factory.second(Factory.first, Context));
|
||||||
Check->setName(Factory.first);
|
|
||||||
Checks.emplace_back(Check);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,13 @@ namespace tidy {
|
||||||
/// this object.
|
/// this object.
|
||||||
class ClangTidyCheckFactories {
|
class ClangTidyCheckFactories {
|
||||||
public:
|
public:
|
||||||
|
typedef std::function<ClangTidyCheck *(
|
||||||
|
StringRef Name, ClangTidyContext *Context)> CheckFactory;
|
||||||
|
|
||||||
/// \brief Registers check \p Factory with name \p Name.
|
/// \brief Registers check \p Factory with name \p Name.
|
||||||
///
|
///
|
||||||
/// For all checks that have default constructors, use \c registerCheck.
|
/// For all checks that have default constructors, use \c registerCheck.
|
||||||
void registerCheckFactory(StringRef Name,
|
void registerCheckFactory(StringRef Name, CheckFactory Factory);
|
||||||
std::function<ClangTidyCheck *()> Factory);
|
|
||||||
|
|
||||||
/// \brief Registers the \c CheckType with the name \p Name.
|
/// \brief Registers the \c CheckType with the name \p Name.
|
||||||
///
|
///
|
||||||
|
@ -53,19 +55,21 @@ public:
|
||||||
/// }
|
/// }
|
||||||
/// };
|
/// };
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename CheckType>
|
template <typename CheckType> void registerCheck(StringRef CheckName) {
|
||||||
void registerCheck(StringRef Name) {
|
registerCheckFactory(CheckName,
|
||||||
registerCheckFactory(Name, []() { return new CheckType(); });
|
[](StringRef Name, ClangTidyContext *Context) {
|
||||||
|
return new CheckType(Name, Context);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Create instances of all checks matching \p CheckRegexString and
|
/// \brief Create instances of all checks matching \p CheckRegexString and
|
||||||
/// store them in \p Checks.
|
/// store them in \p Checks.
|
||||||
///
|
///
|
||||||
/// The caller takes ownership of the return \c ClangTidyChecks.
|
/// The caller takes ownership of the return \c ClangTidyChecks.
|
||||||
void createChecks(GlobList &Filter,
|
void createChecks(ClangTidyContext *Context,
|
||||||
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
|
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
|
||||||
|
|
||||||
typedef std::map<std::string, std::function<ClangTidyCheck *()>> FactoryMap;
|
typedef std::map<std::string, CheckFactory> FactoryMap;
|
||||||
FactoryMap::const_iterator begin() const { return Factories.begin(); }
|
FactoryMap::const_iterator begin() const { return Factories.begin(); }
|
||||||
FactoryMap::const_iterator end() const { return Factories.end(); }
|
FactoryMap::const_iterator end() const { return Factories.end(); }
|
||||||
bool empty() const { return Factories.empty(); }
|
bool empty() const { return Factories.empty(); }
|
||||||
|
|
|
@ -25,6 +25,7 @@ using clang::tidy::FileFilter;
|
||||||
|
|
||||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
|
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
|
||||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
|
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
|
||||||
|
LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair);
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
@ -57,11 +58,34 @@ template <> struct MappingTraits<FileFilter> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct MappingTraits<ClangTidyOptions::StringPair> {
|
||||||
|
static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) {
|
||||||
|
IO.mapRequired("key", KeyValue.first);
|
||||||
|
IO.mapRequired("value", KeyValue.second);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NOptionMap {
|
||||||
|
NOptionMap(IO &) {}
|
||||||
|
NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
|
||||||
|
: Options(OptionMap.begin(), OptionMap.end()) {}
|
||||||
|
ClangTidyOptions::OptionMap denormalize(IO &) {
|
||||||
|
ClangTidyOptions::OptionMap Map;
|
||||||
|
for (const auto &KeyValue : Options)
|
||||||
|
Map[KeyValue.first] = KeyValue.second;
|
||||||
|
return Map;
|
||||||
|
}
|
||||||
|
std::vector<ClangTidyOptions::StringPair> Options;
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct MappingTraits<ClangTidyOptions> {
|
template <> struct MappingTraits<ClangTidyOptions> {
|
||||||
static void mapping(IO &IO, ClangTidyOptions &Options) {
|
static void mapping(IO &IO, ClangTidyOptions &Options) {
|
||||||
|
MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
|
||||||
|
IO, Options.CheckOptions);
|
||||||
IO.mapOptional("Checks", Options.Checks);
|
IO.mapOptional("Checks", Options.Checks);
|
||||||
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
|
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
|
||||||
IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
|
IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
|
||||||
|
IO.mapOptional("CheckOptions", NOpts->Options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,6 +109,10 @@ ClangTidyOptions::mergeWith(const ClangTidyOptions &Other) const {
|
||||||
Result.HeaderFilterRegex = Other.HeaderFilterRegex;
|
Result.HeaderFilterRegex = Other.HeaderFilterRegex;
|
||||||
if (Other.AnalyzeTemporaryDtors)
|
if (Other.AnalyzeTemporaryDtors)
|
||||||
Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors;
|
Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors;
|
||||||
|
|
||||||
|
for (const auto &KeyValue : Other.CheckOptions)
|
||||||
|
Result.CheckOptions[KeyValue.first] = KeyValue.second;
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +197,10 @@ FileOptionsProvider::TryReadConfigFile(StringRef Directory) {
|
||||||
llvm::MemoryBuffer::getFile(ConfigFile.c_str());
|
llvm::MemoryBuffer::getFile(ConfigFile.c_str());
|
||||||
if (std::error_code EC = Text.getError())
|
if (std::error_code EC = Text.getError())
|
||||||
return EC;
|
return EC;
|
||||||
|
// Skip empty files, e.g. files opened for writing via shell output
|
||||||
|
// redirection.
|
||||||
|
if ((*Text)->getBuffer().empty())
|
||||||
|
return make_error_code(llvm::errc::no_such_file_or_directory);
|
||||||
if (std::error_code EC = parseConfiguration((*Text)->getBuffer(), Options))
|
if (std::error_code EC = parseConfiguration((*Text)->getBuffer(), Options))
|
||||||
return EC;
|
return EC;
|
||||||
return Options.mergeWith(OverrideOptions);
|
return Options.mergeWith(OverrideOptions);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/ErrorOr.h"
|
#include "llvm/Support/ErrorOr.h"
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -70,6 +71,12 @@ struct ClangTidyOptions {
|
||||||
|
|
||||||
/// \brief Turns on temporary destructor-based analysis.
|
/// \brief Turns on temporary destructor-based analysis.
|
||||||
llvm::Optional<bool> AnalyzeTemporaryDtors;
|
llvm::Optional<bool> AnalyzeTemporaryDtors;
|
||||||
|
|
||||||
|
typedef std::pair<std::string, std::string> StringPair;
|
||||||
|
typedef std::map<std::string, std::string> OptionMap;
|
||||||
|
|
||||||
|
/// \brief Key-value mapping used to store check-specific options.
|
||||||
|
OptionMap CheckOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Abstract interface for retrieving various ClangTidy options.
|
/// \brief Abstract interface for retrieving various ClangTidy options.
|
||||||
|
|
|
@ -26,6 +26,8 @@ namespace readability {
|
||||||
/// ones generated by -Wold-style-cast.
|
/// ones generated by -Wold-style-cast.
|
||||||
class AvoidCStyleCastsCheck : public ClangTidyCheck {
|
class AvoidCStyleCastsCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace tidy {
|
||||||
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Explicit_Constructors
|
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Explicit_Constructors
|
||||||
class ExplicitConstructorCheck : public ClangTidyCheck {
|
class ExplicitConstructorCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace build {
|
||||||
/// Corresponding cpplint.py check name: 'build/explicit_make_pair'.
|
/// Corresponding cpplint.py check name: 'build/explicit_make_pair'.
|
||||||
class ExplicitMakePairCheck : public ClangTidyCheck {
|
class ExplicitMakePairCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,9 +21,9 @@ namespace runtime {
|
||||||
/// Correspondig cpplint.py check: runtime/int.
|
/// Correspondig cpplint.py check: runtime/int.
|
||||||
class IntegerTypesCheck : public ClangTidyCheck {
|
class IntegerTypesCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
IntegerTypesCheck()
|
IntegerTypesCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
: UnsignedTypePrefix("uint"), SignedTypePrefix("int"),
|
: ClangTidyCheck(Name, Context), UnsignedTypePrefix("uint"),
|
||||||
AddUnderscoreT(false) {}
|
SignedTypePrefix("int"), AddUnderscoreT(false) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace runtime {
|
||||||
/// Corresponding cpplint.py check name: 'runtime/memset'.
|
/// Corresponding cpplint.py check name: 'runtime/memset'.
|
||||||
class MemsetZeroLengthCheck : public ClangTidyCheck {
|
class MemsetZeroLengthCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
MemsetZeroLengthCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace readability {
|
||||||
/// Corresponding cpplint.py check name: 'readability/function'.
|
/// Corresponding cpplint.py check name: 'readability/function'.
|
||||||
class NamedParameterCheck : public ClangTidyCheck {
|
class NamedParameterCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
NamedParameterCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace runtime {
|
||||||
/// Corresponding cpplint.py check name: 'runtime/operator'.
|
/// Corresponding cpplint.py check name: 'runtime/operator'.
|
||||||
class OverloadedUnaryAndCheck : public ClangTidyCheck {
|
class OverloadedUnaryAndCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
OverloadedUnaryAndCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace runtime {
|
||||||
/// Corresponding cpplint.py check name: 'runtime/member_string_reference'.
|
/// Corresponding cpplint.py check name: 'runtime/member_string_reference'.
|
||||||
class StringReferenceMemberCheck : public ClangTidyCheck {
|
class StringReferenceMemberCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
StringReferenceMemberCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace build {
|
||||||
/// Corresponding cpplint.py check name: 'build/namespaces'.
|
/// Corresponding cpplint.py check name: 'build/namespaces'.
|
||||||
class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck {
|
class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
UnnamedNamespaceInHeaderCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace build {
|
||||||
/// Corresponding cpplint.py check name: 'build/namespaces'.
|
/// Corresponding cpplint.py check name: 'build/namespaces'.
|
||||||
class UsingNamespaceDirectiveCheck : public ClangTidyCheck {
|
class UsingNamespaceDirectiveCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace tidy {
|
||||||
/// Finds and fixes header guards that do not adhere to LLVM style.
|
/// Finds and fixes header guards that do not adhere to LLVM style.
|
||||||
class LLVMHeaderGuardCheck : public HeaderGuardCheck {
|
class LLVMHeaderGuardCheck : public HeaderGuardCheck {
|
||||||
public:
|
public:
|
||||||
|
LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: HeaderGuardCheck(Name, Context) {}
|
||||||
bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
|
bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
|
||||||
bool shouldFixHeaderGuard(StringRef Filename) override;
|
bool shouldFixHeaderGuard(StringRef Filename) override;
|
||||||
std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
|
std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace tidy {
|
||||||
/// see: http://llvm.org/docs/CodingStandards.html#include-style
|
/// see: http://llvm.org/docs/CodingStandards.html#include-style
|
||||||
class IncludeOrderCheck : public ClangTidyCheck {
|
class IncludeOrderCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
IncludeOrderCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerPPCallbacks(CompilerInstance &Compiler) override;
|
void registerPPCallbacks(CompilerInstance &Compiler) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,26 @@
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||||
#include "clang/Lex/Lexer.h"
|
#include "clang/Lex/Lexer.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
|
|
||||||
using namespace clang::ast_matchers;
|
using namespace clang::ast_matchers;
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
|
||||||
NamespaceCommentCheck::NamespaceCommentCheck()
|
NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
|
||||||
: NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
|
ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context),
|
||||||
|
NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
|
||||||
"namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$",
|
"namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$",
|
||||||
llvm::Regex::IgnoreCase),
|
llvm::Regex::IgnoreCase),
|
||||||
ShortNamespaceLines(1) {}
|
ShortNamespaceLines(Options.get("ShortNamespaceLines", 1u)),
|
||||||
|
SpacesBeforeComments(Options.get("SpacesBeforeComments", 1u)) {}
|
||||||
|
|
||||||
|
void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||||
|
Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines);
|
||||||
|
Options.store(Opts, "SpacesBeforeComments", SpacesBeforeComments);
|
||||||
|
}
|
||||||
|
|
||||||
void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
|
void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
Finder->addMatcher(namespaceDecl().bind("namespace"), this);
|
Finder->addMatcher(namespaceDecl().bind("namespace"), this);
|
||||||
|
@ -36,10 +42,12 @@ bool locationsInSameFile(const SourceManager &Sources, SourceLocation Loc1,
|
||||||
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
|
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak) {
|
std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak,
|
||||||
|
unsigned SpacesBeforeComments) {
|
||||||
std::string Fix = "// namespace";
|
std::string Fix = "// namespace";
|
||||||
if (!ND->isAnonymousNamespace())
|
if (!ND->isAnonymousNamespace())
|
||||||
Fix.append(" ").append(ND->getNameAsString());
|
Fix.append(std::string(SpacesBeforeComments, ' '))
|
||||||
|
.append(ND->getNameAsString());
|
||||||
if (InsertLineBreak)
|
if (InsertLineBreak)
|
||||||
Fix.append("\n");
|
Fix.append("\n");
|
||||||
return Fix;
|
return Fix;
|
||||||
|
@ -97,7 +105,8 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
|
||||||
diag(Loc, "namespace closing comment refers to a wrong namespace '%0'")
|
diag(Loc, "namespace closing comment refers to a wrong namespace '%0'")
|
||||||
<< NamespaceNameInComment
|
<< NamespaceNameInComment
|
||||||
<< FixItHint::CreateReplacement(
|
<< FixItHint::CreateReplacement(
|
||||||
OldCommentRange, getNamespaceComment(ND, NeedLineBreak));
|
OldCommentRange,
|
||||||
|
getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +119,8 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
|
||||||
|
|
||||||
diag(ND->getLocation(), "namespace not terminated with a closing comment")
|
diag(ND->getLocation(), "namespace not terminated with a closing comment")
|
||||||
<< FixItHint::CreateInsertion(
|
<< FixItHint::CreateInsertion(
|
||||||
AfterRBrace, " " + getNamespaceComment(ND, NeedLineBreak));
|
AfterRBrace,
|
||||||
|
" " + getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tidy
|
} // namespace tidy
|
||||||
|
|
|
@ -21,13 +21,16 @@ namespace tidy {
|
||||||
/// see: http://llvm.org/docs/CodingStandards.html#namespace-indentation
|
/// see: http://llvm.org/docs/CodingStandards.html#namespace-indentation
|
||||||
class NamespaceCommentCheck : public ClangTidyCheck {
|
class NamespaceCommentCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
NamespaceCommentCheck();
|
NamespaceCommentCheck(StringRef Name, ClangTidyContext *Context);
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void storeOptions(ClangTidyOptions::OptionMap &Options) override;
|
||||||
|
|
||||||
llvm::Regex NamespaceCommentPattern;
|
llvm::Regex NamespaceCommentPattern;
|
||||||
const unsigned ShortNamespaceLines;
|
const unsigned ShortNamespaceLines;
|
||||||
|
const unsigned SpacesBeforeComments;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tidy
|
} // namespace tidy
|
||||||
|
|
|
@ -17,8 +17,6 @@ using namespace clang::ast_matchers;
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
|
||||||
TwineLocalCheck::TwineLocalCheck() {}
|
|
||||||
|
|
||||||
void TwineLocalCheck::registerMatchers(MatchFinder *Finder) {
|
void TwineLocalCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
auto TwineType =
|
auto TwineType =
|
||||||
qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine"))));
|
qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine"))));
|
||||||
|
|
|
@ -19,7 +19,8 @@ namespace tidy {
|
||||||
/// and should be generally avoided.
|
/// and should be generally avoided.
|
||||||
class TwineLocalCheck : public ClangTidyCheck {
|
class TwineLocalCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
TwineLocalCheck();
|
TwineLocalCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,8 +18,10 @@ using namespace clang::ast_matchers;
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
|
|
||||||
ArgumentCommentCheck::ArgumentCommentCheck()
|
ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
|
||||||
: IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
|
ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context),
|
||||||
|
IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
|
||||||
|
|
||||||
void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
|
void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
Finder->addMatcher(
|
Finder->addMatcher(
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace tidy {
|
||||||
/// \brief Checks that argument comments match parameter names.
|
/// \brief Checks that argument comments match parameter names.
|
||||||
class ArgumentCommentCheck : public ClangTidyCheck {
|
class ArgumentCommentCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
ArgumentCommentCheck();
|
ArgumentCommentCheck(StringRef Name, ClangTidyContext *Context);
|
||||||
|
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace tidy {
|
||||||
/// }
|
/// }
|
||||||
class BoolPointerImplicitConversion : public ClangTidyCheck {
|
class BoolPointerImplicitConversion : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
BoolPointerImplicitConversion(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace tidy {
|
||||||
/// *ptr->get() ==> **ptr
|
/// *ptr->get() ==> **ptr
|
||||||
class RedundantSmartptrGet : public ClangTidyCheck {
|
class RedundantSmartptrGet : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
RedundantSmartptrGet(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace tidy {
|
||||||
/// conversions.
|
/// conversions.
|
||||||
class SwappedArgumentsCheck : public ClangTidyCheck {
|
class SwappedArgumentsCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
SwappedArgumentsCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace tidy {
|
||||||
/// meant to use a delegating constructor or base class initializer.
|
/// meant to use a delegating constructor or base class initializer.
|
||||||
class UndelegatedConstructorCheck : public ClangTidyCheck {
|
class UndelegatedConstructorCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
UndelegatedConstructorCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace tidy {
|
||||||
/// - Ignore objects returned from a call.
|
/// - Ignore objects returned from a call.
|
||||||
class UnusedRAIICheck : public ClangTidyCheck {
|
class UnusedRAIICheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
UnusedRAIICheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace tidy {
|
||||||
/// \brief Use C++11's 'override' and remove 'virtual' where applicable.
|
/// \brief Use C++11's 'override' and remove 'virtual' where applicable.
|
||||||
class UseOverride : public ClangTidyCheck {
|
class UseOverride : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
UseOverride(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -173,6 +173,7 @@ int clangTidyMain(int argc, const char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DumpConfig) {
|
if (DumpConfig) {
|
||||||
|
EffectiveOptions.CheckOptions = getCheckOptions(EffectiveOptions);
|
||||||
llvm::outs() << configurationAsText(ClangTidyOptions::getDefaults()
|
llvm::outs() << configurationAsText(ClangTidyOptions::getDefaults()
|
||||||
.mergeWith(EffectiveOptions))
|
.mergeWith(EffectiveOptions))
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace tidy {
|
||||||
/// \brief Finds and fixes header guards.
|
/// \brief Finds and fixes header guards.
|
||||||
class HeaderGuardCheck : public ClangTidyCheck {
|
class HeaderGuardCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
HeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerPPCallbacks(CompilerInstance &Compiler) override;
|
void registerPPCallbacks(CompilerInstance &Compiler) override;
|
||||||
|
|
||||||
/// \brief Returns true if the checker should suggest inserting a trailing
|
/// \brief Returns true if the checker should suggest inserting a trailing
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace test {
|
||||||
|
|
||||||
class TestCheck : public ClangTidyCheck {
|
class TestCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
|
TestCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override {
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override {
|
||||||
Finder->addMatcher(ast_matchers::varDecl().bind("var"), this);
|
Finder->addMatcher(ast_matchers::varDecl().bind("var"), this);
|
||||||
}
|
}
|
||||||
|
@ -23,9 +25,8 @@ TEST(ClangTidyDiagnosticConsumer, SortsErrors) {
|
||||||
std::vector<ClangTidyError> Errors;
|
std::vector<ClangTidyError> Errors;
|
||||||
runCheckOnCode<TestCheck>("int a;", &Errors);
|
runCheckOnCode<TestCheck>("int a;", &Errors);
|
||||||
EXPECT_EQ(2ul, Errors.size());
|
EXPECT_EQ(2ul, Errors.size());
|
||||||
// FIXME: Remove " []" once the check name is removed from the message text.
|
EXPECT_EQ("type specifier", Errors[0].Message.Message);
|
||||||
EXPECT_EQ("type specifier []", Errors[0].Message.Message);
|
EXPECT_EQ("variable", Errors[1].Message.Message);
|
||||||
EXPECT_EQ("variable []", Errors[1].Message.Message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GlobList, Empty) {
|
TEST(GlobList, Empty) {
|
||||||
|
|
|
@ -44,13 +44,12 @@ std::string runCheckOnCode(StringRef Code,
|
||||||
std::vector<ClangTidyError> *Errors = nullptr,
|
std::vector<ClangTidyError> *Errors = nullptr,
|
||||||
const Twine &Filename = "input.cc",
|
const Twine &Filename = "input.cc",
|
||||||
ArrayRef<std::string> ExtraArgs = None) {
|
ArrayRef<std::string> ExtraArgs = None) {
|
||||||
T Check;
|
|
||||||
ClangTidyOptions Options;
|
ClangTidyOptions Options;
|
||||||
Options.Checks = "*";
|
Options.Checks = "*";
|
||||||
ClangTidyContext Context(llvm::make_unique<DefaultOptionsProvider>(
|
ClangTidyContext Context(llvm::make_unique<DefaultOptionsProvider>(
|
||||||
ClangTidyGlobalOptions(), Options));
|
ClangTidyGlobalOptions(), Options));
|
||||||
ClangTidyDiagnosticConsumer DiagConsumer(Context);
|
ClangTidyDiagnosticConsumer DiagConsumer(Context);
|
||||||
Check.setContext(&Context);
|
T Check("test-check", &Context);
|
||||||
std::vector<std::string> ArgCXX11(1, "-std=c++11");
|
std::vector<std::string> ArgCXX11(1, "-std=c++11");
|
||||||
ArgCXX11.insert(ArgCXX11.end(), ExtraArgs.begin(), ExtraArgs.end());
|
ArgCXX11.insert(ArgCXX11.end(), ExtraArgs.begin(), ExtraArgs.end());
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,8 @@ static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct WithEndifComment : public LLVMHeaderGuardCheck {
|
struct WithEndifComment : public LLVMHeaderGuardCheck {
|
||||||
|
WithEndifComment(StringRef Name, ClangTidyContext *Context)
|
||||||
|
: LLVMHeaderGuardCheck(Name, Context) {}
|
||||||
bool shouldSuggestEndifComment(StringRef Filename) override { return true; }
|
bool shouldSuggestEndifComment(StringRef Filename) override { return true; }
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue