2020-01-17 05:29:19 +08:00
|
|
|
//===--- RenamderClangTidyCheck.h - clang-tidy ------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|
|
|
|
|
|
|
|
#include "../ClangTidyCheck.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
|
|
|
|
class MacroInfo;
|
|
|
|
|
|
|
|
namespace tidy {
|
|
|
|
|
|
|
|
/// Base class for clang-tidy checks that want to flag declarations and/or
|
|
|
|
/// macros for renaming based on customizable criteria.
|
|
|
|
class RenamerClangTidyCheck : public ClangTidyCheck {
|
|
|
|
public:
|
|
|
|
RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
|
|
|
|
~RenamerClangTidyCheck();
|
|
|
|
|
|
|
|
/// Derived classes should not implement any matching logic themselves; this
|
|
|
|
/// class will do the matching and call the derived class'
|
|
|
|
/// GetDeclFailureInfo() and GetMacroFailureInfo() for determining whether a
|
|
|
|
/// given identifier passes or fails the check.
|
|
|
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override final;
|
|
|
|
void
|
|
|
|
check(const ast_matchers::MatchFinder::MatchResult &Result) override final;
|
|
|
|
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
|
|
|
|
Preprocessor *ModuleExpanderPP) override final;
|
|
|
|
void onEndOfTranslationUnit() override final;
|
|
|
|
|
[clang-tidy] RenamerClangTidy now renames dependent member expr when the member can be resolved
Summary:
Sometimes in templated code Member references are reported as `DependentScopeMemberExpr` because that's what the standard dictates, however in many trivial cases it is easy to resolve the reference to its actual Member.
Take this code:
```
template<typename T>
class A{
int value;
A& operator=(const A& Other){
value = Other.value;
this->value = Other.value;
return *this;
}
};
```
When ran with `clang-tidy file.cpp -checks=readability-identifier-naming --config="{CheckOptions: [{key: readability-identifier-naming.MemberPrefix, value: m_}]}" -fix`
Current behaviour:
```
template<typename T>
class A{
int m_value;
A& operator=(const A& Other){
m_value = Other.value;
this->value = Other.value;
return *this;
}
};
```
As `this->value` and `Other.value` are Dependent they are ignored when creating the fix-its, however this can easily be resolved.
Proposed behaviour:
```
template<typename T>
class A{
int m_value;
A& operator=(const A& Other){
m_value = Other.m_value;
this->m_value = Other.m_value;
return *this;
}
};
```
Reviewers: aaron.ballman, JonasToth, alexfh, hokein, gribozavr2
Reviewed By: aaron.ballman
Subscribers: merge_guards_bot, xazax.hun, cfe-commits
Tags: #clang, #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D73052
2020-05-09 02:30:18 +08:00
|
|
|
/// Derived classes that override this function should call this method from
|
|
|
|
/// the overridden method.
|
|
|
|
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
|
|
|
|
2020-01-17 05:29:19 +08:00
|
|
|
/// This enum will be used in %select of the diagnostic message.
|
|
|
|
/// Each value below IgnoreFailureThreshold should have an error message.
|
|
|
|
enum class ShouldFixStatus {
|
|
|
|
ShouldFix,
|
|
|
|
|
|
|
|
/// The fixup will conflict with a language keyword,
|
|
|
|
/// so we can't fix it automatically.
|
|
|
|
ConflictsWithKeyword,
|
|
|
|
|
|
|
|
/// The fixup will conflict with a macro
|
|
|
|
/// definition, so we can't fix it
|
|
|
|
/// automatically.
|
|
|
|
ConflictsWithMacroDefinition,
|
|
|
|
|
|
|
|
/// Values pass this threshold will be ignored completely
|
|
|
|
/// i.e no message, no fixup.
|
|
|
|
IgnoreFailureThreshold,
|
|
|
|
|
|
|
|
/// If the identifier was used or declared within a macro we
|
|
|
|
/// won't offer a fixup for safety reasons.
|
|
|
|
InsideMacro,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Information describing a failed check
|
|
|
|
struct FailureInfo {
|
|
|
|
std::string KindName; // Tag or misc info to be used as derived classes need
|
|
|
|
std::string Fixup; // The name that will be proposed as a fix-it hint
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Holds an identifier name check failure, tracking the kind of the
|
|
|
|
/// identifier, its possible fixup and the starting locations of all the
|
|
|
|
/// identifier usages.
|
|
|
|
struct NamingCheckFailure {
|
|
|
|
FailureInfo Info;
|
|
|
|
|
|
|
|
/// Whether the failure should be fixed or not.
|
|
|
|
///
|
|
|
|
/// e.g.: if the identifier was used or declared within a macro we won't
|
|
|
|
/// offer a fixup for safety reasons.
|
|
|
|
bool ShouldFix() const {
|
|
|
|
return FixStatus == ShouldFixStatus::ShouldFix && !Info.Fixup.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShouldNotify() const {
|
|
|
|
return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;
|
|
|
|
|
|
|
|
/// A set of all the identifier usages starting SourceLocation, in
|
|
|
|
/// their encoded form.
|
|
|
|
llvm::DenseSet<unsigned> RawUsageLocs;
|
|
|
|
|
|
|
|
NamingCheckFailure() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
using NamingCheckId = std::pair<SourceLocation, std::string>;
|
|
|
|
|
|
|
|
using NamingCheckFailureMap =
|
|
|
|
llvm::DenseMap<NamingCheckId, NamingCheckFailure>;
|
|
|
|
|
|
|
|
/// Check Macros for style violations.
|
|
|
|
void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok,
|
|
|
|
const MacroInfo *MI);
|
|
|
|
|
|
|
|
/// Add a usage of a macro if it already has a violation.
|
|
|
|
void expandMacro(const Token &MacroNameTok, const MacroInfo *MI);
|
|
|
|
|
2020-05-10 01:57:05 +08:00
|
|
|
void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl,
|
|
|
|
SourceRange Range, SourceManager *SourceMgr = nullptr);
|
|
|
|
|
|
|
|
/// Convenience method when the usage to be added is a NamedDecl.
|
|
|
|
void addUsage(const NamedDecl *Decl, SourceRange Range,
|
|
|
|
SourceManager *SourceMgr = nullptr);
|
|
|
|
|
2020-01-17 05:29:19 +08:00
|
|
|
protected:
|
|
|
|
/// Overridden by derived classes, returns information about if and how a Decl
|
|
|
|
/// failed the check. A 'None' result means the Decl did not fail the check.
|
|
|
|
virtual llvm::Optional<FailureInfo>
|
|
|
|
GetDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;
|
|
|
|
|
|
|
|
/// Overridden by derived classes, returns information about if and how a
|
|
|
|
/// macro failed the check. A 'None' result means the macro did not fail the
|
|
|
|
/// check.
|
|
|
|
virtual llvm::Optional<FailureInfo>
|
|
|
|
GetMacroFailureInfo(const Token &MacroNameTok,
|
|
|
|
const SourceManager &SM) const = 0;
|
|
|
|
|
|
|
|
/// Represents customized diagnostic text and how arguments should be applied.
|
|
|
|
/// Example usage:
|
|
|
|
///
|
|
|
|
/// return DiagInfo{"my %1 very %2 special %3 text",
|
|
|
|
/// [=](DiagnosticBuilder &diag) {
|
|
|
|
/// diag << arg1 << arg2 << arg3;
|
|
|
|
/// }};
|
|
|
|
struct DiagInfo {
|
|
|
|
std::string Text;
|
|
|
|
llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Overridden by derived classes, returns a description of the diagnostic
|
|
|
|
/// that should be emitted for the given failure. The base class will then
|
|
|
|
/// further customize the diagnostic by adding info about whether the fix-it
|
|
|
|
/// can be automatically applied or not.
|
|
|
|
virtual DiagInfo GetDiagInfo(const NamingCheckId &ID,
|
|
|
|
const NamingCheckFailure &Failure) const = 0;
|
|
|
|
|
|
|
|
private:
|
|
|
|
NamingCheckFailureMap NamingCheckFailures;
|
[clang-tidy] RenamerClangTidy now renames dependent member expr when the member can be resolved
Summary:
Sometimes in templated code Member references are reported as `DependentScopeMemberExpr` because that's what the standard dictates, however in many trivial cases it is easy to resolve the reference to its actual Member.
Take this code:
```
template<typename T>
class A{
int value;
A& operator=(const A& Other){
value = Other.value;
this->value = Other.value;
return *this;
}
};
```
When ran with `clang-tidy file.cpp -checks=readability-identifier-naming --config="{CheckOptions: [{key: readability-identifier-naming.MemberPrefix, value: m_}]}" -fix`
Current behaviour:
```
template<typename T>
class A{
int m_value;
A& operator=(const A& Other){
m_value = Other.value;
this->value = Other.value;
return *this;
}
};
```
As `this->value` and `Other.value` are Dependent they are ignored when creating the fix-its, however this can easily be resolved.
Proposed behaviour:
```
template<typename T>
class A{
int m_value;
A& operator=(const A& Other){
m_value = Other.m_value;
this->m_value = Other.m_value;
return *this;
}
};
```
Reviewers: aaron.ballman, JonasToth, alexfh, hokein, gribozavr2
Reviewed By: aaron.ballman
Subscribers: merge_guards_bot, xazax.hun, cfe-commits
Tags: #clang, #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D73052
2020-05-09 02:30:18 +08:00
|
|
|
const bool AggressiveDependentMemberLookup;
|
2020-01-17 05:29:19 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace tidy
|
|
|
|
} // namespace clang
|
|
|
|
|
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|