| Index: tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
|
| diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
|
| index 3b42fc286dd911bd6a28b06238a2526ff8cdef74..3c39350d311c0d1c6c26b1268a6b55d43ed8f0f8 100644
|
| --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
|
| +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
|
| @@ -51,6 +51,13 @@ const char kBlinkFieldPrefix[] = "m_";
|
| const char kBlinkStaticMemberPrefix[] = "s_";
|
| const char kGeneratedFileRegex[] = "^gen/|/gen/";
|
|
|
| +template <typename MatcherType, typename NodeType>
|
| +bool IsMatching(const MatcherType& matcher,
|
| + const NodeType& node,
|
| + clang::ASTContext& context) {
|
| + return !match(matcher, node, context).empty();
|
| +}
|
| +
|
| const clang::ast_matchers::internal::
|
| VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr>
|
| unresolvedMemberExpr;
|
| @@ -212,6 +219,21 @@ bool IsBlacklistedMethod(const clang::CXXMethodDecl& decl) {
|
| return false;
|
| }
|
|
|
| +bool IsBlacklistedFunctionOrMethodName(llvm::StringRef name) {
|
| + static const char* kBlacklistedNames[] = {
|
| + // From IsBlacklistedFunction:
|
| + "swap",
|
| + // From IsBlacklistedMethod:
|
| + "trace", "traceImpl", "lock", "unlock", "try_lock", "begin", "end",
|
| + "rbegin", "rend", "disable",
|
| + };
|
| + for (const auto& b : kBlacklistedNames) {
|
| + if (name == b)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) {
|
| return IsBlacklistedFunction(Node);
|
| }
|
| @@ -322,7 +344,7 @@ bool GetNameForDecl(const clang::FunctionDecl& decl,
|
| // return type.
|
| auto conflict_matcher =
|
| functionDecl(returns(type_containing_same_name_as_function));
|
| - if (!match(conflict_matcher, decl, context).empty())
|
| + if (IsMatching(conflict_matcher, decl, context))
|
| name = "Get" + name;
|
|
|
| return true;
|
| @@ -536,14 +558,63 @@ struct TargetNodeTraits<clang::UnresolvedMemberExpr> {
|
| static const char* GetType() { return "UnresolvedMemberExpr"; }
|
| };
|
|
|
| -template <typename DeclNode, typename TargetNode>
|
| +template <>
|
| +struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> {
|
| + static clang::SourceLocation GetLoc(
|
| + const clang::UnresolvedUsingValueDecl& decl) {
|
| + return decl.getNameInfo().getLoc();
|
| + }
|
| + static const char* GetName() { return "decl"; }
|
| + static const char* GetType() { return "UnresolvedUsingValueDecl"; }
|
| +};
|
| +
|
| +template <typename TargetNode>
|
| class RewriterBase : public MatchFinder::MatchCallback {
|
| public:
|
| explicit RewriterBase(std::set<Replacement>* replacements)
|
| : replacements_(replacements) {}
|
|
|
| + const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) {
|
| + const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>(
|
| + TargetNodeTraits<TargetNode>::GetName());
|
| + assert(target_node);
|
| + return *target_node;
|
| + }
|
| +
|
| + void AddReplacement(const MatchFinder::MatchResult& result,
|
| + llvm::StringRef old_name,
|
| + std::string new_name) {
|
| + if (old_name == new_name)
|
| + return;
|
| +
|
| + clang::SourceLocation loc =
|
| + TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result));
|
| + clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc);
|
| + replacements_->emplace(*result.SourceManager, range, new_name);
|
| + replacement_names_.emplace(old_name.str(), std::move(new_name));
|
| + }
|
| +
|
| + const std::unordered_map<std::string, std::string>& replacement_names()
|
| + const {
|
| + return replacement_names_;
|
| + }
|
| +
|
| + private:
|
| + std::set<Replacement>* const replacements_;
|
| + std::unordered_map<std::string, std::string> replacement_names_;
|
| +};
|
| +
|
| +template <typename DeclNode, typename TargetNode>
|
| +class DeclRewriterBase : public RewriterBase<TargetNode> {
|
| + public:
|
| + using Base = RewriterBase<TargetNode>;
|
| +
|
| + explicit DeclRewriterBase(std::set<Replacement>* replacements)
|
| + : Base(replacements) {}
|
| +
|
| void run(const MatchFinder::MatchResult& result) override {
|
| const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
|
| + assert(decl);
|
| // If false, there's no name to be renamed.
|
| if (!decl->getIdentifier())
|
| return;
|
| @@ -556,8 +627,7 @@ class RewriterBase : public MatchFinder::MatchCallback {
|
| // don't replace in that case.
|
| clang::SourceLocation spell =
|
| result.SourceManager->getSpellingLoc(decl_loc);
|
| - if (strcmp(result.SourceManager->getBufferName(spell),
|
| - "<scratch space>") == 0)
|
| + if (result.SourceManager->getBufferName(spell) == "<scratch space>")
|
| return;
|
| }
|
| clang::ASTContext* context = result.Context;
|
| @@ -565,55 +635,112 @@ class RewriterBase : public MatchFinder::MatchCallback {
|
| if (!GetNameForDecl(*decl, *context, new_name))
|
| return; // If false, the name was not suitable for renaming.
|
| llvm::StringRef old_name = decl->getName();
|
| - if (old_name == new_name)
|
| - return;
|
| - clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc(
|
| - *result.Nodes.getNodeAs<TargetNode>(
|
| - TargetNodeTraits<TargetNode>::GetName()));
|
| - clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc);
|
| - replacements_->emplace(*result.SourceManager, range, new_name);
|
| - replacement_names_.emplace(old_name.str(), std::move(new_name));
|
| - }
|
| -
|
| - const std::unordered_map<std::string, std::string>& replacement_names()
|
| - const {
|
| - return replacement_names_;
|
| + Base::AddReplacement(result, old_name, std::move(new_name));
|
| }
|
| -
|
| - private:
|
| - std::set<Replacement>* const replacements_;
|
| - std::unordered_map<std::string, std::string> replacement_names_;
|
| };
|
|
|
| -using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>;
|
| -using VarDeclRewriter = RewriterBase<clang::VarDecl, clang::NamedDecl>;
|
| -using MemberRewriter = RewriterBase<clang::FieldDecl, clang::MemberExpr>;
|
| -using DeclRefRewriter = RewriterBase<clang::VarDecl, clang::DeclRefExpr>;
|
| -using FieldDeclRefRewriter = RewriterBase<clang::FieldDecl, clang::DeclRefExpr>;
|
| +using FieldDeclRewriter = DeclRewriterBase<clang::FieldDecl, clang::NamedDecl>;
|
| +using VarDeclRewriter = DeclRewriterBase<clang::VarDecl, clang::NamedDecl>;
|
| +using MemberRewriter = DeclRewriterBase<clang::FieldDecl, clang::MemberExpr>;
|
| +using DeclRefRewriter = DeclRewriterBase<clang::VarDecl, clang::DeclRefExpr>;
|
| +using FieldDeclRefRewriter =
|
| + DeclRewriterBase<clang::FieldDecl, clang::DeclRefExpr>;
|
| using FunctionDeclRewriter =
|
| - RewriterBase<clang::FunctionDecl, clang::NamedDecl>;
|
| + DeclRewriterBase<clang::FunctionDecl, clang::NamedDecl>;
|
| using FunctionRefRewriter =
|
| - RewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
|
| + DeclRewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
|
| using ConstructorInitializerRewriter =
|
| - RewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
|
| + DeclRewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
|
|
|
| -using MethodDeclRewriter = RewriterBase<clang::CXXMethodDecl, clang::NamedDecl>;
|
| +using MethodDeclRewriter =
|
| + DeclRewriterBase<clang::CXXMethodDecl, clang::NamedDecl>;
|
| using MethodRefRewriter =
|
| - RewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>;
|
| + DeclRewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>;
|
| using MethodMemberRewriter =
|
| - RewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
|
| + DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
|
|
|
| using EnumConstantDeclRewriter =
|
| - RewriterBase<clang::EnumConstantDecl, clang::NamedDecl>;
|
| + DeclRewriterBase<clang::EnumConstantDecl, clang::NamedDecl>;
|
| using EnumConstantDeclRefRewriter =
|
| - RewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>;
|
| + DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>;
|
|
|
| using UnresolvedLookupRewriter =
|
| - RewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>;
|
| + DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>;
|
| using UnresolvedMemberRewriter =
|
| - RewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>;
|
| + DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>;
|
| +
|
| +using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>;
|
| +
|
| +clang::DeclarationName GetUnresolvedName(
|
| + const clang::UnresolvedMemberExpr& expr) {
|
| + return expr.getMemberName();
|
| +}
|
| +
|
| +clang::DeclarationName GetUnresolvedName(
|
| + const clang::UnresolvedUsingValueDecl& decl) {
|
| + return decl.getDeclName();
|
| +}
|
| +
|
| +template <typename TargetNode>
|
| +class UnresolvedRewriterBase : public RewriterBase<TargetNode> {
|
| + public:
|
| + using Base = RewriterBase<TargetNode>;
|
| +
|
| + explicit UnresolvedRewriterBase(std::set<Replacement>* replacements)
|
| + : RewriterBase<TargetNode>(replacements) {}
|
|
|
| -using UsingDeclRewriter = RewriterBase<clang::UsingDecl, clang::NamedDecl>;
|
| + void run(const MatchFinder::MatchResult& result) override {
|
| + const TargetNode& expr = Base::GetTargetNode(result);
|
| + llvm::StringRef old_name = GetUnresolvedName(expr).getAsString();
|
| + std::string new_name;
|
| + if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name,
|
| + new_name)) {
|
| + Base::AddReplacement(result, old_name, std::move(new_name));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + // This method calculates a new name for nodes that depend on template
|
| + // parameters (http://en.cppreference.com/w/cpp/language/dependent_name). The
|
| + // renaming is based on crude heuristics, because such nodes are not bound to
|
| + // a specific decl until template instantiation - at the point of rename, one
|
| + // cannot tell whether the node will eventually resolve to a field / method /
|
| + // constant / etc.
|
| + bool GuessNameForUnresolvedDependentNode(const TargetNode& node,
|
| + clang::ASTContext& context,
|
| + llvm::StringRef old_name,
|
| + std::string& new_name) {
|
| + // |m_fieldName| -> |field_name_|.
|
| + if (old_name.startswith(kBlinkFieldPrefix)) {
|
| + std::string field_name = old_name.str().substr(strlen(kBlinkFieldPrefix));
|
| + if (field_name.find('_') == std::string::npos) {
|
| + new_name = CamelCaseToUnderscoreCase(field_name) + "_";
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + // |T::myMethod(...)| -> |T::MyMethod(...)|.
|
| + if ((old_name.find('_') == std::string::npos) &&
|
| + !IsBlacklistedFunctionOrMethodName(old_name)) {
|
| + new_name = old_name;
|
| + new_name[0] = clang::toUppercase(new_name[0]);
|
| + return true;
|
| + }
|
| +
|
| + // In the future we can consider more heuristics:
|
| + // - "s_" and "g_" prefixes
|
| + // - "ALL_CAPS"
|
| + // - |T::myStaticField| -> |T::kMyStaticField|
|
| + // (but have to be careful not to rename |value| in WTF/TypeTraits.h?)
|
| + return false;
|
| + }
|
| +};
|
| +
|
| +using UnresolvedDependentMemberRewriter =
|
| + UnresolvedRewriterBase<clang::UnresolvedMemberExpr>;
|
| +
|
| +using UnresolvedUsingValueDeclRewriter =
|
| + UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>;
|
|
|
| } // namespace
|
|
|
| @@ -885,7 +1012,7 @@ int main(int argc, const char* argv[]) {
|
| match_finder.addMatcher(unresolved_lookup_matcher,
|
| &unresolved_lookup_rewriter);
|
|
|
| - // Unresolved member expressions ========
|
| + // Unresolved member expressions (for non-dependent fields / methods) ========
|
| // Similar to unresolved lookup expressions, but for methods in a member
|
| // context, e.g. var_with_templated_type.Method().
|
| auto unresolved_member_matcher = expr(id(
|
| @@ -899,6 +1026,36 @@ int main(int argc, const char* argv[]) {
|
| match_finder.addMatcher(unresolved_member_matcher,
|
| &unresolved_member_rewriter);
|
|
|
| + // Unresolved using value decls ========
|
| + // Example:
|
| + // template <typename T>
|
| + // class BaseClass {
|
| + // public:
|
| + // unsigned long m_size;
|
| + // };
|
| + // template <typename T>
|
| + // class DerivedClass : protected BaseClass<T> {
|
| + // private:
|
| + // using Base = BaseClass<T>;
|
| + // using Base::m_size; // <- |m_size| here is matched by
|
| + // void method() { // |unresolved_using_value_decl_matcher|.
|
| + // m_size = 123; // <- |m_size| here is matched by
|
| + // } // |unresolved_dependent_using_matcher|.
|
| + // };
|
| + auto unresolved_dependent_using_matcher =
|
| + expr(id("expr", unresolvedMemberExpr(allOverloadsMatch(allOf(
|
| + in_blink_namespace, unresolvedUsingValueDecl())))));
|
| + UnresolvedDependentMemberRewriter unresolved_dependent_member_rewriter(
|
| + &replacements);
|
| + match_finder.addMatcher(unresolved_dependent_using_matcher,
|
| + &unresolved_dependent_member_rewriter);
|
| + auto unresolved_using_value_decl_matcher =
|
| + decl(id("decl", unresolvedUsingValueDecl(in_blink_namespace)));
|
| + UnresolvedUsingValueDeclRewriter unresolved_using_value_decl_rewriter(
|
| + &replacements);
|
| + match_finder.addMatcher(unresolved_using_value_decl_matcher,
|
| + &unresolved_using_value_decl_rewriter);
|
| +
|
| // Using declarations ========
|
| // Given
|
| // using blink::X;
|
|
|