Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Changes Blink-style names to Chrome-style names. Currently transforms: | 5 // Changes Blink-style names to Chrome-style names. Currently transforms: |
| 6 // fields: | 6 // fields: |
| 7 // int m_operationCount => int operation_count_ | 7 // int m_operationCount => int operation_count_ |
| 8 // variables (including parameters): | 8 // variables (including parameters): |
| 9 // int mySuperVariable => int my_super_variable | 9 // int mySuperVariable => int my_super_variable |
| 10 // constants: | 10 // constants: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 bool IsMatching(const MatcherType& matcher, | 55 bool IsMatching(const MatcherType& matcher, |
| 56 const NodeType& node, | 56 const NodeType& node, |
| 57 clang::ASTContext& context) { | 57 clang::ASTContext& context) { |
| 58 return !match(matcher, node, context).empty(); | 58 return !match(matcher, node, context).empty(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 const clang::ast_matchers::internal:: | 61 const clang::ast_matchers::internal:: |
| 62 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> | 62 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> |
| 63 unresolvedMemberExpr; | 63 unresolvedMemberExpr; |
| 64 | 64 |
| 65 const clang::ast_matchers::internal:: | |
| 66 VariadicDynCastAllOfMatcher<clang::Expr, clang::DependentScopeDeclRefExpr> | |
| 67 dependentScopeDeclRefExpr; | |
| 68 | |
| 69 const clang::ast_matchers::internal:: | |
| 70 VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXDependentScopeMemberExpr> | |
| 71 cxxDependentScopeMemberExpr; | |
| 72 | |
| 65 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { | 73 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { |
| 66 return Node.isOverloadedOperator(); | 74 return Node.isOverloadedOperator(); |
| 67 } | 75 } |
| 68 | 76 |
| 69 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) { | 77 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) { |
| 70 return Node.isInstance(); | 78 return Node.isInstance(); |
| 71 } | 79 } |
| 72 | 80 |
| 73 AST_MATCHER_P(clang::FunctionTemplateDecl, | 81 AST_MATCHER_P(clang::FunctionTemplateDecl, |
| 74 templatedDecl, | 82 templatedDecl, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 return inner_matcher.matches(decl, finder, builder); | 166 return inner_matcher.matches(decl, finder, builder); |
| 159 } | 167 } |
| 160 | 168 |
| 161 AST_MATCHER_P(clang::CXXMethodDecl, | 169 AST_MATCHER_P(clang::CXXMethodDecl, |
| 162 includeAllOverriddenMethods, | 170 includeAllOverriddenMethods, |
| 163 clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>, | 171 clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>, |
| 164 InnerMatcher) { | 172 InnerMatcher) { |
| 165 return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder); | 173 return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder); |
| 166 } | 174 } |
| 167 | 175 |
| 176 // Matches |T::m| and/or |x->T::m| and/or |x->m| CXXDependentScopeMemberExpr | |
| 177 // if member |m| comes from a type that matches the InnerMatcher. | |
| 178 AST_MATCHER_P( | |
| 179 clang::CXXDependentScopeMemberExpr, | |
| 180 hasMemberFromType, | |
| 181 clang::ast_matchers::internal::Matcher<clang::QualType>, | |
| 182 InnerMatcher) { | |
| 183 // Given |T::m| and/or |x->T::m| and/or |x->m| ... | |
| 184 if (clang::NestedNameSpecifier* nestedNameSpecifier = Node.getQualifier()) { | |
| 185 // ... if |T| is present, then InnerMatcher has to match |T|. | |
| 186 clang::QualType qualType(nestedNameSpecifier->getAsType(), 0); | |
| 187 return InnerMatcher.matches(qualType, Finder, Builder); | |
| 188 } else { | |
| 189 // ... if there is no |T|, then InnerMatcher has to match the type of |x|. | |
| 190 clang::Expr* base_expr = Node.isImplicitAccess() ? nullptr : Node.getBase(); | |
| 191 return base_expr && InnerMatcher.matches( | |
| 192 base_expr->getType(), Finder, Builder); | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 // Matches |const Class<T>&| QualType if InnerMatcher matches |Class<T>|. | |
| 197 AST_MATCHER_P(clang::QualType, | |
| 198 hasBaseType, | |
| 199 clang::ast_matchers::internal::Matcher<clang::Type>, | |
| 200 InnerMatcher) { | |
| 201 const clang::Type* type = Node.getTypePtrOrNull(); | |
| 202 return type && InnerMatcher.matches(*type, Finder, Builder); | |
| 203 } | |
| 204 | |
| 168 bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl, | 205 bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl, |
| 169 const char* class_name) { | 206 const char* class_name) { |
| 170 if (decl.getParent()->getQualifiedNameAsString() == class_name) | 207 if (decl.getParent()->getQualifiedNameAsString() == class_name) |
| 171 return true; | 208 return true; |
| 172 for (auto it = decl.begin_overridden_methods(); | 209 for (auto it = decl.begin_overridden_methods(); |
| 173 it != decl.end_overridden_methods(); ++it) { | 210 it != decl.end_overridden_methods(); ++it) { |
| 174 if (IsMethodOverrideOf(**it, class_name)) | 211 if (IsMethodOverrideOf(**it, class_name)) |
| 175 return true; | 212 return true; |
| 176 } | 213 } |
| 177 return false; | 214 return false; |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 template <> | 561 template <> |
| 525 struct TargetNodeTraits<clang::DeclRefExpr> { | 562 struct TargetNodeTraits<clang::DeclRefExpr> { |
| 526 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { | 563 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { |
| 527 return expr.getLocation(); | 564 return expr.getLocation(); |
| 528 } | 565 } |
| 529 static const char* GetName() { return "expr"; } | 566 static const char* GetName() { return "expr"; } |
| 530 static const char* GetType() { return "DeclRefExpr"; } | 567 static const char* GetType() { return "DeclRefExpr"; } |
| 531 }; | 568 }; |
| 532 | 569 |
| 533 template <> | 570 template <> |
| 571 struct TargetNodeTraits<clang::DependentScopeDeclRefExpr> { | |
| 572 static clang::SourceLocation GetLoc( | |
| 573 const clang::DependentScopeDeclRefExpr& expr) { | |
| 574 return expr.getLocation(); | |
| 575 } | |
| 576 static const char* GetName() { return "expr"; } | |
| 577 }; | |
| 578 | |
| 579 template <> | |
| 580 struct TargetNodeTraits<clang::CXXDependentScopeMemberExpr> { | |
| 581 static clang::SourceLocation GetLoc( | |
| 582 const clang::CXXDependentScopeMemberExpr& expr) { | |
| 583 return expr.getMemberLoc(); | |
| 584 } | |
| 585 static const char* GetName() { return "expr"; } | |
| 586 }; | |
| 587 | |
| 588 template <> | |
| 534 struct TargetNodeTraits<clang::CXXCtorInitializer> { | 589 struct TargetNodeTraits<clang::CXXCtorInitializer> { |
| 535 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { | 590 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { |
| 536 assert(init.isWritten()); | 591 assert(init.isWritten()); |
| 537 return init.getSourceLocation(); | 592 return init.getSourceLocation(); |
| 538 } | 593 } |
| 539 static const char* GetName() { return "initializer"; } | 594 static const char* GetName() { return "initializer"; } |
| 540 static const char* GetType() { return "CXXCtorInitializer"; } | 595 static const char* GetType() { return "CXXCtorInitializer"; } |
| 541 }; | 596 }; |
| 542 | 597 |
| 543 template <> | 598 template <> |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | 725 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; |
| 671 | 726 |
| 672 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; | 727 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; |
| 673 | 728 |
| 674 clang::DeclarationName GetUnresolvedName( | 729 clang::DeclarationName GetUnresolvedName( |
| 675 const clang::UnresolvedMemberExpr& expr) { | 730 const clang::UnresolvedMemberExpr& expr) { |
| 676 return expr.getMemberName(); | 731 return expr.getMemberName(); |
| 677 } | 732 } |
| 678 | 733 |
| 679 clang::DeclarationName GetUnresolvedName( | 734 clang::DeclarationName GetUnresolvedName( |
| 735 const clang::DependentScopeDeclRefExpr& expr) { | |
| 736 return expr.getDeclName(); | |
| 737 } | |
| 738 | |
| 739 clang::DeclarationName GetUnresolvedName( | |
| 740 const clang::CXXDependentScopeMemberExpr& expr) { | |
| 741 return expr.getMember(); | |
| 742 } | |
| 743 | |
| 744 clang::DeclarationName GetUnresolvedName( | |
| 680 const clang::UnresolvedUsingValueDecl& decl) { | 745 const clang::UnresolvedUsingValueDecl& decl) { |
| 681 return decl.getDeclName(); | 746 return decl.getDeclName(); |
| 682 } | 747 } |
| 683 | 748 |
| 749 // Returns whether |expr_node| is used as a callee in the AST (i.e. if | |
| 750 // |expr_node| needs to resolve to a method or a function). | |
| 751 bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) { | |
| 752 auto matcher = stmt(hasParent(callExpr(callee(equalsNode(&expr))))); | |
| 753 return IsMatching(matcher, expr, context); | |
| 754 } | |
| 755 | |
| 756 // Returns whether |decl| will be used as a callee in the AST (i.e. if the value | |
| 757 // brought by the using declaration will resolve to a method or a function). | |
| 758 bool IsCallee(const clang::UnresolvedUsingValueDecl& /* decl */, | |
| 759 clang::ASTContext& /* context */) { | |
| 760 // Heuristic - looking only at the shape of AST, let's assume that |using | |
|
dcheng
2016/12/01 07:15:06
Nit: perhaps refine this comment to say that from
Łukasz Anforowicz
2016/12/01 18:26:57
Done.
| |
| 761 // Base::foo| refers to a method. This heuristic can be refined by also | |
| 762 // looking at the name of |decl| (this is done both for | |
| 763 // UnresolvedUsingValueDecl and for clang::Expr in | |
| 764 // GuessNameForUnresolvedDependentNode method). | |
| 765 return true; | |
| 766 } | |
| 767 | |
| 684 template <typename TargetNode> | 768 template <typename TargetNode> |
| 685 class UnresolvedRewriterBase : public RewriterBase<TargetNode> { | 769 class UnresolvedRewriterBase : public RewriterBase<TargetNode> { |
| 686 public: | 770 public: |
| 687 using Base = RewriterBase<TargetNode>; | 771 using Base = RewriterBase<TargetNode>; |
| 688 | 772 |
| 689 explicit UnresolvedRewriterBase(std::set<Replacement>* replacements) | 773 explicit UnresolvedRewriterBase(std::set<Replacement>* replacements) |
| 690 : RewriterBase<TargetNode>(replacements) {} | 774 : RewriterBase<TargetNode>(replacements) {} |
| 691 | 775 |
| 692 void run(const MatchFinder::MatchResult& result) override { | 776 void run(const MatchFinder::MatchResult& result) override { |
| 693 const TargetNode& expr = Base::GetTargetNode(result); | 777 const TargetNode& node = Base::GetTargetNode(result); |
| 694 llvm::StringRef old_name = GetUnresolvedName(expr).getAsString(); | 778 |
| 779 // Make sure there is an old name + extract the old name. | |
| 780 clang::IdentifierInfo* info = GetUnresolvedName(node).getAsIdentifierInfo(); | |
| 781 if (!info) | |
| 782 return; | |
| 783 llvm::StringRef old_name = info->getName(); | |
| 784 | |
| 785 // Try to guess a new name. | |
| 695 std::string new_name; | 786 std::string new_name; |
| 696 if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name, | 787 if (GuessNameForUnresolvedDependentNode(node, *result.Context, new_name)) |
| 697 new_name)) { | |
| 698 Base::AddReplacement(result, old_name, std::move(new_name)); | 788 Base::AddReplacement(result, old_name, std::move(new_name)); |
| 699 } | |
| 700 } | 789 } |
| 701 | 790 |
| 702 private: | 791 private: |
| 703 // This method calculates a new name for nodes that depend on template | 792 // This method calculates a new name for nodes that depend on template |
| 704 // parameters (http://en.cppreference.com/w/cpp/language/dependent_name). The | 793 // parameters (http://en.cppreference.com/w/cpp/language/dependent_name). The |
| 705 // renaming is based on crude heuristics, because such nodes are not bound to | 794 // renaming is based on crude heuristics, because such nodes are not bound to |
| 706 // a specific decl until template instantiation - at the point of rename, one | 795 // a specific decl until template instantiation - at the point of rename, one |
| 707 // cannot tell whether the node will eventually resolve to a field / method / | 796 // cannot tell whether the node will eventually resolve to a field / method / |
| 708 // constant / etc. | 797 // constant / etc. |
| 798 // | |
| 799 // The method returns false if no renaming should be done. | |
| 800 // Otherwise the method returns true and sets |new_name|. | |
| 709 bool GuessNameForUnresolvedDependentNode(const TargetNode& node, | 801 bool GuessNameForUnresolvedDependentNode(const TargetNode& node, |
| 710 clang::ASTContext& context, | 802 clang::ASTContext& context, |
| 711 llvm::StringRef old_name, | |
| 712 std::string& new_name) { | 803 std::string& new_name) { |
| 804 // Verify that we have the kind of name we can rename. | |
| 805 clang::DeclarationName decl_name = GetUnresolvedName(node); | |
| 806 switch (decl_name.getNameKind()) { | |
| 807 // Do not rewrite this: | |
| 808 // return operator T*(); | |
| 809 // into this: | |
| 810 // return Operator type - parameter - 0 - 0 * T * (); | |
| 811 case clang::DeclarationName::NameKind::CXXConversionFunctionName: | |
| 812 case clang::DeclarationName::NameKind::CXXOperatorName: | |
| 813 case clang::DeclarationName::NameKind::CXXLiteralOperatorName: | |
| 814 return false; | |
| 815 default: | |
| 816 break; | |
| 817 } | |
| 818 llvm::StringRef old_name = decl_name.getAsIdentifierInfo()->getName(); | |
| 819 | |
| 713 // |m_fieldName| -> |field_name_|. | 820 // |m_fieldName| -> |field_name_|. |
| 714 if (old_name.startswith(kBlinkFieldPrefix)) { | 821 if (old_name.startswith(kBlinkFieldPrefix)) { |
| 715 std::string field_name = old_name.str().substr(strlen(kBlinkFieldPrefix)); | 822 std::string field_name = old_name.substr(strlen(kBlinkFieldPrefix)); |
| 716 if (field_name.find('_') == std::string::npos) { | 823 if (field_name.find('_') == std::string::npos) { |
| 717 new_name = CamelCaseToUnderscoreCase(field_name) + "_"; | 824 new_name = CamelCaseToUnderscoreCase(field_name) + "_"; |
| 718 return true; | 825 return true; |
| 719 } | 826 } |
| 720 } | 827 } |
| 721 | 828 |
| 722 // |T::myMethod(...)| -> |T::MyMethod(...)|. | 829 // |T::myMethod(...)| -> |T::MyMethod(...)|. |
| 723 if ((old_name.find('_') == std::string::npos) && | 830 if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) && |
| 724 !IsBlacklistedFunctionOrMethodName(old_name)) { | 831 !IsBlacklistedFunctionOrMethodName(old_name)) { |
| 725 new_name = old_name; | 832 new_name = old_name; |
| 726 new_name[0] = clang::toUppercase(new_name[0]); | 833 new_name[0] = clang::toUppercase(old_name[0]); |
| 727 return true; | 834 return true; |
| 728 } | 835 } |
| 729 | 836 |
| 730 // In the future we can consider more heuristics: | 837 // In the future we can consider more heuristics: |
| 731 // - "s_" and "g_" prefixes | 838 // - "s_" and "g_" prefixes |
| 732 // - "ALL_CAPS" | 839 // - "ALL_CAPS" |
| 733 // - |T::myStaticField| -> |T::kMyStaticField| | 840 // - |T::myStaticField| -> |T::kMyStaticField| |
| 734 // (but have to be careful not to rename |value| in WTF/TypeTraits.h?) | 841 // (but have to be careful not to rename |value| in WTF/TypeTraits.h?) |
| 735 return false; | 842 return false; |
| 736 } | 843 } |
| 737 }; | 844 }; |
| 738 | 845 |
| 739 using UnresolvedDependentMemberRewriter = | 846 using UnresolvedDependentMemberRewriter = |
| 740 UnresolvedRewriterBase<clang::UnresolvedMemberExpr>; | 847 UnresolvedRewriterBase<clang::UnresolvedMemberExpr>; |
| 741 | 848 |
| 742 using UnresolvedUsingValueDeclRewriter = | 849 using UnresolvedUsingValueDeclRewriter = |
| 743 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; | 850 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; |
| 744 | 851 |
| 852 using DependentScopeDeclRefExprRewriter = | |
| 853 UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>; | |
| 854 | |
| 855 using CXXDependentScopeMemberExprRewriter = | |
| 856 UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>; | |
| 857 | |
| 745 } // namespace | 858 } // namespace |
| 746 | 859 |
| 747 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); | 860 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); |
| 748 | 861 |
| 749 int main(int argc, const char* argv[]) { | 862 int main(int argc, const char* argv[]) { |
| 750 // TODO(dcheng): Clang tooling should do this itself. | 863 // TODO(dcheng): Clang tooling should do this itself. |
| 751 // http://llvm.org/bugs/show_bug.cgi?id=21627 | 864 // http://llvm.org/bugs/show_bug.cgi?id=21627 |
| 752 llvm::InitializeNativeTarget(); | 865 llvm::InitializeNativeTarget(); |
| 753 llvm::InitializeNativeTargetAsmParser(); | 866 llvm::InitializeNativeTargetAsmParser(); |
| 754 llvm::cl::OptionCategory category( | 867 llvm::cl::OptionCategory category( |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1061 // using blink::X; | 1174 // using blink::X; |
| 1062 // matches |using blink::X|. | 1175 // matches |using blink::X|. |
| 1063 auto using_decl_matcher = id( | 1176 auto using_decl_matcher = id( |
| 1064 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( | 1177 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( |
| 1065 var_decl_matcher, field_decl_matcher, function_decl_matcher, | 1178 var_decl_matcher, field_decl_matcher, function_decl_matcher, |
| 1066 method_decl_matcher, function_template_decl_matcher, | 1179 method_decl_matcher, function_template_decl_matcher, |
| 1067 method_template_decl_matcher, enum_member_decl_matcher))))); | 1180 method_template_decl_matcher, enum_member_decl_matcher))))); |
| 1068 UsingDeclRewriter using_decl_rewriter(&replacements); | 1181 UsingDeclRewriter using_decl_rewriter(&replacements); |
| 1069 match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter); | 1182 match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter); |
| 1070 | 1183 |
| 1184 // Matches any QualType that refers to a blink type: | |
| 1185 // - const blink::Foo& | |
| 1186 // - blink::Foo* | |
| 1187 // - blink::Foo<T> | |
| 1188 // - ... | |
| 1189 // TODO(lukasza): The matchers below can be simplified after | |
| 1190 // https://llvm.org/bugs/show_bug.cgi?id=30331 is fixed. | |
| 1191 // Simplified matchers: | |
| 1192 // auto blink_qual_type_base_matcher = | |
| 1193 // qualType(hasDeclaration(in_blink_namespace)); | |
| 1194 // auto blink_qual_type_matcher = qualType(anyOf( | |
| 1195 // blink_qual_type_base_matcher, | |
| 1196 // pointsTo(blink_qual_type_base_matcher), | |
| 1197 // references(blink_qual_type_base_matcher))); | |
| 1198 auto blink_qual_type_bug_workaround_matcher1 = hasBaseType( | |
| 1199 anyOf(enumType(hasDeclaration(in_blink_namespace)), | |
| 1200 recordType(hasDeclaration(in_blink_namespace)), | |
| 1201 templateSpecializationType(hasDeclaration(in_blink_namespace)), | |
| 1202 templateTypeParmType(hasDeclaration(in_blink_namespace)), | |
| 1203 typedefType(hasDeclaration(in_blink_namespace)))); | |
| 1204 auto blink_qual_type_base_matcher = | |
| 1205 qualType(anyOf(blink_qual_type_bug_workaround_matcher1, | |
| 1206 hasBaseType(elaboratedType( | |
| 1207 namesType(blink_qual_type_bug_workaround_matcher1))))); | |
| 1208 auto blink_qual_type_matcher = | |
| 1209 qualType(anyOf(blink_qual_type_base_matcher, pointsTo(in_blink_namespace), | |
| 1210 references(in_blink_namespace))); | |
| 1211 | |
| 1212 // Template-dependent decl lookup ======== | |
| 1213 // Given | |
| 1214 // template <typename T> void f() { T::foo(); } | |
| 1215 // matches |T::foo|. | |
| 1216 auto dependent_scope_decl_ref_expr_matcher = | |
| 1217 expr(id("expr", dependentScopeDeclRefExpr(has(nestedNameSpecifier( | |
| 1218 specifiesType(blink_qual_type_matcher)))))); | |
| 1219 DependentScopeDeclRefExprRewriter dependent_scope_decl_ref_expr_rewriter( | |
| 1220 &replacements); | |
| 1221 match_finder.addMatcher(dependent_scope_decl_ref_expr_matcher, | |
| 1222 &dependent_scope_decl_ref_expr_rewriter); | |
| 1223 | |
| 1224 // Template-dependent member lookup ======== | |
| 1225 // Given | |
| 1226 // template <typename T> | |
| 1227 // class Foo { | |
| 1228 // void f() { T::foo(); } | |
| 1229 // void g(T x) { x.bar(); } | |
| 1230 // }; | |
| 1231 // matches |T::foo| and |x.bar|. | |
| 1232 auto cxx_dependent_scope_member_expr_matcher = expr(id( | |
| 1233 "expr", | |
| 1234 cxxDependentScopeMemberExpr(hasMemberFromType(blink_qual_type_matcher)))); | |
| 1235 CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( | |
| 1236 &replacements); | |
| 1237 match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, | |
| 1238 &cxx_dependent_scope_member_expr_rewriter); | |
| 1239 | |
| 1071 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = | 1240 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = |
| 1072 clang::tooling::newFrontendActionFactory(&match_finder); | 1241 clang::tooling::newFrontendActionFactory(&match_finder); |
| 1073 int result = tool.run(factory.get()); | 1242 int result = tool.run(factory.get()); |
| 1074 if (result != 0) | 1243 if (result != 0) |
| 1075 return result; | 1244 return result; |
| 1076 | 1245 |
| 1077 #if defined(_WIN32) | 1246 #if defined(_WIN32) |
| 1078 HANDLE lockfd = CreateFile("rewrite-sym.lock", GENERIC_READ, FILE_SHARE_READ, | 1247 HANDLE lockfd = CreateFile("rewrite-sym.lock", GENERIC_READ, FILE_SHARE_READ, |
| 1079 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 1248 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 1080 OVERLAPPED overlapped = {}; | 1249 OVERLAPPED overlapped = {}; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1112 for (const auto& r : replacements) { | 1281 for (const auto& r : replacements) { |
| 1113 std::string replacement_text = r.getReplacementText().str(); | 1282 std::string replacement_text = r.getReplacementText().str(); |
| 1114 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 1283 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
| 1115 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 1284 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
| 1116 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 1285 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
| 1117 } | 1286 } |
| 1118 llvm::outs() << "==== END EDITS ====\n"; | 1287 llvm::outs() << "==== END EDITS ====\n"; |
| 1119 | 1288 |
| 1120 return 0; | 1289 return 0; |
| 1121 } | 1290 } |
| OLD | NEW |