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: |
| 11 // const int maxThings => const int kMaxThings | 11 // const int maxThings => const int kMaxThings |
| 12 // free functions and methods: | 12 // free functions and methods: |
| 13 // void doThisThenThat() => void DoThisAndThat() | 13 // void doThisThenThat() => void DoThisAndThat() |
| 14 | 14 |
| 15 #include <assert.h> | 15 #include <assert.h> |
| 16 #include <algorithm> | 16 #include <algorithm> |
| 17 #include <memory> | 17 #include <memory> |
| 18 #include <set> | 18 #include <set> |
| 19 #include <string> | 19 #include <string> |
| 20 | 20 |
| 21 #include "clang/AST/ASTContext.h" | 21 #include "clang/AST/ASTContext.h" |
| 22 #include "clang/ASTMatchers/ASTMatchFinder.h" | 22 #include "clang/ASTMatchers/ASTMatchFinder.h" |
| 23 #include "clang/ASTMatchers/ASTMatchers.h" | 23 #include "clang/ASTMatchers/ASTMatchers.h" |
| 24 #include "clang/ASTMatchers/ASTMatchersMacros.h" | 24 #include "clang/ASTMatchers/ASTMatchersMacros.h" |
| 25 #include "clang/Basic/CharInfo.h" | 25 #include "clang/Basic/CharInfo.h" |
| 26 #include "clang/Basic/SourceManager.h" | 26 #include "clang/Basic/SourceManager.h" |
| 27 #include "clang/Frontend/CompilerInstance.h" | |
| 27 #include "clang/Frontend/FrontendActions.h" | 28 #include "clang/Frontend/FrontendActions.h" |
| 29 #include "clang/Lex/MacroArgs.h" | |
| 28 #include "clang/Lex/Lexer.h" | 30 #include "clang/Lex/Lexer.h" |
| 31 #include "clang/Lex/PPCallbacks.h" | |
| 32 #include "clang/Lex/Preprocessor.h" | |
| 29 #include "clang/Tooling/CommonOptionsParser.h" | 33 #include "clang/Tooling/CommonOptionsParser.h" |
| 30 #include "clang/Tooling/Refactoring.h" | 34 #include "clang/Tooling/Refactoring.h" |
| 31 #include "clang/Tooling/Tooling.h" | 35 #include "clang/Tooling/Tooling.h" |
| 32 #include "llvm/Support/CommandLine.h" | 36 #include "llvm/Support/CommandLine.h" |
| 33 #include "llvm/Support/TargetSelect.h" | 37 #include "llvm/Support/TargetSelect.h" |
| 34 | 38 |
| 35 #include "EditTracker.h" | 39 #include "EditTracker.h" |
| 36 | 40 |
| 37 using namespace clang::ast_matchers; | 41 using namespace clang::ast_matchers; |
| 38 using clang::tooling::CommonOptionsParser; | 42 using clang::tooling::CommonOptionsParser; |
| 39 using clang::tooling::Replacement; | 43 using clang::tooling::Replacement; |
| 40 using llvm::StringRef; | 44 using llvm::StringRef; |
| 41 | 45 |
| 42 namespace { | 46 namespace { |
| 43 | 47 |
| 44 const char kBlinkFieldPrefix[] = "m_"; | 48 const char kBlinkFieldPrefix[] = "m_"; |
| 45 const char kBlinkStaticMemberPrefix[] = "s_"; | 49 const char kBlinkStaticMemberPrefix[] = "s_"; |
| 46 const char kGeneratedFileRegex[] = "^gen/|/gen/"; | 50 const char kGeneratedFileRegex[] = "^gen/|/gen/"; |
| 51 const char kGMockMethodNamePrefix[] = "gmock_"; | |
| 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()) | |
|
dcheng
2017/01/09 19:27:47
It's too bad it's not easy to do something like us
Łukasz Anforowicz
2017/01/09 20:11:27
Acknowledged.
| |
| 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 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 786 StringRef actual_old_text = clang::Lexer::getSourceText( | 826 StringRef actual_old_text = clang::Lexer::getSourceText( |
| 787 range, source_manager, context.getLangOpts()); | 827 range, source_manager, context.getLangOpts()); |
| 788 if (actual_old_text != expected_old_text) | 828 if (actual_old_text != expected_old_text) |
| 789 return false; | 829 return false; |
| 790 | 830 |
| 791 if (replacement) | 831 if (replacement) |
| 792 *replacement = Replacement(source_manager, range, new_text); | 832 *replacement = Replacement(source_manager, range, new_text); |
| 793 return true; | 833 return true; |
| 794 } | 834 } |
| 795 | 835 |
| 836 virtual clang::SourceLocation GetTargetLoc( | |
| 837 const MatchFinder::MatchResult& result) { | |
| 838 return TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | |
| 839 } | |
| 840 | |
| 796 void AddReplacement(const MatchFinder::MatchResult& result, | 841 void AddReplacement(const MatchFinder::MatchResult& result, |
| 797 llvm::StringRef old_name, | 842 llvm::StringRef old_name, |
| 798 std::string new_name) { | 843 std::string new_name) { |
| 799 if (old_name == new_name) | 844 if (old_name == new_name) |
| 800 return; | 845 return; |
| 801 | 846 |
| 802 clang::SourceLocation loc = | 847 clang::SourceLocation loc = GetTargetLoc(result); |
| 803 TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | 848 if (loc.isInvalid()) |
| 849 return; | |
| 804 | 850 |
| 805 Replacement replacement; | 851 Replacement replacement; |
| 806 if (!GenerateReplacement(result, loc, old_name, new_name, &replacement)) | 852 if (!GenerateReplacement(result, loc, old_name, new_name, &replacement)) |
| 807 return; | 853 return; |
| 808 | 854 |
| 809 replacements_->insert(std::move(replacement)); | 855 replacements_->insert(std::move(replacement)); |
| 810 edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name); | 856 edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name); |
| 811 } | 857 } |
| 812 | 858 |
| 813 const EditTracker& edit_tracker() const { return edit_tracker_; } | 859 const EditTracker& edit_tracker() const { return edit_tracker_; } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 876 using EnumConstantDeclRefRewriter = | 922 using EnumConstantDeclRefRewriter = |
| 877 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; | 923 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; |
| 878 | 924 |
| 879 using UnresolvedLookupRewriter = | 925 using UnresolvedLookupRewriter = |
| 880 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; | 926 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; |
| 881 using UnresolvedMemberRewriter = | 927 using UnresolvedMemberRewriter = |
| 882 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | 928 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; |
| 883 | 929 |
| 884 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; | 930 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; |
| 885 | 931 |
| 932 class GMockMemberRewriter | |
| 933 : public DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr> { | |
| 934 public: | |
| 935 using Base = DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; | |
| 936 | |
| 937 explicit GMockMemberRewriter(std::set<Replacement>* replacements) | |
| 938 : Base(replacements) {} | |
| 939 | |
| 940 std::unique_ptr<clang::PPCallbacks> CreatePreprocessorCallbacks() { | |
| 941 return llvm::make_unique<GMockMemberRewriter::PPCallbacks>(this); | |
| 942 } | |
| 943 | |
| 944 clang::SourceLocation GetTargetLoc( | |
| 945 const MatchFinder::MatchResult& result) override { | |
| 946 // Find location of the gmock_##MockedMethod identifier. | |
| 947 clang::SourceLocation target_loc = Base::GetTargetLoc(result); | |
| 948 | |
| 949 // Find location of EXPECT_CALL macro invocation. | |
| 950 clang::SourceLocation macro_call_loc = | |
| 951 result.SourceManager->getExpansionLoc(target_loc); | |
| 952 | |
| 953 // Map |macro_call_loc| to argument location (location of the method name | |
| 954 // that needs renaming). | |
| 955 auto it = expect_call_to_2nd_arg.find(macro_call_loc); | |
| 956 if (it == expect_call_to_2nd_arg.end()) | |
| 957 return clang::SourceLocation(); | |
| 958 return it->second; | |
| 959 } | |
| 960 | |
| 961 private: | |
| 962 std::map<clang::SourceLocation, clang::SourceLocation> expect_call_to_2nd_arg; | |
| 963 | |
| 964 // Called from PPCallbacks with the locations of EXPECT_CALL macro invocation: | |
| 965 // Example: | |
| 966 // EXPECT_CALL(my_mock, myMethod(123, 456)); | |
| 967 // ^- expansion_loc ^- actual_arg_loc | |
| 968 void RecordExpectCallMacroInvocation(clang::SourceLocation expansion_loc, | |
| 969 clang::SourceLocation second_arg_loc) { | |
| 970 expect_call_to_2nd_arg[expansion_loc] = second_arg_loc; | |
| 971 } | |
| 972 | |
| 973 class PPCallbacks : public clang::PPCallbacks { | |
| 974 public: | |
| 975 PPCallbacks(GMockMemberRewriter* rewriter) : rewriter_(rewriter) {} | |
|
dcheng
2017/01/09 19:27:47
Nit: explicit
Łukasz Anforowicz
2017/01/09 20:11:27
Ooops. Done.
| |
| 976 ~PPCallbacks() override {} | |
| 977 void MacroExpands(const clang::Token& name, | |
| 978 const clang::MacroDefinition& def, | |
| 979 clang::SourceRange range, | |
| 980 const clang::MacroArgs* args) override { | |
| 981 clang::IdentifierInfo* id = name.getIdentifierInfo(); | |
| 982 if (!id) | |
| 983 return; | |
| 984 | |
| 985 if (id->getName() != "EXPECT_CALL") | |
| 986 return; | |
| 987 | |
| 988 if (def.getMacroInfo()->getNumArgs() != 2) | |
| 989 return; | |
| 990 | |
| 991 // TODO(lukasza): Should check if def.getMacroInfo()->getDefinitionLoc() | |
| 992 // is in testing/gmock/include/gmock/gmock-spec-builders.h but I don't | |
| 993 // know how to get clang::SourceManager to call getFileName. | |
| 994 | |
| 995 rewriter_->RecordExpectCallMacroInvocation( | |
| 996 name.getLocation(), args->getUnexpArgument(1)->getLocation()); | |
| 997 } | |
| 998 | |
| 999 private: | |
| 1000 GMockMemberRewriter* rewriter_; | |
| 1001 }; | |
| 1002 }; | |
| 1003 | |
| 886 clang::DeclarationName GetUnresolvedName( | 1004 clang::DeclarationName GetUnresolvedName( |
| 887 const clang::UnresolvedMemberExpr& expr) { | 1005 const clang::UnresolvedMemberExpr& expr) { |
| 888 return expr.getMemberName(); | 1006 return expr.getMemberName(); |
| 889 } | 1007 } |
| 890 | 1008 |
| 891 clang::DeclarationName GetUnresolvedName( | 1009 clang::DeclarationName GetUnresolvedName( |
| 892 const clang::DependentScopeDeclRefExpr& expr) { | 1010 const clang::DependentScopeDeclRefExpr& expr) { |
| 893 return expr.getDeclName(); | 1011 return expr.getDeclName(); |
| 894 } | 1012 } |
| 895 | 1013 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1013 | 1131 |
| 1014 using UnresolvedUsingValueDeclRewriter = | 1132 using UnresolvedUsingValueDeclRewriter = |
| 1015 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; | 1133 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; |
| 1016 | 1134 |
| 1017 using DependentScopeDeclRefExprRewriter = | 1135 using DependentScopeDeclRefExprRewriter = |
| 1018 UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>; | 1136 UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>; |
| 1019 | 1137 |
| 1020 using CXXDependentScopeMemberExprRewriter = | 1138 using CXXDependentScopeMemberExprRewriter = |
| 1021 UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>; | 1139 UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>; |
| 1022 | 1140 |
| 1141 class SourceFileCallbacks : public clang::tooling::SourceFileCallbacks { | |
| 1142 public: | |
| 1143 SourceFileCallbacks() : source_counter_(0) {} | |
| 1144 ~SourceFileCallbacks() override {} | |
| 1145 | |
| 1146 void AddPPCallbacks(std::unique_ptr<clang::PPCallbacks> new_callbacks) { | |
| 1147 if (!pp_callbacks_) { | |
| 1148 pp_callbacks_ = std::move(new_callbacks); | |
| 1149 } else { | |
| 1150 pp_callbacks_ = llvm::make_unique<clang::PPChainedCallbacks>( | |
| 1151 std::move(new_callbacks), std::move(pp_callbacks_)); | |
|
dcheng
2017/01/09 19:27:47
Do we need chaining support? It seems like we our
Łukasz Anforowicz
2017/01/09 20:11:27
Done.
| |
| 1152 } | |
| 1153 } | |
| 1154 | |
| 1155 // clang::tooling::SourceFileCallbacks override: | |
| 1156 bool handleBeginSource(clang::CompilerInstance& compiler, | |
| 1157 llvm::StringRef Filename) override { | |
| 1158 source_counter_++; | |
| 1159 assert(source_counter_ == 1); // We only have *one* pp_callbacks_. | |
|
dcheng
2017/01/09 19:27:47
What happens if the tool is run on multiple files
Łukasz Anforowicz
2017/01/09 20:11:27
Fixed by creating a new PPCallbacks every time.
| |
| 1160 | |
| 1161 if (pp_callbacks_) | |
| 1162 compiler.getPreprocessor().addPPCallbacks(std::move(pp_callbacks_)); | |
|
dcheng
2017/01/09 19:27:47
Similarly, I think we should be able to assert pp_
Łukasz Anforowicz
2017/01/09 20:11:27
See above - we are now creating a new PPCallbacks
| |
| 1163 | |
| 1164 return true; | |
| 1165 } | |
| 1166 | |
| 1167 private: | |
| 1168 int source_counter_; | |
| 1169 std::unique_ptr<clang::PPCallbacks> pp_callbacks_; | |
| 1170 }; | |
| 1171 | |
| 1023 } // namespace | 1172 } // namespace |
| 1024 | 1173 |
| 1025 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); | 1174 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); |
| 1026 | 1175 |
| 1027 int main(int argc, const char* argv[]) { | 1176 int main(int argc, const char* argv[]) { |
| 1028 // TODO(dcheng): Clang tooling should do this itself. | 1177 // TODO(dcheng): Clang tooling should do this itself. |
| 1029 // http://llvm.org/bugs/show_bug.cgi?id=21627 | 1178 // http://llvm.org/bugs/show_bug.cgi?id=21627 |
| 1030 llvm::InitializeNativeTarget(); | 1179 llvm::InitializeNativeTarget(); |
| 1031 llvm::InitializeNativeTargetAsmParser(); | 1180 llvm::InitializeNativeTargetAsmParser(); |
| 1032 llvm::cl::OptionCategory category( | 1181 llvm::cl::OptionCategory category( |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1198 // same method. | 1347 // same method. |
| 1199 is_blink_method)); | 1348 is_blink_method)); |
| 1200 MethodDeclRewriter method_decl_rewriter(&replacements); | 1349 MethodDeclRewriter method_decl_rewriter(&replacements); |
| 1201 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); | 1350 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); |
| 1202 | 1351 |
| 1203 // Method references in a non-member context ======== | 1352 // Method references in a non-member context ======== |
| 1204 // Given | 1353 // Given |
| 1205 // S s; | 1354 // S s; |
| 1206 // s.g(); | 1355 // s.g(); |
| 1207 // void (S::*p)() = &S::g; | 1356 // void (S::*p)() = &S::g; |
| 1208 // matches |&S::g| but not |s.g()|. | 1357 // matches |&S::g| but not |s.g|. |
| 1209 auto method_ref_matcher = id( | 1358 auto method_ref_matcher = id( |
| 1210 "expr", declRefExpr(to(method_decl_matcher), | 1359 "expr", declRefExpr(to(method_decl_matcher), |
| 1211 // Ignore template substitutions. | 1360 // Ignore template substitutions. |
| 1212 unless(hasAncestor(substNonTypeTemplateParmExpr())))); | 1361 unless(hasAncestor(substNonTypeTemplateParmExpr())))); |
| 1213 | 1362 |
| 1214 MethodRefRewriter method_ref_rewriter(&replacements); | 1363 MethodRefRewriter method_ref_rewriter(&replacements); |
| 1215 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); | 1364 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); |
| 1216 | 1365 |
| 1217 // Method references in a member context ======== | 1366 // Method references in a member context ======== |
| 1218 // Given | 1367 // Given |
| 1219 // S s; | 1368 // S s; |
| 1220 // s.g(); | 1369 // s.g(); |
| 1221 // void (S::*p)() = &S::g; | 1370 // void (S::*p)() = &S::g; |
| 1222 // matches |s.g()| but not |&S::g|. | 1371 // matches |s.g| but not |&S::g|. |
| 1223 auto method_member_matcher = | 1372 auto method_member_matcher = |
| 1224 id("expr", memberExpr(member(method_decl_matcher))); | 1373 id("expr", memberExpr(member(method_decl_matcher))); |
| 1225 | 1374 |
| 1226 MethodMemberRewriter method_member_rewriter(&replacements); | 1375 MethodMemberRewriter method_member_rewriter(&replacements); |
| 1227 match_finder.addMatcher(method_member_matcher, &method_member_rewriter); | 1376 match_finder.addMatcher(method_member_matcher, &method_member_rewriter); |
| 1228 | 1377 |
| 1229 // Initializers ======== | 1378 // Initializers ======== |
| 1230 // Given | 1379 // Given |
| 1231 // struct S { | 1380 // struct S { |
| 1232 // int x; | 1381 // int x; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1381 // }; | 1530 // }; |
| 1382 // matches |T::foo| and |x.bar|. | 1531 // matches |T::foo| and |x.bar|. |
| 1383 auto cxx_dependent_scope_member_expr_matcher = | 1532 auto cxx_dependent_scope_member_expr_matcher = |
| 1384 expr(id("expr", cxxDependentScopeMemberExpr( | 1533 expr(id("expr", cxxDependentScopeMemberExpr( |
| 1385 hasMemberFromType(blink_qual_type_matcher)))); | 1534 hasMemberFromType(blink_qual_type_matcher)))); |
| 1386 CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( | 1535 CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( |
| 1387 &replacements); | 1536 &replacements); |
| 1388 match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, | 1537 match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, |
| 1389 &cxx_dependent_scope_member_expr_rewriter); | 1538 &cxx_dependent_scope_member_expr_rewriter); |
| 1390 | 1539 |
| 1540 // GMock calls lookup ======== | |
| 1541 // Given | |
| 1542 // EXPECT_CALL(obj, myMethod(...)) | |
| 1543 // will match obj.gmock_myMethod(...) call generated by the macro | |
| 1544 // (but only if it mocks a Blink method). | |
| 1545 auto gmock_member_matcher = | |
| 1546 id("expr", memberExpr(hasDeclaration( | |
| 1547 decl(cxxMethodDecl(mocksMethod(method_decl_matcher)))))); | |
| 1548 GMockMemberRewriter gmock_member_rewriter(&replacements); | |
| 1549 match_finder.addMatcher(gmock_member_matcher, &gmock_member_rewriter); | |
| 1550 | |
| 1551 // Run all the matchers. | |
|
dcheng
2017/01/09 19:27:47
This comment seems a bit out-of-place, since it lo
Łukasz Anforowicz
2017/01/09 20:11:27
I changed the comment - does it look better now?
| |
| 1552 SourceFileCallbacks source_file_callbacks; | |
| 1553 source_file_callbacks.AddPPCallbacks( | |
| 1554 gmock_member_rewriter.CreatePreprocessorCallbacks()); | |
| 1391 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = | 1555 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = |
| 1392 clang::tooling::newFrontendActionFactory(&match_finder); | 1556 clang::tooling::newFrontendActionFactory(&match_finder, |
| 1557 &source_file_callbacks); | |
| 1393 int result = tool.run(factory.get()); | 1558 int result = tool.run(factory.get()); |
| 1394 if (result != 0) | 1559 if (result != 0) |
| 1395 return result; | 1560 return result; |
| 1396 | 1561 |
| 1397 // Supplemental data for the Blink rename rebase helper. | 1562 // Supplemental data for the Blink rename rebase helper. |
| 1398 // TODO(dcheng): There's a lot of match rewriters missing from this list. | 1563 // TODO(dcheng): There's a lot of match rewriters missing from this list. |
| 1399 llvm::outs() << "==== BEGIN TRACKED EDITS ====\n"; | 1564 llvm::outs() << "==== BEGIN TRACKED EDITS ====\n"; |
| 1400 field_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); | 1565 field_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); |
| 1401 var_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); | 1566 var_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs()); |
| 1402 enum_member_decl_rewriter.edit_tracker().SerializeTo("enu", llvm::outs()); | 1567 enum_member_decl_rewriter.edit_tracker().SerializeTo("enu", llvm::outs()); |
| 1403 function_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); | 1568 function_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); |
| 1404 method_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); | 1569 method_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs()); |
| 1405 llvm::outs() << "==== END TRACKED EDITS ====\n"; | 1570 llvm::outs() << "==== END TRACKED EDITS ====\n"; |
| 1406 | 1571 |
| 1407 // Serialization format is documented in tools/clang/scripts/run_tool.py | 1572 // Serialization format is documented in tools/clang/scripts/run_tool.py |
| 1408 llvm::outs() << "==== BEGIN EDITS ====\n"; | 1573 llvm::outs() << "==== BEGIN EDITS ====\n"; |
| 1409 for (const auto& r : replacements) { | 1574 for (const auto& r : replacements) { |
| 1410 std::string replacement_text = r.getReplacementText().str(); | 1575 std::string replacement_text = r.getReplacementText().str(); |
| 1411 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 1576 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
| 1412 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 1577 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
| 1413 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 1578 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
| 1414 } | 1579 } |
| 1415 llvm::outs() << "==== END EDITS ====\n"; | 1580 llvm::outs() << "==== END EDITS ====\n"; |
| 1416 | 1581 |
| 1417 return 0; | 1582 return 0; |
| 1418 } | 1583 } |
| OLD | NEW |