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 26 matching lines...) Expand all Loading... | |
| 37 using namespace clang::ast_matchers; | 37 using namespace clang::ast_matchers; |
| 38 using clang::tooling::CommonOptionsParser; | 38 using clang::tooling::CommonOptionsParser; |
| 39 using clang::tooling::Replacement; | 39 using clang::tooling::Replacement; |
| 40 using llvm::StringRef; | 40 using llvm::StringRef; |
| 41 | 41 |
| 42 namespace { | 42 namespace { |
| 43 | 43 |
| 44 const char kBlinkFieldPrefix[] = "m_"; | 44 const char kBlinkFieldPrefix[] = "m_"; |
| 45 const char kBlinkStaticMemberPrefix[] = "s_"; | 45 const char kBlinkStaticMemberPrefix[] = "s_"; |
| 46 const char kGeneratedFileRegex[] = "^gen/|/gen/"; | 46 const char kGeneratedFileRegex[] = "^gen/|/gen/"; |
| 47 const char kGMockMethodNamePrefix[] = "gmock_"; | |
| 48 const int kGMockMaxArgOffset = 400; // ~8 lines of backtracking. | |
| 49 const char kGMockExpectCallArgName[] = "call"; | |
| 50 const char kGMockExpectCallFilename[] = | |
| 51 "testing/gmock/include/gmock/gmock-spec-builders.h"; | |
| 47 | 52 |
| 48 template <typename MatcherType, typename NodeType> | 53 template <typename MatcherType, typename NodeType> |
| 49 bool IsMatching(const MatcherType& matcher, | 54 bool IsMatching(const MatcherType& matcher, |
| 50 const NodeType& node, | 55 const NodeType& node, |
| 51 clang::ASTContext& context) { | 56 clang::ASTContext& context) { |
| 52 return !match(matcher, node, context).empty(); | 57 return !match(matcher, node, context).empty(); |
| 53 } | 58 } |
| 54 | 59 |
| 55 const clang::ast_matchers::internal:: | 60 const clang::ast_matchers::internal:: |
| 56 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> | 61 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 72 return Node.isInstance(); | 77 return Node.isInstance(); |
| 73 } | 78 } |
| 74 | 79 |
| 75 AST_MATCHER_P(clang::FunctionTemplateDecl, | 80 AST_MATCHER_P(clang::FunctionTemplateDecl, |
| 76 templatedDecl, | 81 templatedDecl, |
| 77 clang::ast_matchers::internal::Matcher<clang::FunctionDecl>, | 82 clang::ast_matchers::internal::Matcher<clang::FunctionDecl>, |
| 78 InnerMatcher) { | 83 InnerMatcher) { |
| 79 return InnerMatcher.matches(*Node.getTemplatedDecl(), Finder, Builder); | 84 return InnerMatcher.matches(*Node.getTemplatedDecl(), Finder, Builder); |
| 80 } | 85 } |
| 81 | 86 |
| 87 // Matches a CXXMethodDecl of a method declared via MOCK_METHODx macro if such | |
| 88 // method mocks a method matched by the InnerMatcher. For example if "foo" | |
| 89 // matcher matches "interfaceMethod", then mocksMethod(foo()) will match | |
| 90 // "gmock_interfaceMethod" declared by MOCK_METHOD_x(interfaceMethod). | |
| 91 AST_MATCHER_P(clang::CXXMethodDecl, | |
| 92 mocksMethod, | |
| 93 clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>, | |
| 94 InnerMatcher) { | |
| 95 if (!Node.getDeclName().isIdentifier()) | |
| 96 return false; | |
| 97 | |
| 98 llvm::StringRef method_name = Node.getName(); | |
| 99 if (!method_name.startswith(kGMockMethodNamePrefix)) | |
| 100 return false; | |
| 101 | |
| 102 llvm::StringRef mocked_method_name = | |
| 103 method_name.substr(strlen(kGMockMethodNamePrefix)); | |
| 104 for (const auto& potentially_mocked_method : Node.getParent()->methods()) { | |
| 105 if (!potentially_mocked_method->isVirtual()) | |
| 106 continue; | |
| 107 | |
| 108 clang::DeclarationName decl_name = potentially_mocked_method->getDeclName(); | |
| 109 if (!decl_name.isIdentifier() || | |
| 110 potentially_mocked_method->getName() != mocked_method_name) | |
| 111 continue; | |
| 112 if (potentially_mocked_method->getNumParams() != Node.getNumParams()) | |
| 113 continue; | |
| 114 | |
| 115 if (InnerMatcher.matches(*potentially_mocked_method, Finder, Builder)) | |
| 116 return true; | |
| 117 } | |
| 118 | |
| 119 return false; | |
| 120 } | |
| 121 | |
| 82 // If |InnerMatcher| matches |top|, then the returned matcher will match: | 122 // If |InnerMatcher| matches |top|, then the returned matcher will match: |
| 83 // - |top::function| | 123 // - |top::function| |
| 84 // - |top::Class::method| | 124 // - |top::Class::method| |
| 85 // - |top::internal::Class::method| | 125 // - |top::internal::Class::method| |
| 86 AST_MATCHER_P( | 126 AST_MATCHER_P( |
| 87 clang::NestedNameSpecifier, | 127 clang::NestedNameSpecifier, |
| 88 hasTopLevelPrefix, | 128 hasTopLevelPrefix, |
| 89 clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>, | 129 clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>, |
| 90 InnerMatcher) { | 130 InnerMatcher) { |
| 91 const clang::NestedNameSpecifier* NodeToMatch = &Node; | 131 const clang::NestedNameSpecifier* NodeToMatch = &Node; |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 template <> | 710 template <> |
| 671 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> { | 711 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> { |
| 672 static clang::SourceLocation GetLoc( | 712 static clang::SourceLocation GetLoc( |
| 673 const clang::UnresolvedUsingValueDecl& decl) { | 713 const clang::UnresolvedUsingValueDecl& decl) { |
| 674 return decl.getNameInfo().getLoc(); | 714 return decl.getNameInfo().getLoc(); |
| 675 } | 715 } |
| 676 static const char* GetName() { return "decl"; } | 716 static const char* GetName() { return "decl"; } |
| 677 static const char* GetType() { return "UnresolvedUsingValueDecl"; } | 717 static const char* GetType() { return "UnresolvedUsingValueDecl"; } |
| 678 }; | 718 }; |
| 679 | 719 |
| 720 bool JumpAboveMacroScratchSpace(const clang::SourceManager& source_manager, | |
| 721 clang::SourceLocation* loc) { | |
| 722 if (loc->isMacroID()) { | |
| 723 // Try to jump "above" the scratch buffer if |loc| is inside | |
| 724 // token##Concatenation. | |
| 725 const int kMaxJumps = 5; | |
| 726 bool verified_out_of_scratch_space = false; | |
| 727 for (int i = 0; i < kMaxJumps && !verified_out_of_scratch_space; i++) { | |
| 728 clang::SourceLocation spell = source_manager.getSpellingLoc(*loc); | |
| 729 verified_out_of_scratch_space = | |
| 730 source_manager.getBufferName(spell) != "<scratch space>"; | |
| 731 if (!verified_out_of_scratch_space) | |
| 732 *loc = source_manager.getImmediateMacroCallerLoc(*loc); | |
| 733 } | |
| 734 if (!verified_out_of_scratch_space) | |
| 735 return false; | |
| 736 } | |
| 737 | |
| 738 return true; | |
| 739 } | |
| 740 | |
| 741 llvm::StringRef GetActualText(const clang::ASTContext& context, | |
| 742 const clang::SourceManager& source_manager, | |
| 743 clang::SourceLocation loc, | |
| 744 size_t length, | |
| 745 clang::CharSourceRange* out_range) { | |
|
dcheng
2017/01/06 06:58:45
Stylistically, I'm not a fan of optional output ar
Łukasz Anforowicz
2017/01/07 01:16:29
I've inlined GetActualText back into the only call
| |
| 746 clang::SourceLocation spell = source_manager.getSpellingLoc(loc); | |
| 747 clang::CharSourceRange range = clang::CharSourceRange::getCharRange( | |
| 748 spell, spell.getLocWithOffset(length)); | |
| 749 | |
| 750 if (out_range) | |
| 751 *out_range = range; | |
| 752 | |
| 753 return clang::Lexer::getSourceText(range, source_manager, | |
| 754 context.getLangOpts()); | |
| 755 } | |
| 756 | |
| 680 template <typename TargetNode> | 757 template <typename TargetNode> |
| 681 class RewriterBase : public MatchFinder::MatchCallback { | 758 class RewriterBase : public MatchFinder::MatchCallback { |
| 682 public: | 759 public: |
| 683 explicit RewriterBase(std::set<Replacement>* replacements) | 760 explicit RewriterBase(std::set<Replacement>* replacements) |
| 684 : replacements_(replacements) {} | 761 : replacements_(replacements) {} |
| 685 | 762 |
| 686 const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) { | 763 const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) { |
| 687 const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>( | 764 const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>( |
| 688 TargetNodeTraits<TargetNode>::GetName()); | 765 TargetNodeTraits<TargetNode>::GetName()); |
| 689 assert(target_node); | 766 assert(target_node); |
| 690 return *target_node; | 767 return *target_node; |
| 691 } | 768 } |
| 692 | 769 |
| 693 bool GenerateReplacement(const MatchFinder::MatchResult& result, | 770 bool GenerateReplacement(const MatchFinder::MatchResult& result, |
| 694 clang::SourceLocation loc, | 771 clang::SourceLocation loc, |
| 695 llvm::StringRef old_name, | 772 llvm::StringRef old_name, |
| 696 std::string new_name, | 773 std::string new_name, |
| 697 Replacement* replacement) { | 774 Replacement* replacement) { |
| 698 const clang::ASTContext& context = *result.Context; | 775 const clang::ASTContext& context = *result.Context; |
| 699 const clang::SourceManager& source_manager = *result.SourceManager; | 776 const clang::SourceManager& source_manager = *result.SourceManager; |
| 700 | 777 |
| 701 if (loc.isMacroID()) { | 778 if (!JumpAboveMacroScratchSpace(source_manager, &loc)) |
| 702 // Try to jump "above" the scratch buffer if |loc| is inside | 779 return false; |
| 703 // token##Concatenation. | |
| 704 const int kMaxJumps = 5; | |
| 705 bool verified_out_of_scratch_space = false; | |
| 706 for (int i = 0; i < kMaxJumps && !verified_out_of_scratch_space; i++) { | |
| 707 clang::SourceLocation spell = source_manager.getSpellingLoc(loc); | |
| 708 verified_out_of_scratch_space = | |
| 709 source_manager.getBufferName(spell) != "<scratch space>"; | |
| 710 if (!verified_out_of_scratch_space) | |
| 711 loc = source_manager.getImmediateMacroCallerLoc(loc); | |
| 712 } | |
| 713 if (!verified_out_of_scratch_space) | |
| 714 return false; | |
| 715 } | |
| 716 | 780 |
| 717 // If the edit affects only the first character of the identifier, then | 781 // If the edit affects only the first character of the identifier, then |
| 718 // narrow down the edit to only this single character. This is important | 782 // narrow down the edit to only this single character. This is important |
| 719 // for dealing with toFooBar -> ToFooBar method renaming when the method | 783 // for dealing with toFooBar -> ToFooBar method renaming when the method |
| 720 // name is built using macro token concatenation like to##macroArgument - in | 784 // name is built using macro token concatenation like to##macroArgument - in |
| 721 // this case we should only rewrite "t" -> "T" and leave "o##macroArgument" | 785 // this case we should only rewrite "t" -> "T" and leave "o##macroArgument" |
| 722 // untouched. | 786 // untouched. |
| 723 llvm::StringRef expected_old_text = old_name; | 787 llvm::StringRef expected_old_text = old_name; |
| 724 llvm::StringRef new_text = new_name; | 788 llvm::StringRef new_text = new_name; |
| 725 if (loc.isMacroID() && expected_old_text.substr(1) == new_text.substr(1)) { | 789 if (loc.isMacroID() && expected_old_text.substr(1) == new_text.substr(1)) { |
| 726 expected_old_text = expected_old_text.substr(0, 1); | 790 expected_old_text = expected_old_text.substr(0, 1); |
| 727 new_text = new_text.substr(0, 1); | 791 new_text = new_text.substr(0, 1); |
| 728 } | 792 } |
| 729 clang::SourceLocation spell = source_manager.getSpellingLoc(loc); | |
| 730 clang::CharSourceRange range = clang::CharSourceRange::getCharRange( | |
| 731 spell, spell.getLocWithOffset(expected_old_text.size())); | |
| 732 | 793 |
| 733 // We need to ensure that |actual_old_text| is the same as | 794 // We need to ensure that |actual_old_text| is the same as |
| 734 // |expected_old_text| - it can be different if |actual_old_text| contains | 795 // |expected_old_text| - it can be different if |actual_old_text| contains |
| 735 // a macro argument (see DEFINE_WITH_TOKEN_CONCATENATION2 in | 796 // a macro argument (see DEFINE_WITH_TOKEN_CONCATENATION2 in |
| 736 // macros-original.cc testcase). | 797 // macros-original.cc testcase). |
| 737 StringRef actual_old_text = clang::Lexer::getSourceText( | 798 clang::CharSourceRange range; |
| 738 range, source_manager, context.getLangOpts()); | 799 StringRef actual_old_text = GetActualText(context, source_manager, loc, |
| 800 expected_old_text.size(), &range); | |
| 739 if (actual_old_text != expected_old_text) | 801 if (actual_old_text != expected_old_text) |
| 740 return false; | 802 return false; |
| 741 | 803 |
| 742 if (replacement) | 804 if (replacement) |
| 743 *replacement = Replacement(source_manager, range, new_text); | 805 *replacement = Replacement(source_manager, range, new_text); |
| 806 | |
| 744 return true; | 807 return true; |
| 745 } | 808 } |
| 746 | 809 |
| 810 virtual clang::SourceLocation GetTargetLoc( | |
| 811 const MatchFinder::MatchResult& result) { | |
| 812 return TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | |
| 813 } | |
| 814 | |
| 747 void AddReplacement(const MatchFinder::MatchResult& result, | 815 void AddReplacement(const MatchFinder::MatchResult& result, |
| 748 llvm::StringRef old_name, | 816 llvm::StringRef old_name, |
| 749 std::string new_name) { | 817 std::string new_name) { |
| 750 if (old_name == new_name) | 818 if (old_name == new_name) |
| 751 return; | 819 return; |
| 752 | 820 |
| 753 clang::SourceLocation loc = | 821 clang::SourceLocation loc = GetTargetLoc(result); |
| 754 TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | 822 if (loc.isInvalid()) |
| 823 return; | |
| 755 | 824 |
| 756 Replacement replacement; | 825 Replacement replacement; |
| 757 if (!GenerateReplacement(result, loc, old_name, new_name, &replacement)) | 826 if (!GenerateReplacement(result, loc, old_name, new_name, &replacement)) |
| 758 return; | 827 return; |
| 759 | 828 |
| 760 replacements_->insert(std::move(replacement)); | 829 replacements_->insert(std::move(replacement)); |
| 761 edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name); | 830 edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name); |
| 762 } | 831 } |
| 763 | 832 |
| 764 const EditTracker& edit_tracker() const { return edit_tracker_; } | 833 const EditTracker& edit_tracker() const { return edit_tracker_; } |
| 765 | 834 |
| 766 private: | 835 private: |
| 767 std::set<Replacement>* const replacements_; | 836 std::set<Replacement>* const replacements_; |
| 768 EditTracker edit_tracker_; | 837 EditTracker edit_tracker_; |
| 769 }; | 838 }; |
| 770 | 839 |
| 771 template <typename DeclNode, typename TargetNode> | 840 template <typename DeclNode, typename TargetNode> |
| 772 class DeclRewriterBase : public RewriterBase<TargetNode> { | 841 class DeclRewriterBase : public RewriterBase<TargetNode> { |
| 773 public: | 842 public: |
| 774 using Base = RewriterBase<TargetNode>; | 843 using Base = RewriterBase<TargetNode>; |
| 775 | 844 |
| 776 explicit DeclRewriterBase(std::set<Replacement>* replacements) | 845 explicit DeclRewriterBase(std::set<Replacement>* replacements) |
| 777 : Base(replacements) {} | 846 : Base(replacements) {} |
| 778 | 847 |
| 779 void run(const MatchFinder::MatchResult& result) override { | 848 const DeclNode* GetDecl(const MatchFinder::MatchResult& result) { |
| 780 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); | 849 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); |
| 781 assert(decl); | 850 assert(decl); |
| 851 return decl; | |
| 852 } | |
| 853 | |
| 854 void run(const MatchFinder::MatchResult& result) override { | |
| 855 const DeclNode* decl = GetDecl(result); | |
| 782 llvm::StringRef old_name = decl->getName(); | 856 llvm::StringRef old_name = decl->getName(); |
| 783 | 857 |
| 784 // Return early if there's no name to be renamed. | 858 // Return early if there's no name to be renamed. |
| 785 if (!decl->getIdentifier()) | 859 if (!decl->getIdentifier()) |
| 786 return; | 860 return; |
| 787 | 861 |
| 788 // Get the new name. | 862 // Get the new name. |
| 789 std::string new_name; | 863 std::string new_name; |
| 790 if (!GetNameForDecl(*decl, *result.Context, new_name)) | 864 if (!GetNameForDecl(*decl, *result.Context, new_name)) |
| 791 return; // If false, the name was not suitable for renaming. | 865 return; // If false, the name was not suitable for renaming. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 using EnumConstantDeclRefRewriter = | 901 using EnumConstantDeclRefRewriter = |
| 828 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; | 902 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; |
| 829 | 903 |
| 830 using UnresolvedLookupRewriter = | 904 using UnresolvedLookupRewriter = |
| 831 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; | 905 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; |
| 832 using UnresolvedMemberRewriter = | 906 using UnresolvedMemberRewriter = |
| 833 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | 907 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; |
| 834 | 908 |
| 835 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; | 909 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; |
| 836 | 910 |
| 911 class GMockMemberRewriter | |
| 912 : public DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr> { | |
| 913 public: | |
| 914 using Base = DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; | |
| 915 | |
| 916 explicit GMockMemberRewriter(std::set<Replacement>* replacements) | |
| 917 : Base(replacements) {} | |
| 918 | |
| 919 clang::SourceLocation GetTargetLoc( | |
| 920 const MatchFinder::MatchResult& result) override { | |
| 921 const clang::SourceManager& source_manager = *result.SourceManager; | |
| 922 const clang::ASTContext& context = *result.Context; | |
| 923 const clang::CXXMethodDecl* decl = GetDecl(result); | |
| 924 llvm::StringRef old_name = decl->getName(); | |
| 925 | |
| 926 // This is the location of gmock_##MockedMethod identifier. | |
| 927 clang::SourceLocation target_loc = Base::GetTargetLoc(result); | |
| 928 if (!JumpAboveMacroScratchSpace(source_manager, &target_loc)) | |
| 929 return clang::SourceLocation(); | |
| 930 | |
| 931 // Find |macro_arg_loc| that points at |methodName| in | |
| 932 // EXPECT_CALL(obj, methodName(...)). | |
| 933 clang::SourceLocation macro_arg_loc; | |
| 934 for (int offset = 0; offset > -kGMockMaxArgOffset; offset--) { | |
| 935 macro_arg_loc = target_loc.getLocWithOffset(offset); | |
| 936 | |
| 937 // Check if |macro_arg_loc| contains the mocked method name. | |
| 938 llvm::StringRef actual_text_of_macro_arg = GetActualText( | |
| 939 context, source_manager, macro_arg_loc, old_name.size(), nullptr); | |
| 940 if (actual_text_of_macro_arg != old_name) | |
| 941 continue; | |
| 942 | |
| 943 // Location inside macro definition where the macro argument is expanded. | |
| 944 clang::SourceLocation macro_param_expansion_loc; | |
| 945 if (!source_manager.isMacroArgExpansion(macro_arg_loc, | |
| 946 ¯o_param_expansion_loc)) | |
| 947 continue; | |
| 948 | |
| 949 // Check if |macro_param_expansion_loc| points here: | |
| 950 // testing/gmock/include/gmock/gmock-spec-builders.h:1844:20: | |
| 951 // 1843: #define GMOCK_EXPECT_CALL_IMPL_(obj, call) \ | |
| 952 // 1844: ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE_... | |
| 953 // ^ here | |
| 954 // 1845: #define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, c... | |
| 955 clang::SourceLocation spell_loc = | |
| 956 source_manager.getSpellingLoc(macro_param_expansion_loc); | |
| 957 StringRef filename = source_manager.getFilename(spell_loc); | |
| 958 if (!filename.endswith(kGMockExpectCallFilename)) | |
| 959 continue; | |
| 960 | |
| 961 StringRef actual_text_of_macro_param_name = | |
| 962 GetActualText(context, source_manager, macro_param_expansion_loc, | |
| 963 strlen(kGMockExpectCallArgName), nullptr); | |
| 964 if (actual_text_of_macro_param_name != kGMockExpectCallArgName) | |
| 965 continue; | |
| 966 | |
| 967 // Found it! | |
| 968 return macro_arg_loc; | |
| 969 } | |
| 970 | |
| 971 llvm::errs() << "Couldn't rewrite GMock's EXPECT_CALL at " | |
| 972 << target_loc.printToString(source_manager) << "\n"; | |
| 973 return clang::SourceLocation(); | |
| 974 } | |
| 975 }; | |
| 976 | |
| 837 clang::DeclarationName GetUnresolvedName( | 977 clang::DeclarationName GetUnresolvedName( |
| 838 const clang::UnresolvedMemberExpr& expr) { | 978 const clang::UnresolvedMemberExpr& expr) { |
| 839 return expr.getMemberName(); | 979 return expr.getMemberName(); |
| 840 } | 980 } |
| 841 | 981 |
| 842 clang::DeclarationName GetUnresolvedName( | 982 clang::DeclarationName GetUnresolvedName( |
| 843 const clang::DependentScopeDeclRefExpr& expr) { | 983 const clang::DependentScopeDeclRefExpr& expr) { |
| 844 return expr.getDeclName(); | 984 return expr.getDeclName(); |
| 845 } | 985 } |
| 846 | 986 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1149 // same method. | 1289 // same method. |
| 1150 is_blink_method)); | 1290 is_blink_method)); |
| 1151 MethodDeclRewriter method_decl_rewriter(&replacements); | 1291 MethodDeclRewriter method_decl_rewriter(&replacements); |
| 1152 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); | 1292 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); |
| 1153 | 1293 |
| 1154 // Method references in a non-member context ======== | 1294 // Method references in a non-member context ======== |
| 1155 // Given | 1295 // Given |
| 1156 // S s; | 1296 // S s; |
| 1157 // s.g(); | 1297 // s.g(); |
| 1158 // void (S::*p)() = &S::g; | 1298 // void (S::*p)() = &S::g; |
| 1159 // matches |&S::g| but not |s.g()|. | 1299 // matches |&S::g| but not |s.g|. |
| 1160 auto method_ref_matcher = id( | 1300 auto method_ref_matcher = id( |
| 1161 "expr", declRefExpr(to(method_decl_matcher), | 1301 "expr", declRefExpr(to(method_decl_matcher), |
| 1162 // Ignore template substitutions. | 1302 // Ignore template substitutions. |
| 1163 unless(hasAncestor(substNonTypeTemplateParmExpr())))); | 1303 unless(hasAncestor(substNonTypeTemplateParmExpr())))); |
| 1164 | 1304 |
| 1165 MethodRefRewriter method_ref_rewriter(&replacements); | 1305 MethodRefRewriter method_ref_rewriter(&replacements); |
| 1166 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); | 1306 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); |
| 1167 | 1307 |
| 1168 // Method references in a member context ======== | 1308 // Method references in a member context ======== |
| 1169 // Given | 1309 // Given |
| 1170 // S s; | 1310 // S s; |
| 1171 // s.g(); | 1311 // s.g(); |
| 1172 // void (S::*p)() = &S::g; | 1312 // void (S::*p)() = &S::g; |
| 1173 // matches |s.g()| but not |&S::g|. | 1313 // matches |s.g| but not |&S::g|. |
| 1174 auto method_member_matcher = | 1314 auto method_member_matcher = |
| 1175 id("expr", memberExpr(member(method_decl_matcher))); | 1315 id("expr", memberExpr(member(method_decl_matcher))); |
| 1176 | 1316 |
| 1177 MethodMemberRewriter method_member_rewriter(&replacements); | 1317 MethodMemberRewriter method_member_rewriter(&replacements); |
| 1178 match_finder.addMatcher(method_member_matcher, &method_member_rewriter); | 1318 match_finder.addMatcher(method_member_matcher, &method_member_rewriter); |
| 1179 | 1319 |
| 1180 // Initializers ======== | 1320 // Initializers ======== |
| 1181 // Given | 1321 // Given |
| 1182 // struct S { | 1322 // struct S { |
| 1183 // int x; | 1323 // int x; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1332 // }; | 1472 // }; |
| 1333 // matches |T::foo| and |x.bar|. | 1473 // matches |T::foo| and |x.bar|. |
| 1334 auto cxx_dependent_scope_member_expr_matcher = | 1474 auto cxx_dependent_scope_member_expr_matcher = |
| 1335 expr(id("expr", cxxDependentScopeMemberExpr( | 1475 expr(id("expr", cxxDependentScopeMemberExpr( |
| 1336 hasMemberFromType(blink_qual_type_matcher)))); | 1476 hasMemberFromType(blink_qual_type_matcher)))); |
| 1337 CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( | 1477 CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( |
| 1338 &replacements); | 1478 &replacements); |
| 1339 match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, | 1479 match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, |
| 1340 &cxx_dependent_scope_member_expr_rewriter); | 1480 &cxx_dependent_scope_member_expr_rewriter); |
| 1341 | 1481 |
| 1482 // GMock calls lookup ======== | |
| 1483 // Given | |
| 1484 // EXPECT_CALL(obj, myMethod(...)) | |
| 1485 // will match obj.gmock_myMethod(...) call generated by the macro | |
| 1486 // (but only if it mocks a Blink method). | |
| 1487 auto gmock_member_matcher = | |
| 1488 id("expr", memberExpr(hasDeclaration( | |
| 1489 decl(cxxMethodDecl(mocksMethod(method_decl_matcher)))))); | |
| 1490 GMockMemberRewriter gmock_member_rewriter(&replacements); | |
| 1491 match_finder.addMatcher(gmock_member_matcher, &gmock_member_rewriter); | |
| 1492 | |
| 1493 // Run all the matchers. | |
| 1342 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = | 1494 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = |
| 1343 clang::tooling::newFrontendActionFactory(&match_finder); | 1495 clang::tooling::newFrontendActionFactory(&match_finder); |
| 1344 int result = tool.run(factory.get()); | 1496 int result = tool.run(factory.get()); |
| 1345 if (result != 0) | 1497 if (result != 0) |
| 1346 return result; | 1498 return result; |
| 1347 | 1499 |
| 1348 // Supplemental data for the Blink rename rebase helper. | 1500 // Supplemental data for the Blink rename rebase helper. |
| 1349 // TODO(dcheng): There's a lot of match rewriters missing from this list. | 1501 // TODO(dcheng): There's a lot of match rewriters missing from this list. |
| 1350 llvm::outs() << "==== BEGIN TRACKED EDITS ====\n"; | 1502 llvm::outs() << "==== BEGIN TRACKED EDITS ====\n"; |
| 1351 field_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); | 1503 field_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); |
| 1352 var_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); | 1504 var_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); |
| 1353 enum_member_decl_rewriter.edit_tracker().SerializeTo("enu", llvm::outs()); | 1505 enum_member_decl_rewriter.edit_tracker().SerializeTo("enu", llvm::outs()); |
| 1354 function_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); | 1506 function_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); |
| 1355 method_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); | 1507 method_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); |
| 1356 llvm::outs() << "==== END TRACKED EDITS ====\n"; | 1508 llvm::outs() << "==== END TRACKED EDITS ====\n"; |
| 1357 | 1509 |
| 1358 // Serialization format is documented in tools/clang/scripts/run_tool.py | 1510 // Serialization format is documented in tools/clang/scripts/run_tool.py |
| 1359 llvm::outs() << "==== BEGIN EDITS ====\n"; | 1511 llvm::outs() << "==== BEGIN EDITS ====\n"; |
| 1360 for (const auto& r : replacements) { | 1512 for (const auto& r : replacements) { |
| 1361 std::string replacement_text = r.getReplacementText().str(); | 1513 std::string replacement_text = r.getReplacementText().str(); |
| 1362 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 1514 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
| 1363 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 1515 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
| 1364 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 1516 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
| 1365 } | 1517 } |
| 1366 llvm::outs() << "==== END EDITS ====\n"; | 1518 llvm::outs() << "==== END EDITS ====\n"; |
| 1367 | 1519 |
| 1368 return 0; | 1520 return 0; |
| 1369 } | 1521 } |
| OLD | NEW |