• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 //
5 // Changes Blink-style names to Chrome-style names. Currently transforms:
6 //   fields:
7 //     int m_operationCount => int operation_count_
8 //   variables (including parameters):
9 //     int mySuperVariable => int my_super_variable
10 //   constants:
11 //     const int maxThings => const int kMaxThings
12 //   free functions and methods:
13 //     void doThisThenThat() => void DoThisAndThat()
14 
15 #include <assert.h>
16 #include <algorithm>
17 #include <memory>
18 #include <set>
19 #include <string>
20 
21 #include "clang/AST/ASTContext.h"
22 #include "clang/ASTMatchers/ASTMatchFinder.h"
23 #include "clang/ASTMatchers/ASTMatchers.h"
24 #include "clang/ASTMatchers/ASTMatchersMacros.h"
25 #include "clang/Basic/CharInfo.h"
26 #include "clang/Basic/SourceManager.h"
27 #include "clang/Frontend/CompilerInstance.h"
28 #include "clang/Frontend/FrontendActions.h"
29 #include "clang/Lex/MacroArgs.h"
30 #include "clang/Lex/Lexer.h"
31 #include "clang/Lex/PPCallbacks.h"
32 #include "clang/Lex/Preprocessor.h"
33 #include "clang/Tooling/CommonOptionsParser.h"
34 #include "clang/Tooling/Refactoring.h"
35 #include "clang/Tooling/Tooling.h"
36 #include "llvm/Support/CommandLine.h"
37 #include "llvm/Support/TargetSelect.h"
38 
39 #include "EditTracker.h"
40 
41 using namespace clang::ast_matchers;
42 using clang::tooling::CommonOptionsParser;
43 using clang::tooling::Replacement;
44 using llvm::StringRef;
45 
46 namespace {
47 
48 const char kBlinkFieldPrefix[] = "m_";
49 const char kBlinkStaticMemberPrefix[] = "s_";
50 const char kGeneratedFileRegex[] = "^gen/|/gen/";
51 const char kGMockMethodNamePrefix[] = "gmock_";
52 
53 template <typename MatcherType, typename NodeType>
IsMatching(const MatcherType & matcher,const NodeType & node,clang::ASTContext & context)54 bool IsMatching(const MatcherType& matcher,
55                 const NodeType& node,
56                 clang::ASTContext& context) {
57   return !match(matcher, node, context).empty();
58 }
59 
60 const clang::ast_matchers::internal::
61     VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr>
62         unresolvedMemberExpr;
63 
64 const clang::ast_matchers::internal::
65     VariadicDynCastAllOfMatcher<clang::Expr, clang::DependentScopeDeclRefExpr>
66         dependentScopeDeclRefExpr;
67 
68 const clang::ast_matchers::internal::
69     VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXDependentScopeMemberExpr>
70         cxxDependentScopeMemberExpr;
71 
AST_MATCHER(clang::FunctionDecl,isOverloadedOperator)72 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) {
73   return Node.isOverloadedOperator();
74 }
75 
AST_MATCHER(clang::CXXMethodDecl,isInstanceMethod)76 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) {
77   return Node.isInstance();
78 }
79 
AST_MATCHER_P(clang::FunctionTemplateDecl,templatedDecl,clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,InnerMatcher)80 AST_MATCHER_P(clang::FunctionTemplateDecl,
81               templatedDecl,
82               clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,
83               InnerMatcher) {
84   return InnerMatcher.matches(*Node.getTemplatedDecl(), Finder, Builder);
85 }
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).
AST_MATCHER_P(clang::CXXMethodDecl,mocksMethod,clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,InnerMatcher)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 
122 // If |InnerMatcher| matches |top|, then the returned matcher will match:
123 // - |top::function|
124 // - |top::Class::method|
125 // - |top::internal::Class::method|
AST_MATCHER_P(clang::NestedNameSpecifier,hasTopLevelPrefix,clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,InnerMatcher)126 AST_MATCHER_P(
127     clang::NestedNameSpecifier,
128     hasTopLevelPrefix,
129     clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,
130     InnerMatcher) {
131   const clang::NestedNameSpecifier* NodeToMatch = &Node;
132   while (NodeToMatch->getPrefix())
133     NodeToMatch = NodeToMatch->getPrefix();
134   return InnerMatcher.matches(*NodeToMatch, Finder, Builder);
135 }
136 
137 // This will narrow CXXCtorInitializers down for both FieldDecls and
138 // IndirectFieldDecls (ie. anonymous unions and such). In both cases
139 // getAnyMember() will return a FieldDecl which we can match against.
AST_MATCHER_P(clang::CXXCtorInitializer,forAnyField,clang::ast_matchers::internal::Matcher<clang::FieldDecl>,InnerMatcher)140 AST_MATCHER_P(clang::CXXCtorInitializer,
141               forAnyField,
142               clang::ast_matchers::internal::Matcher<clang::FieldDecl>,
143               InnerMatcher) {
144   const clang::FieldDecl* NodeAsDecl = Node.getAnyMember();
145   return (NodeAsDecl != nullptr &&
146           InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
147 }
148 
149 // Matches if all the overloads in the lookup set match the provided matcher.
AST_MATCHER_P(clang::OverloadExpr,allOverloadsMatch,clang::ast_matchers::internal::Matcher<clang::NamedDecl>,InnerMatcher)150 AST_MATCHER_P(clang::OverloadExpr,
151               allOverloadsMatch,
152               clang::ast_matchers::internal::Matcher<clang::NamedDecl>,
153               InnerMatcher) {
154   if (Node.getNumDecls() == 0)
155     return false;
156 
157   for (clang::NamedDecl* decl : Node.decls()) {
158     if (!InnerMatcher.matches(*decl, Finder, Builder))
159       return false;
160   }
161   return true;
162 }
163 
PrintForDiagnostics(clang::raw_ostream & os,const clang::FunctionDecl & decl)164 void PrintForDiagnostics(clang::raw_ostream& os,
165                          const clang::FunctionDecl& decl) {
166   decl.getLocStart().print(os, decl.getASTContext().getSourceManager());
167   os << ": ";
168   decl.getNameForDiagnostic(os, decl.getASTContext().getPrintingPolicy(), true);
169 }
170 
171 template <typename T>
MatchAllOverriddenMethods(const clang::CXXMethodDecl & decl,T && inner_matcher,clang::ast_matchers::internal::ASTMatchFinder * finder,clang::ast_matchers::internal::BoundNodesTreeBuilder * builder)172 bool MatchAllOverriddenMethods(
173     const clang::CXXMethodDecl& decl,
174     T&& inner_matcher,
175     clang::ast_matchers::internal::ASTMatchFinder* finder,
176     clang::ast_matchers::internal::BoundNodesTreeBuilder* builder) {
177   bool override_matches = false;
178   bool override_not_matches = false;
179 
180   for (auto it = decl.begin_overridden_methods();
181        it != decl.end_overridden_methods(); ++it) {
182     if (MatchAllOverriddenMethods(**it, inner_matcher, finder, builder))
183       override_matches = true;
184     else
185       override_not_matches = true;
186   }
187 
188   // If this fires we have a class overriding a method that matches, and a
189   // method that does not match the inner matcher. In that case we will match
190   // one ancestor method but not the other. If we rename one of the and not the
191   // other it will break what this class overrides, disconnecting it from the
192   // one we did not rename which creates a behaviour change. So assert and
193   // demand the user to fix the code first (or add the method to our
194   // blacklist T_T).
195   if (override_matches && override_not_matches) {
196     // blink::InternalSettings::trace method overrides
197     // 1) blink::InternalSettingsGenerated::trace
198     //    (won't be renamed because it is in generated code)
199     // 2) blink::Supplement<blink::Page>::trace
200     //    (will be renamed).
201     // It is safe to rename blink::InternalSettings::trace, because
202     // both 1 and 2 will both be renamed (#1 via manual changes of the code
203     // generator for DOM bindings and #2 via the clang tool).
204     auto internal_settings_class_decl = cxxRecordDecl(
205         hasName("InternalSettings"),
206         hasParent(namespaceDecl(hasName("blink"),
207                                 hasParent(translationUnitDecl()))));
208     auto is_method_safe_to_rename = cxxMethodDecl(
209         hasName("trace"),
210         anyOf(hasParent(internal_settings_class_decl),  // in .h file
211               has(nestedNameSpecifier(specifiesType(    // in .cpp file
212                   hasDeclaration(internal_settings_class_decl))))));
213     if (IsMatching(is_method_safe_to_rename, decl, decl.getASTContext()))
214       return true;
215 
216     // For previously unknown conflicts, error out and require a human to
217     // analyse the problem (rather than falling back to a potentially unsafe /
218     // code semantics changing rename).
219     llvm::errs() << "ERROR: ";
220     PrintForDiagnostics(llvm::errs(), decl);
221     llvm::errs() << " method overrides "
222                  << "some virtual methods that will be automatically renamed "
223                  << "and some that won't be renamed.";
224     llvm::errs() << "\n";
225     for (auto it = decl.begin_overridden_methods();
226          it != decl.end_overridden_methods(); ++it) {
227       if (MatchAllOverriddenMethods(**it, inner_matcher, finder, builder))
228         llvm::errs() << "Overriden method that will be renamed: ";
229       else
230         llvm::errs() << "Overriden method that will not be renamed: ";
231       PrintForDiagnostics(llvm::errs(), **it);
232       llvm::errs() << "\n";
233     }
234     llvm::errs() << "\n";
235     assert(false);
236   }
237 
238   // If the method overrides something that doesn't match, so the method itself
239   // doesn't match.
240   if (override_not_matches)
241     return false;
242 
243   // If the method overrides something that matches, so the method ifself
244   // matches.
245   if (override_matches)
246     return true;
247 
248   return inner_matcher.matches(decl, finder, builder);
249 }
250 
AST_MATCHER_P(clang::CXXMethodDecl,includeAllOverriddenMethods,clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,InnerMatcher)251 AST_MATCHER_P(clang::CXXMethodDecl,
252               includeAllOverriddenMethods,
253               clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,
254               InnerMatcher) {
255   return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder);
256 }
257 
258 // Matches |T::m| and/or |x->T::m| and/or |x->m| CXXDependentScopeMemberExpr
259 // if member |m| comes from a type that matches the InnerMatcher.
AST_MATCHER_P(clang::CXXDependentScopeMemberExpr,hasMemberFromType,clang::ast_matchers::internal::Matcher<clang::QualType>,InnerMatcher)260 AST_MATCHER_P(clang::CXXDependentScopeMemberExpr,
261               hasMemberFromType,
262               clang::ast_matchers::internal::Matcher<clang::QualType>,
263               InnerMatcher) {
264   // Given |T::m| and/or |x->T::m| and/or |x->m| ...
265   if (clang::NestedNameSpecifier* nestedNameSpecifier = Node.getQualifier()) {
266     // ... if |T| is present, then InnerMatcher has to match |T|.
267     clang::QualType qualType(nestedNameSpecifier->getAsType(), 0);
268     return InnerMatcher.matches(qualType, Finder, Builder);
269   } else {
270     // ... if there is no |T|, then InnerMatcher has to match the type of |x|.
271     clang::Expr* base_expr = Node.isImplicitAccess() ? nullptr : Node.getBase();
272     return base_expr &&
273            InnerMatcher.matches(base_expr->getType(), Finder, Builder);
274   }
275 }
276 
277 // Matches |const Class<T>&| QualType if InnerMatcher matches |Class<T>|.
AST_MATCHER_P(clang::QualType,hasBaseType,clang::ast_matchers::internal::Matcher<clang::Type>,InnerMatcher)278 AST_MATCHER_P(clang::QualType,
279               hasBaseType,
280               clang::ast_matchers::internal::Matcher<clang::Type>,
281               InnerMatcher) {
282   const clang::Type* type = Node.getTypePtrOrNull();
283   return type && InnerMatcher.matches(*type, Finder, Builder);
284 }
285 
IsMethodOverrideOf(const clang::CXXMethodDecl & decl,const char * class_name)286 bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl,
287                         const char* class_name) {
288   if (decl.getParent()->getQualifiedNameAsString() == class_name)
289     return true;
290   for (auto it = decl.begin_overridden_methods();
291        it != decl.end_overridden_methods(); ++it) {
292     if (IsMethodOverrideOf(**it, class_name))
293       return true;
294   }
295   return false;
296 }
297 
IsBlacklistedFunctionName(llvm::StringRef name)298 bool IsBlacklistedFunctionName(llvm::StringRef name) {
299   // https://crbug.com/672902: Method names with an underscore are typically
300   // mimicked after std library / are typically not originating from Blink.
301   // Do not rewrite such names (like push_back, emplace_back, etc.).
302   if (name.find('_') != llvm::StringRef::npos)
303     return true;
304 
305   return false;
306 }
307 
IsBlacklistedFreeFunctionName(llvm::StringRef name)308 bool IsBlacklistedFreeFunctionName(llvm::StringRef name) {
309   // swap() functions should match the signature of std::swap for ADL tricks.
310   return name == "swap";
311 }
312 
IsBlacklistedInstanceMethodName(llvm::StringRef name)313 bool IsBlacklistedInstanceMethodName(llvm::StringRef name) {
314   static const char* kBlacklistedNames[] = {
315       // We should avoid renaming the method names listed below, because
316       // 1. They are used in templated code (e.g. in <algorithms>)
317       // 2. They (begin+end) are used in range-based for syntax sugar
318       //    - for (auto x : foo) { ... }  // <- foo.begin() will be called.
319       "begin", "end", "rbegin", "rend", "lock", "unlock", "try_lock",
320 
321       // https://crbug.com/672902: Should not rewrite names that mimick methods
322       // from std library.
323       "back", "empty", "erase", "front", "insert",
324   };
325   for (const auto& b : kBlacklistedNames) {
326     if (name == b)
327       return true;
328   }
329   return false;
330 }
331 
IsBlacklistedMethodName(llvm::StringRef name)332 bool IsBlacklistedMethodName(llvm::StringRef name) {
333   return IsBlacklistedFunctionName(name) ||
334          IsBlacklistedInstanceMethodName(name);
335 }
336 
IsBlacklistedFunction(const clang::FunctionDecl & decl)337 bool IsBlacklistedFunction(const clang::FunctionDecl& decl) {
338   clang::StringRef name = decl.getName();
339   return IsBlacklistedFunctionName(name) || IsBlacklistedFreeFunctionName(name);
340 }
341 
IsBlacklistedMethod(const clang::CXXMethodDecl & decl)342 bool IsBlacklistedMethod(const clang::CXXMethodDecl& decl) {
343   clang::StringRef name = decl.getName();
344   if (IsBlacklistedFunctionName(name))
345     return true;
346 
347   // Remaining cases are only applicable to instance methods.
348   if (decl.isStatic())
349     return false;
350 
351   if (IsBlacklistedInstanceMethodName(name))
352     return true;
353 
354   // Subclasses of InspectorAgent will subclass "disable()" from both blink and
355   // from gen/, which is problematic, but DevTools folks don't want to rename
356   // it or split this up. So don't rename it at all.
357   if (name.equals("disable") &&
358       IsMethodOverrideOf(decl, "blink::InspectorAgent"))
359     return true;
360 
361   return false;
362 }
363 
AST_MATCHER(clang::FunctionDecl,isBlacklistedFunction)364 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) {
365   return IsBlacklistedFunction(Node);
366 }
367 
AST_MATCHER(clang::CXXMethodDecl,isBlacklistedMethod)368 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) {
369   return IsBlacklistedMethod(Node);
370 }
371 
372 // Helper to convert from a camelCaseName to camel_case_name. It uses some
373 // heuristics to try to handle acronyms in camel case names correctly.
CamelCaseToUnderscoreCase(StringRef input)374 std::string CamelCaseToUnderscoreCase(StringRef input) {
375   std::string output;
376   bool needs_underscore = false;
377   bool was_lowercase = false;
378   bool was_uppercase = false;
379   bool first_char = true;
380   // Iterate in reverse to minimize the amount of backtracking.
381   for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin();
382        --i) {
383     char c = *i;
384     bool is_lowercase = clang::isLowercase(c);
385     bool is_uppercase = clang::isUppercase(c);
386     c = clang::toLowercase(c);
387     // Transitioning from upper to lower case requires an underscore. This is
388     // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_'
389     // in 'dH'. This is a complement to the non-acronym case further down.
390     if (was_uppercase && is_lowercase)
391       needs_underscore = true;
392     if (needs_underscore) {
393       output += '_';
394       needs_underscore = false;
395     }
396     output += c;
397     // Handles the non-acronym case: transitioning from lower to upper case
398     // requires an underscore when emitting the next character, e.g. didLoad
399     // needs a '_' in 'dL'.
400     if (!first_char && was_lowercase && is_uppercase)
401       needs_underscore = true;
402     was_lowercase = is_lowercase;
403     was_uppercase = is_uppercase;
404     first_char = false;
405   }
406   std::reverse(output.begin(), output.end());
407   return output;
408 }
409 
CanBeEvaluatedAtCompileTime(const clang::Stmt * stmt,const clang::ASTContext & context)410 bool CanBeEvaluatedAtCompileTime(const clang::Stmt* stmt,
411                                  const clang::ASTContext& context) {
412   auto* expr = clang::dyn_cast<clang::Expr>(stmt);
413   if (!expr) {
414     // If the statement is not an expression then it's a constant.
415     return true;
416   }
417 
418   // Function calls create non-consistent behaviour. For some template
419   // instantiations they can be constexpr while for others they are not, which
420   // changes the output of isEvaluatable().
421   if (expr->hasNonTrivialCall(context))
422     return false;
423 
424   // Recurse on children. If they are all const (or are uses of template
425   // input) then the statement can be considered const. For whatever reason the
426   // below checks can give different-and-less-consistent responses if we call
427   // them on a complex expression than if we call them on the most primitive
428   // pieces (some pieces would say false but the whole thing says true).
429   for (auto* child : expr->children()) {
430     if (!CanBeEvaluatedAtCompileTime(child, context))
431       return false;
432   }
433 
434   // If the expression depends on template input, we can not call
435   // isEvaluatable() on it as it will do bad things/crash.
436   if (!expr->isInstantiationDependent()) {
437     // If the expression can be evaluated at compile time, then it should have a
438     // kFoo style name. Otherwise, not.
439     return expr->isEvaluatable(context);
440   }
441 
442   // We do our best to figure out special cases as we come across them here, for
443   // template dependent situations. Some cases in code are only considered
444   // instantiation dependent for some template instantiations! Which is
445   // terrible! So most importantly we try to match isEvaluatable in those cases.
446   switch (expr->getStmtClass()) {
447     case clang::Stmt::CXXThisExprClass:
448       return false;
449     case clang::Stmt::DeclRefExprClass: {
450       auto* declref = clang::dyn_cast<clang::DeclRefExpr>(expr);
451       auto* decl = declref->getDecl();
452       if (auto* vardecl = clang::dyn_cast<clang::VarDecl>(decl)) {
453         if (auto* initializer = vardecl->getInit())
454           return CanBeEvaluatedAtCompileTime(initializer, context);
455         return false;
456       }
457       break;
458     }
459 
460     default:
461       break;
462   }
463 
464   // Otherwise, we consider depending on template parameters to not interfere
465   // with being const.. with exceptions hopefully covered above.
466   return true;
467 }
468 
IsProbablyConst(const clang::VarDecl & decl,const clang::ASTContext & context)469 bool IsProbablyConst(const clang::VarDecl& decl,
470                      const clang::ASTContext& context) {
471   clang::QualType type = decl.getType();
472   if (!type.isConstQualified())
473     return false;
474 
475   if (type.isVolatileQualified())
476     return false;
477 
478   if (decl.isConstexpr())
479     return true;
480 
481   // Parameters should not be renamed to |kFooBar| style (even if they are
482   // const and have an initializer (aka default value)).
483   if (clang::isa<clang::ParmVarDecl>(&decl))
484     return false;
485 
486   // http://google.github.io/styleguide/cppguide.html#Constant_Names
487   // Static variables that are const-qualified should use kConstantStyle naming.
488   if (decl.getStorageDuration() == clang::SD_Static)
489     return true;
490 
491   const clang::Expr* initializer = decl.getInit();
492   if (!initializer)
493     return false;
494 
495   return CanBeEvaluatedAtCompileTime(initializer, context);
496 }
497 
AST_MATCHER_P(clang::QualType,hasString,std::string,ExpectedString)498 AST_MATCHER_P(clang::QualType, hasString, std::string, ExpectedString) {
499   return ExpectedString == Node.getAsString();
500 }
501 
ShouldPrefixFunctionName(const std::string & old_method_name)502 bool ShouldPrefixFunctionName(const std::string& old_method_name) {
503   // Functions that are named similarily to a type - they should be prefixed
504   // with a "Get" prefix.
505   static const char* kConflictingMethods[] = {
506       "animationWorklet",
507       "audioWorklet",
508       "binaryType",
509       "blob",
510       "channelCountMode",
511       "color",
512       "counterDirectives",
513       "document",
514       "emptyChromeClient",
515       "emptyEditorClient",
516       "emptySpellCheckerClient",
517       "entryType",
518       "error",
519       "fileUtilities",
520       "font",
521       "frame",
522       "frameBlameContext",
523       "frontend",
524       "hash",
525       "heapObjectHeader",
526       "iconURL",
527       "inputMethodController",
528       "inputType",
529       "layout",
530       "layoutBlock",
531       "layoutObject",
532       "layoutSize",
533       "length",
534       "lineCap",
535       "lineEndings",
536       "lineJoin",
537       "listItems",
538       "matchedProperties",
539       "midpointState",
540       "mouseEvent",
541       "name",
542       "navigationType",
543       "node",
544       "outcome",
545       "pagePopup",
546       "paintWorklet",
547       "path",
548       "processingInstruction",
549       "readyState",
550       "relList",
551       "resource",
552       "response",
553       "sandboxSupport",
554       "screenInfo",
555       "scrollAnimator",
556       "settings",
557       "signalingState",
558       "state",
559       "string",
560       "styleSheet",
561       "text",
562       "textAlign",
563       "textBaseline",
564       "theme",
565       "thread",
566       "timing",
567       "topLevelBlameContext",
568       "vector",
569       "widget",
570       "wordBoundaries",
571       "wrapperTypeInfo",
572   };
573   for (const auto& conflicting_method : kConflictingMethods) {
574     if (old_method_name == conflicting_method)
575       return true;
576   }
577 
578   return false;
579 }
580 
AST_MATCHER(clang::FunctionDecl,shouldPrefixFunctionName)581 AST_MATCHER(clang::FunctionDecl, shouldPrefixFunctionName) {
582   return ShouldPrefixFunctionName(Node.getName().str());
583 }
584 
GetNameForDecl(const clang::FunctionDecl & decl,clang::ASTContext & context,std::string & name)585 bool GetNameForDecl(const clang::FunctionDecl& decl,
586                     clang::ASTContext& context,
587                     std::string& name) {
588   name = decl.getName().str();
589   name[0] = clang::toUppercase(name[0]);
590 
591   // Given
592   //   class Foo {};
593   //   class DerivedFoo : class Foo;
594   //   using Bar = Foo;
595   //   Bar f1();  // <- |Bar| would be matched by hasString("Bar") below.
596   //   Bar f2();  // <- |Bar| would be matched by hasName("Foo") below.
597   //   DerivedFoo f3();  // <- |DerivedFoo| matched by isDerivedFrom(...) below.
598   // |type_with_same_name_as_function| matcher matches Bar and Foo return types.
599   auto type_with_same_name_as_function = qualType(anyOf(
600       // hasString matches the type as spelled (Bar above).
601       hasString(name),
602       // hasDeclaration matches resolved type (Foo or DerivedFoo above).
603       hasDeclaration(namedDecl(hasName(name)))));
604 
605   // |type_containing_same_name_as_function| matcher will match all of the
606   // return types below:
607   // - Foo foo()  // Direct application of |type_with_same_name_as_function|.
608   // - Foo* foo()  // |hasDescendant| traverses references/pointers.
609   // - RefPtr<Foo> foo()  // |hasDescendant| traverses template arguments.
610   auto type_containing_same_name_as_function =
611       qualType(anyOf(type_with_same_name_as_function,
612                      hasDescendant(type_with_same_name_as_function)));
613   // https://crbug.com/582312: Prepend "Get" if method name conflicts with
614   // return type.
615   auto conflict_matcher = functionDecl(anyOf(
616       // For functions and non-virtual or base method implementations just
617       // compare with the immediate return type.
618       functionDecl(returns(type_containing_same_name_as_function),
619                    unless(cxxMethodDecl(isOverride()))),
620       // For methods that override one or more methods, compare with the return
621       // type of the *base* methods.
622       cxxMethodDecl(isOverride(), forEachOverridden(returns(
623                                       type_containing_same_name_as_function))),
624       // And also check hardcoded list of function names to prefix with "Get".
625       shouldPrefixFunctionName()));
626   if (IsMatching(conflict_matcher, decl, context))
627     name = "Get" + name;
628 
629   return true;
630 }
631 
GetNameForDecl(const clang::EnumConstantDecl & decl,clang::ASTContext & context,std::string & name)632 bool GetNameForDecl(const clang::EnumConstantDecl& decl,
633                     clang::ASTContext& context,
634                     std::string& name) {
635   StringRef original_name = decl.getName();
636 
637   // If it's already correct leave it alone.
638   if (original_name.size() >= 2 && original_name[0] == 'k' &&
639       clang::isUppercase(original_name[1]))
640     return false;
641 
642   bool is_shouty = true;
643   for (char c : original_name) {
644     if (!clang::isUppercase(c) && !clang::isDigit(c) && c != '_') {
645       is_shouty = false;
646       break;
647     }
648   }
649 
650   if (is_shouty)
651     return false;
652 
653   name = 'k';  // k prefix on enum values.
654   name += original_name;
655   name[1] = clang::toUppercase(name[1]);
656   return true;
657 }
658 
GetNameForDecl(const clang::FieldDecl & decl,clang::ASTContext & context,std::string & name)659 bool GetNameForDecl(const clang::FieldDecl& decl,
660                     clang::ASTContext& context,
661                     std::string& name) {
662   StringRef original_name = decl.getName();
663   bool member_prefix = original_name.startswith(kBlinkFieldPrefix);
664 
665   StringRef rename_part = !member_prefix
666                               ? original_name
667                               : original_name.substr(strlen(kBlinkFieldPrefix));
668   name = CamelCaseToUnderscoreCase(rename_part);
669 
670   // Assume that prefix of m_ was intentional and always replace it with a
671   // suffix _.
672   if (member_prefix && name.back() != '_')
673     name += '_';
674 
675   return true;
676 }
677 
GetNameForDecl(const clang::VarDecl & decl,clang::ASTContext & context,std::string & name)678 bool GetNameForDecl(const clang::VarDecl& decl,
679                     clang::ASTContext& context,
680                     std::string& name) {
681   StringRef original_name = decl.getName();
682 
683   // Nothing to do for unnamed parameters.
684   if (clang::isa<clang::ParmVarDecl>(decl)) {
685     if (original_name.empty())
686       return false;
687 
688     // Check if |decl| and |decl.getLocation| are in sync.  We need to skip
689     // out-of-sync ParmVarDecls to avoid renaming buggy ParmVarDecls that
690     // 1) have decl.getLocation() pointing at a parameter declaration without a
691     // name, but 2) have decl.getName() retained from a template specialization
692     // of a method.  See also: https://llvm.org/bugs/show_bug.cgi?id=29145
693     clang::SourceLocation loc =
694         context.getSourceManager().getSpellingLoc(decl.getLocation());
695     auto parents = context.getParents(decl);
696     bool is_child_location_within_parent_source_range = std::all_of(
697         parents.begin(), parents.end(),
698         [&loc](const clang::ast_type_traits::DynTypedNode& parent) {
699           clang::SourceLocation begin = parent.getSourceRange().getBegin();
700           clang::SourceLocation end = parent.getSourceRange().getEnd();
701           return (begin < loc) && (loc < end);
702         });
703     if (!is_child_location_within_parent_source_range)
704       return false;
705   }
706 
707   // static class members match against VarDecls. Blink style dictates that
708   // these should be prefixed with `s_`, so strip that off. Also check for `m_`
709   // and strip that off too, for code that accidentally uses the wrong prefix.
710   if (original_name.startswith(kBlinkStaticMemberPrefix))
711     original_name = original_name.substr(strlen(kBlinkStaticMemberPrefix));
712   else if (original_name.startswith(kBlinkFieldPrefix))
713     original_name = original_name.substr(strlen(kBlinkFieldPrefix));
714 
715   bool is_const = IsProbablyConst(decl, context);
716   if (is_const) {
717     // Don't try to rename constants that already conform to Chrome style.
718     if (original_name.size() >= 2 && original_name[0] == 'k' &&
719         clang::isUppercase(original_name[1]))
720       return false;
721     // Or names are spelt with underscore casing. While they are actually
722     // compile consts, the author wrote it explicitly as a variable not as
723     // a constant (they would have used kFormat otherwise here), so preserve
724     // it rather than try to mangle a kFormat out of it.
725     if (original_name.find('_') != StringRef::npos)
726       return false;
727 
728     name = 'k';
729     name.append(original_name.data(), original_name.size());
730     name[1] = clang::toUppercase(name[1]);
731   } else {
732     name = CamelCaseToUnderscoreCase(original_name);
733 
734     // Non-const variables with static storage duration at namespace scope are
735     // prefixed with `g_' to reduce the likelihood of a naming collision.
736     const clang::DeclContext* decl_context = decl.getDeclContext();
737     if (name.find("g_") != 0 && decl.hasGlobalStorage() &&
738         decl_context->isNamespace())
739       name.insert(0, "g_");
740   }
741 
742   // Static members end with _ just like other members, but constants should
743   // not.
744   if (!is_const && decl.isStaticDataMember()) {
745     name += '_';
746   }
747 
748   return true;
749 }
750 
GetNameForDecl(const clang::FunctionTemplateDecl & decl,clang::ASTContext & context,std::string & name)751 bool GetNameForDecl(const clang::FunctionTemplateDecl& decl,
752                     clang::ASTContext& context,
753                     std::string& name) {
754   clang::FunctionDecl* templated_function = decl.getTemplatedDecl();
755   return GetNameForDecl(*templated_function, context, name);
756 }
757 
GetNameForDecl(const clang::NamedDecl & decl,clang::ASTContext & context,std::string & name)758 bool GetNameForDecl(const clang::NamedDecl& decl,
759                     clang::ASTContext& context,
760                     std::string& name) {
761   if (auto* function = clang::dyn_cast<clang::FunctionDecl>(&decl))
762     return GetNameForDecl(*function, context, name);
763   if (auto* var = clang::dyn_cast<clang::VarDecl>(&decl))
764     return GetNameForDecl(*var, context, name);
765   if (auto* field = clang::dyn_cast<clang::FieldDecl>(&decl))
766     return GetNameForDecl(*field, context, name);
767   if (auto* function_template =
768           clang::dyn_cast<clang::FunctionTemplateDecl>(&decl))
769     return GetNameForDecl(*function_template, context, name);
770   if (auto* enumc = clang::dyn_cast<clang::EnumConstantDecl>(&decl))
771     return GetNameForDecl(*enumc, context, name);
772 
773   return false;
774 }
775 
GetNameForDecl(const clang::UsingDecl & decl,clang::ASTContext & context,std::string & name)776 bool GetNameForDecl(const clang::UsingDecl& decl,
777                     clang::ASTContext& context,
778                     std::string& name) {
779   assert(decl.shadow_size() > 0);
780 
781   // If a using declaration's targeted declaration is a set of overloaded
782   // functions, it can introduce multiple shadowed declarations. Just using the
783   // first one is OK, since overloaded functions have the same name, by
784   // definition.
785   return GetNameForDecl(*decl.shadow_begin()->getTargetDecl(), context, name);
786 }
787 
788 template <typename Type>
789 struct TargetNodeTraits;
790 
791 template <>
792 struct TargetNodeTraits<clang::NamedDecl> {
GetLoc__anon6b399b860111::TargetNodeTraits793   static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) {
794     return decl.getLocation();
795   }
GetName__anon6b399b860111::TargetNodeTraits796   static const char* GetName() { return "decl"; }
GetType__anon6b399b860111::TargetNodeTraits797   static const char* GetType() { return "NamedDecl"; }
798 };
799 
800 template <>
801 struct TargetNodeTraits<clang::MemberExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits802   static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) {
803     return expr.getMemberLoc();
804   }
GetName__anon6b399b860111::TargetNodeTraits805   static const char* GetName() { return "expr"; }
GetType__anon6b399b860111::TargetNodeTraits806   static const char* GetType() { return "MemberExpr"; }
807 };
808 
809 template <>
810 struct TargetNodeTraits<clang::DeclRefExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits811   static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) {
812     return expr.getLocation();
813   }
GetName__anon6b399b860111::TargetNodeTraits814   static const char* GetName() { return "expr"; }
GetType__anon6b399b860111::TargetNodeTraits815   static const char* GetType() { return "DeclRefExpr"; }
816 };
817 
818 template <>
819 struct TargetNodeTraits<clang::DependentScopeDeclRefExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits820   static clang::SourceLocation GetLoc(
821       const clang::DependentScopeDeclRefExpr& expr) {
822     return expr.getLocation();
823   }
GetName__anon6b399b860111::TargetNodeTraits824   static const char* GetName() { return "expr"; }
825 };
826 
827 template <>
828 struct TargetNodeTraits<clang::CXXDependentScopeMemberExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits829   static clang::SourceLocation GetLoc(
830       const clang::CXXDependentScopeMemberExpr& expr) {
831     return expr.getMemberLoc();
832   }
GetName__anon6b399b860111::TargetNodeTraits833   static const char* GetName() { return "expr"; }
834 };
835 
836 template <>
837 struct TargetNodeTraits<clang::CXXCtorInitializer> {
GetLoc__anon6b399b860111::TargetNodeTraits838   static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) {
839     assert(init.isWritten());
840     return init.getSourceLocation();
841   }
GetName__anon6b399b860111::TargetNodeTraits842   static const char* GetName() { return "initializer"; }
GetType__anon6b399b860111::TargetNodeTraits843   static const char* GetType() { return "CXXCtorInitializer"; }
844 };
845 
846 template <>
847 struct TargetNodeTraits<clang::UnresolvedLookupExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits848   static clang::SourceLocation GetLoc(const clang::UnresolvedLookupExpr& expr) {
849     return expr.getNameLoc();
850   }
GetName__anon6b399b860111::TargetNodeTraits851   static const char* GetName() { return "expr"; }
GetType__anon6b399b860111::TargetNodeTraits852   static const char* GetType() { return "UnresolvedLookupExpr"; }
853 };
854 
855 template <>
856 struct TargetNodeTraits<clang::UnresolvedMemberExpr> {
GetLoc__anon6b399b860111::TargetNodeTraits857   static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) {
858     return expr.getMemberLoc();
859   }
GetName__anon6b399b860111::TargetNodeTraits860   static const char* GetName() { return "expr"; }
GetType__anon6b399b860111::TargetNodeTraits861   static const char* GetType() { return "UnresolvedMemberExpr"; }
862 };
863 
864 template <>
865 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> {
GetLoc__anon6b399b860111::TargetNodeTraits866   static clang::SourceLocation GetLoc(
867       const clang::UnresolvedUsingValueDecl& decl) {
868     return decl.getNameInfo().getLoc();
869   }
GetName__anon6b399b860111::TargetNodeTraits870   static const char* GetName() { return "decl"; }
GetType__anon6b399b860111::TargetNodeTraits871   static const char* GetType() { return "UnresolvedUsingValueDecl"; }
872 };
873 
874 template <typename TargetNode>
875 class RewriterBase : public MatchFinder::MatchCallback {
876  public:
RewriterBase(std::set<Replacement> * replacements)877   explicit RewriterBase(std::set<Replacement>* replacements)
878       : replacements_(replacements) {}
879 
GetTargetNode(const MatchFinder::MatchResult & result)880   const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) {
881     const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>(
882         TargetNodeTraits<TargetNode>::GetName());
883     assert(target_node);
884     return *target_node;
885   }
886 
GenerateReplacement(const MatchFinder::MatchResult & result,clang::SourceLocation loc,llvm::StringRef old_name,std::string new_name,Replacement * replacement)887   bool GenerateReplacement(const MatchFinder::MatchResult& result,
888                            clang::SourceLocation loc,
889                            llvm::StringRef old_name,
890                            std::string new_name,
891                            Replacement* replacement) {
892     const clang::ASTContext& context = *result.Context;
893     const clang::SourceManager& source_manager = *result.SourceManager;
894 
895     if (loc.isMacroID()) {
896       // Try to jump "above" the scratch buffer if |loc| is inside
897       // token##Concatenation.
898       const int kMaxJumps = 5;
899       bool verified_out_of_scratch_space = false;
900       for (int i = 0; i < kMaxJumps && !verified_out_of_scratch_space; i++) {
901         clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
902         verified_out_of_scratch_space =
903             source_manager.getBufferName(spell) != "<scratch space>";
904         if (!verified_out_of_scratch_space)
905           loc = source_manager.getImmediateMacroCallerLoc(loc);
906       }
907       if (!verified_out_of_scratch_space)
908         return false;
909     }
910 
911     // If the edit affects only the first character of the identifier, then
912     // narrow down the edit to only this single character.  This is important
913     // for dealing with toFooBar -> ToFooBar method renaming when the method
914     // name is built using macro token concatenation like to##macroArgument - in
915     // this case we should only rewrite "t" -> "T" and leave "o##macroArgument"
916     // untouched.
917     llvm::StringRef expected_old_text = old_name;
918     llvm::StringRef new_text = new_name;
919     if (loc.isMacroID() && expected_old_text.substr(1) == new_text.substr(1)) {
920       expected_old_text = expected_old_text.substr(0, 1);
921       new_text = new_text.substr(0, 1);
922     }
923     clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
924     clang::CharSourceRange range = clang::CharSourceRange::getCharRange(
925         spell, spell.getLocWithOffset(expected_old_text.size()));
926 
927     // We need to ensure that |actual_old_text| is the same as
928     // |expected_old_text| - it can be different if |actual_old_text| contains
929     // a macro argument (see DEFINE_WITH_TOKEN_CONCATENATION2 in
930     // macros-original.cc testcase).
931     StringRef actual_old_text = clang::Lexer::getSourceText(
932         range, source_manager, context.getLangOpts());
933     if (actual_old_text != expected_old_text)
934       return false;
935 
936     if (replacement)
937       *replacement = Replacement(source_manager, range, new_text);
938     return true;
939   }
940 
GetTargetLoc(const MatchFinder::MatchResult & result)941   virtual clang::SourceLocation GetTargetLoc(
942       const MatchFinder::MatchResult& result) {
943     return TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result));
944   }
945 
AddReplacement(const MatchFinder::MatchResult & result,llvm::StringRef old_name,std::string new_name)946   void AddReplacement(const MatchFinder::MatchResult& result,
947                       llvm::StringRef old_name,
948                       std::string new_name) {
949     if (old_name == new_name)
950       return;
951 
952     clang::SourceLocation loc = GetTargetLoc(result);
953     if (loc.isInvalid())
954       return;
955 
956     Replacement replacement;
957     if (!GenerateReplacement(result, loc, old_name, new_name, &replacement))
958       return;
959 
960     replacements_->insert(std::move(replacement));
961     edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name);
962   }
963 
edit_tracker() const964   const EditTracker& edit_tracker() const { return edit_tracker_; }
965 
966  private:
967   std::set<Replacement>* const replacements_;
968   EditTracker edit_tracker_;
969 };
970 
971 template <typename DeclNode, typename TargetNode>
972 class DeclRewriterBase : public RewriterBase<TargetNode> {
973  public:
974   using Base = RewriterBase<TargetNode>;
975 
DeclRewriterBase(std::set<Replacement> * replacements)976   explicit DeclRewriterBase(std::set<Replacement>* replacements)
977       : Base(replacements) {}
978 
run(const MatchFinder::MatchResult & result)979   void run(const MatchFinder::MatchResult& result) override {
980     const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
981     assert(decl);
982     llvm::StringRef old_name = decl->getName();
983 
984     // Return early if there's no name to be renamed.
985     if (!decl->getIdentifier())
986       return;
987 
988     // Get the new name.
989     std::string new_name;
990     if (!GetNameForDecl(*decl, *result.Context, new_name))
991       return;  // If false, the name was not suitable for renaming.
992 
993     // Check if we are able to rewrite the decl (to avoid rewriting if the
994     // decl's identifier is part of macro##Token##Concatenation).
995     clang::SourceLocation decl_loc =
996         TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
997     if (!Base::GenerateReplacement(result, decl_loc, old_name, new_name,
998                                    nullptr))
999       return;
1000 
1001     Base::AddReplacement(result, old_name, std::move(new_name));
1002   }
1003 };
1004 
1005 using FieldDeclRewriter = DeclRewriterBase<clang::FieldDecl, clang::NamedDecl>;
1006 using VarDeclRewriter = DeclRewriterBase<clang::VarDecl, clang::NamedDecl>;
1007 using MemberRewriter = DeclRewriterBase<clang::FieldDecl, clang::MemberExpr>;
1008 using DeclRefRewriter = DeclRewriterBase<clang::VarDecl, clang::DeclRefExpr>;
1009 using FieldDeclRefRewriter =
1010     DeclRewriterBase<clang::FieldDecl, clang::DeclRefExpr>;
1011 using FunctionDeclRewriter =
1012     DeclRewriterBase<clang::FunctionDecl, clang::NamedDecl>;
1013 using FunctionRefRewriter =
1014     DeclRewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
1015 using ConstructorInitializerRewriter =
1016     DeclRewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
1017 
1018 using MethodDeclRewriter =
1019     DeclRewriterBase<clang::CXXMethodDecl, clang::NamedDecl>;
1020 using MethodRefRewriter =
1021     DeclRewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>;
1022 using MethodMemberRewriter =
1023     DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
1024 
1025 using EnumConstantDeclRewriter =
1026     DeclRewriterBase<clang::EnumConstantDecl, clang::NamedDecl>;
1027 using EnumConstantDeclRefRewriter =
1028     DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>;
1029 
1030 using UnresolvedLookupRewriter =
1031     DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>;
1032 using UnresolvedMemberRewriter =
1033     DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>;
1034 
1035 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>;
1036 
1037 class GMockMemberRewriter
1038     : public DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr> {
1039  public:
1040   using Base = DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
1041 
GMockMemberRewriter(std::set<Replacement> * replacements)1042   explicit GMockMemberRewriter(std::set<Replacement>* replacements)
1043       : Base(replacements) {}
1044 
CreatePreprocessorCallbacks()1045   std::unique_ptr<clang::PPCallbacks> CreatePreprocessorCallbacks() {
1046     return llvm::make_unique<GMockMemberRewriter::PPCallbacks>(this);
1047   }
1048 
GetTargetLoc(const MatchFinder::MatchResult & result)1049   clang::SourceLocation GetTargetLoc(
1050       const MatchFinder::MatchResult& result) override {
1051     // Find location of the gmock_##MockedMethod identifier.
1052     clang::SourceLocation target_loc = Base::GetTargetLoc(result);
1053 
1054     // Find location of EXPECT_CALL macro invocation.
1055     clang::SourceLocation macro_call_loc =
1056         result.SourceManager->getExpansionLoc(target_loc);
1057 
1058     // Map |macro_call_loc| to argument location (location of the method name
1059     // that needs renaming).
1060     auto it = expect_call_to_2nd_arg.find(macro_call_loc);
1061     if (it == expect_call_to_2nd_arg.end())
1062       return clang::SourceLocation();
1063     return it->second;
1064   }
1065 
1066  private:
1067   std::map<clang::SourceLocation, clang::SourceLocation> expect_call_to_2nd_arg;
1068 
1069   // Called from PPCallbacks with the locations of EXPECT_CALL macro invocation:
1070   // Example:
1071   //   EXPECT_CALL(my_mock, myMethod(123, 456));
1072   //   ^- expansion_loc     ^- actual_arg_loc
RecordExpectCallMacroInvocation(clang::SourceLocation expansion_loc,clang::SourceLocation second_arg_loc)1073   void RecordExpectCallMacroInvocation(clang::SourceLocation expansion_loc,
1074                                        clang::SourceLocation second_arg_loc) {
1075     expect_call_to_2nd_arg[expansion_loc] = second_arg_loc;
1076   }
1077 
1078   class PPCallbacks : public clang::PPCallbacks {
1079    public:
PPCallbacks(GMockMemberRewriter * rewriter)1080     explicit PPCallbacks(GMockMemberRewriter* rewriter) : rewriter_(rewriter) {}
~PPCallbacks()1081     ~PPCallbacks() override {}
MacroExpands(const clang::Token & name,const clang::MacroDefinition & def,clang::SourceRange range,const clang::MacroArgs * args)1082     void MacroExpands(const clang::Token& name,
1083                       const clang::MacroDefinition& def,
1084                       clang::SourceRange range,
1085                       const clang::MacroArgs* args) override {
1086       clang::IdentifierInfo* id = name.getIdentifierInfo();
1087       if (!id)
1088         return;
1089 
1090       if (id->getName() != "EXPECT_CALL")
1091         return;
1092 
1093       if (def.getMacroInfo()->getNumArgs() != 2)
1094         return;
1095 
1096       // TODO(lukasza): Should check if def.getMacroInfo()->getDefinitionLoc()
1097       // is in testing/gmock/include/gmock/gmock-spec-builders.h but I don't
1098       // know how to get clang::SourceManager to call getFileName.
1099 
1100       rewriter_->RecordExpectCallMacroInvocation(
1101           name.getLocation(), args->getUnexpArgument(1)->getLocation());
1102     }
1103 
1104    private:
1105     GMockMemberRewriter* rewriter_;
1106   };
1107 };
1108 
GetUnresolvedName(const clang::UnresolvedMemberExpr & expr)1109 clang::DeclarationName GetUnresolvedName(
1110     const clang::UnresolvedMemberExpr& expr) {
1111   return expr.getMemberName();
1112 }
1113 
GetUnresolvedName(const clang::DependentScopeDeclRefExpr & expr)1114 clang::DeclarationName GetUnresolvedName(
1115     const clang::DependentScopeDeclRefExpr& expr) {
1116   return expr.getDeclName();
1117 }
1118 
GetUnresolvedName(const clang::CXXDependentScopeMemberExpr & expr)1119 clang::DeclarationName GetUnresolvedName(
1120     const clang::CXXDependentScopeMemberExpr& expr) {
1121   return expr.getMember();
1122 }
1123 
GetUnresolvedName(const clang::UnresolvedUsingValueDecl & decl)1124 clang::DeclarationName GetUnresolvedName(
1125     const clang::UnresolvedUsingValueDecl& decl) {
1126   return decl.getDeclName();
1127 }
1128 
1129 // Returns whether |expr_node| is used as a callee in the AST (i.e. if
1130 // |expr_node| needs to resolve to a method or a function).
IsCallee(const clang::Expr & expr,clang::ASTContext & context)1131 bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) {
1132   auto matcher = stmt(hasParent(callExpr(callee(equalsNode(&expr)))));
1133   return IsMatching(matcher, expr, context);
1134 }
1135 
1136 // Returns whether |decl| will be used as a callee in the AST (i.e. if the value
1137 // brought by the using declaration will resolve to a method or a function).
IsCallee(const clang::UnresolvedUsingValueDecl & decl,clang::ASTContext &)1138 bool IsCallee(const clang::UnresolvedUsingValueDecl& decl,
1139               clang::ASTContext& /* context */) {
1140   // Caller (i.e. GuessNameForUnresolvedDependentNode) should have already
1141   // filtered out fields before calling |IsCallee|.
1142   clang::IdentifierInfo* info = GetUnresolvedName(decl).getAsIdentifierInfo();
1143   assert(info);
1144   bool name_looks_like_a_field = info->getName().startswith(kBlinkFieldPrefix);
1145   assert(!name_looks_like_a_field);
1146 
1147   // Looking just at clang::UnresolvedUsingValueDecl, we cannot tell whether it
1148   // refers to something callable or not.  Since fields should have been already
1149   // filtered out before calling IsCallee (see the assert above), let's assume
1150   // that |using Base::foo| refers to a method.
1151   return true;
1152 }
1153 
1154 template <typename TargetNode>
1155 class UnresolvedRewriterBase : public RewriterBase<TargetNode> {
1156  public:
1157   using Base = RewriterBase<TargetNode>;
1158 
UnresolvedRewriterBase(std::set<Replacement> * replacements)1159   explicit UnresolvedRewriterBase(std::set<Replacement>* replacements)
1160       : RewriterBase<TargetNode>(replacements) {}
1161 
run(const MatchFinder::MatchResult & result)1162   void run(const MatchFinder::MatchResult& result) override {
1163     const TargetNode& node = Base::GetTargetNode(result);
1164 
1165     clang::DeclarationName decl_name = GetUnresolvedName(node);
1166     switch (decl_name.getNameKind()) {
1167       // Do not rewrite this:
1168       //   return operator T*();
1169       // into this:
1170       //   return Operator type - parameter - 0 - 0 * T * ();
1171       case clang::DeclarationName::NameKind::CXXConversionFunctionName:
1172       case clang::DeclarationName::NameKind::CXXOperatorName:
1173       case clang::DeclarationName::NameKind::CXXLiteralOperatorName:
1174         return;
1175       default:
1176         break;
1177     }
1178 
1179     // Make sure there is an old name + extract the old name.
1180     clang::IdentifierInfo* info = GetUnresolvedName(node).getAsIdentifierInfo();
1181     if (!info)
1182       return;
1183     llvm::StringRef old_name = info->getName();
1184 
1185     // Try to guess a new name.
1186     std::string new_name;
1187     if (GuessNameForUnresolvedDependentNode(node, *result.Context, old_name,
1188                                             new_name))
1189       Base::AddReplacement(result, old_name, std::move(new_name));
1190   }
1191 
1192  private:
1193   // This method calculates a new name for nodes that depend on template
1194   // parameters (http://en.cppreference.com/w/cpp/language/dependent_name).  The
1195   // renaming is based on crude heuristics, because such nodes are not bound to
1196   // a specific decl until template instantiation - at the point of rename, one
1197   // cannot tell whether the node will eventually resolve to a field / method /
1198   // constant / etc.
1199   //
1200   // The method returns false if no renaming should be done.
1201   // Otherwise the method returns true and sets |new_name|.
GuessNameForUnresolvedDependentNode(const TargetNode & node,clang::ASTContext & context,llvm::StringRef old_name,std::string & new_name)1202   bool GuessNameForUnresolvedDependentNode(const TargetNode& node,
1203                                            clang::ASTContext& context,
1204                                            llvm::StringRef old_name,
1205                                            std::string& new_name) {
1206     // |m_fieldName| -> |field_name_|.
1207     if (old_name.startswith(kBlinkFieldPrefix)) {
1208       std::string field_name = old_name.substr(strlen(kBlinkFieldPrefix));
1209       if (field_name.find('_') == std::string::npos) {
1210         new_name = CamelCaseToUnderscoreCase(field_name) + "_";
1211         return true;
1212       }
1213     }
1214 
1215     // |T::myMethod(...)| -> |T::MyMethod(...)|.
1216     if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) &&
1217         !IsBlacklistedMethodName(old_name)) {
1218       new_name = old_name;
1219       new_name[0] = clang::toUppercase(old_name[0]);
1220       if (ShouldPrefixFunctionName(old_name))
1221         new_name = "Get" + new_name;
1222       return true;
1223     }
1224 
1225     // In the future we can consider more heuristics:
1226     // - "s_" and "g_" prefixes
1227     // - "ALL_CAPS"
1228     // - |T::myStaticField| -> |T::kMyStaticField|
1229     //   (but have to be careful not to rename |value| in WTF/TypeTraits.h?)
1230     return false;
1231   }
1232 };
1233 
1234 using UnresolvedDependentMemberRewriter =
1235     UnresolvedRewriterBase<clang::UnresolvedMemberExpr>;
1236 
1237 using UnresolvedUsingValueDeclRewriter =
1238     UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>;
1239 
1240 using DependentScopeDeclRefExprRewriter =
1241     UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>;
1242 
1243 using CXXDependentScopeMemberExprRewriter =
1244     UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>;
1245 
1246 class SourceFileCallbacks : public clang::tooling::SourceFileCallbacks {
1247  public:
SourceFileCallbacks(GMockMemberRewriter * gmock_member_rewriter)1248   explicit SourceFileCallbacks(GMockMemberRewriter* gmock_member_rewriter)
1249       : gmock_member_rewriter_(gmock_member_rewriter) {
1250     assert(gmock_member_rewriter);
1251   }
1252 
~SourceFileCallbacks()1253   ~SourceFileCallbacks() override {}
1254 
1255   // clang::tooling::SourceFileCallbacks override:
handleBeginSource(clang::CompilerInstance & compiler,llvm::StringRef Filename)1256   bool handleBeginSource(clang::CompilerInstance& compiler,
1257                          llvm::StringRef Filename) override {
1258     compiler.getPreprocessor().addPPCallbacks(
1259         gmock_member_rewriter_->CreatePreprocessorCallbacks());
1260     return true;
1261   }
1262 
1263  private:
1264   GMockMemberRewriter* gmock_member_rewriter_;
1265 };
1266 
1267 }  // namespace
1268 
1269 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
1270 
main(int argc,const char * argv[])1271 int main(int argc, const char* argv[]) {
1272   // TODO(dcheng): Clang tooling should do this itself.
1273   // http://llvm.org/bugs/show_bug.cgi?id=21627
1274   llvm::InitializeNativeTarget();
1275   llvm::InitializeNativeTargetAsmParser();
1276   llvm::cl::OptionCategory category(
1277       "rewrite_to_chrome_style: convert Blink style to Chrome style.");
1278   CommonOptionsParser options(argc, argv, category);
1279   clang::tooling::ClangTool tool(options.getCompilations(),
1280                                  options.getSourcePathList());
1281 
1282   MatchFinder match_finder;
1283   std::set<Replacement> replacements;
1284 
1285   // Blink namespace matchers ========
1286   auto blink_namespace_decl =
1287       namespaceDecl(anyOf(hasName("blink"), hasName("WTF")),
1288                     hasParent(translationUnitDecl()));
1289   auto protocol_namespace_decl =
1290       namespaceDecl(hasName("protocol"),
1291                     hasParent(namespaceDecl(hasName("blink"),
1292                                             hasParent(translationUnitDecl()))));
1293 
1294   // Given top-level compilation unit:
1295   //   namespace WTF {
1296   //     void foo() {}
1297   //   }
1298   // matches |foo|.
1299   auto decl_under_blink_namespace =
1300       decl(hasAncestor(blink_namespace_decl),
1301            unless(hasAncestor(protocol_namespace_decl)));
1302 
1303   // Given top-level compilation unit:
1304   //   void WTF::function() {}
1305   //   void WTF::Class::method() {}
1306   // matches |WTF::function| and |WTF::Class::method| decls.
1307   auto decl_has_qualifier_to_blink_namespace =
1308       declaratorDecl(has(nestedNameSpecifier(
1309           hasTopLevelPrefix(specifiesNamespace(blink_namespace_decl)))));
1310 
1311   auto in_blink_namespace = decl(
1312       anyOf(decl_under_blink_namespace, decl_has_qualifier_to_blink_namespace,
1313             hasAncestor(decl_has_qualifier_to_blink_namespace)),
1314       unless(isExpansionInFileMatching(kGeneratedFileRegex)));
1315 
1316   // Field, variable, and enum declarations ========
1317   // Given
1318   //   int x;
1319   //   struct S {
1320   //     int y;
1321   //     enum { VALUE };
1322   //   };
1323   // matches |x|, |y|, and |VALUE|.
1324   auto field_decl_matcher = id("decl", fieldDecl(in_blink_namespace));
1325   auto is_type_trait_value =
1326       varDecl(hasName("value"), hasStaticStorageDuration(), isPublic(),
1327               hasType(isConstQualified()),
1328               hasType(type(anyOf(builtinType(), enumType()))),
1329               unless(hasAncestor(recordDecl(
1330                   has(cxxMethodDecl(isUserProvided(), isInstanceMethod()))))));
1331   auto var_decl_matcher =
1332       id("decl", varDecl(in_blink_namespace, unless(is_type_trait_value)));
1333   auto enum_member_decl_matcher =
1334       id("decl", enumConstantDecl(in_blink_namespace));
1335 
1336   FieldDeclRewriter field_decl_rewriter(&replacements);
1337   match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter);
1338 
1339   VarDeclRewriter var_decl_rewriter(&replacements);
1340   match_finder.addMatcher(var_decl_matcher, &var_decl_rewriter);
1341 
1342   EnumConstantDeclRewriter enum_member_decl_rewriter(&replacements);
1343   match_finder.addMatcher(enum_member_decl_matcher, &enum_member_decl_rewriter);
1344 
1345   // Field, variable, and enum references ========
1346   // Given
1347   //   bool x = true;
1348   //   if (x) {
1349   //     ...
1350   //   }
1351   // matches |x| in if (x).
1352   auto member_matcher = id(
1353       "expr",
1354       memberExpr(
1355           member(field_decl_matcher),
1356           // Needed to avoid matching member references in functions (which will
1357           // be an ancestor of the member reference) synthesized by the
1358           // compiler, such as a synthesized copy constructor.
1359           // This skips explicitly defaulted functions as well, but that's OK:
1360           // there's nothing interesting to rewrite in those either.
1361           unless(hasAncestor(functionDecl(isDefaulted())))));
1362   auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher)));
1363   auto enum_member_ref_matcher =
1364       id("expr", declRefExpr(to(enum_member_decl_matcher)));
1365 
1366   MemberRewriter member_rewriter(&replacements);
1367   match_finder.addMatcher(member_matcher, &member_rewriter);
1368 
1369   DeclRefRewriter decl_ref_rewriter(&replacements);
1370   match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter);
1371 
1372   EnumConstantDeclRefRewriter enum_member_ref_rewriter(&replacements);
1373   match_finder.addMatcher(enum_member_ref_matcher, &enum_member_ref_rewriter);
1374 
1375   // Member references in a non-member context ========
1376   // Given
1377   //   struct S {
1378   //     typedef int U::*UnspecifiedBoolType;
1379   //     operator UnspecifiedBoolType() { return s_ ? &U::s_ : 0; }
1380   //     int s_;
1381   //   };
1382   // matches |&U::s_| but not |s_|.
1383   auto member_ref_matcher = id("expr", declRefExpr(to(field_decl_matcher)));
1384 
1385   FieldDeclRefRewriter member_ref_rewriter(&replacements);
1386   match_finder.addMatcher(member_ref_matcher, &member_ref_rewriter);
1387 
1388   // Non-method function declarations ========
1389   // Given
1390   //   void f();
1391   //   struct S {
1392   //     void g();
1393   //   };
1394   // matches |f| but not |g|.
1395   auto function_decl_matcher = id(
1396       "decl",
1397       functionDecl(
1398           unless(anyOf(
1399               // Methods are covered by the method matchers.
1400               cxxMethodDecl(),
1401               // Out-of-line overloaded operators have special names and should
1402               // never be renamed.
1403               isOverloadedOperator(),
1404               // Must be checked after filtering out overloaded operators to
1405               // prevent asserts about the identifier not being a simple name.
1406               isBlacklistedFunction())),
1407           in_blink_namespace));
1408   FunctionDeclRewriter function_decl_rewriter(&replacements);
1409   match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter);
1410 
1411   // Non-method function references ========
1412   // Given
1413   //   f();
1414   //   void (*p)() = &f;
1415   // matches |f()| and |&f|.
1416   auto function_ref_matcher = id(
1417       "expr", declRefExpr(to(function_decl_matcher),
1418                           // Ignore template substitutions.
1419                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
1420   FunctionRefRewriter function_ref_rewriter(&replacements);
1421   match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter);
1422 
1423   // Method declarations ========
1424   // Given
1425   //   struct S {
1426   //     void g();
1427   //   };
1428   // matches |g|.
1429   // For a method to be considered for rewrite, it must not override something
1430   // that we're not rewriting. Any methods that we would not normally consider
1431   // but that override something we are rewriting should also be rewritten. So
1432   // we use includeAllOverriddenMethods() to check these rules not just for the
1433   // method being matched but for the methods it overrides also.
1434   auto is_blink_method = includeAllOverriddenMethods(
1435       allOf(in_blink_namespace, unless(isBlacklistedMethod())));
1436   auto method_decl_matcher = id(
1437       "decl",
1438       cxxMethodDecl(
1439           unless(anyOf(
1440               // Overloaded operators have special names and should never be
1441               // renamed.
1442               isOverloadedOperator(),
1443               // Similarly, constructors, destructors, and conversion
1444               // functions should not be considered for renaming.
1445               cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())),
1446           // Check this last after excluding things, to avoid
1447           // asserts about overriding non-blink and blink for the
1448           // same method.
1449           is_blink_method));
1450   MethodDeclRewriter method_decl_rewriter(&replacements);
1451   match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter);
1452 
1453   // Method references in a non-member context ========
1454   // Given
1455   //   S s;
1456   //   s.g();
1457   //   void (S::*p)() = &S::g;
1458   // matches |&S::g| but not |s.g|.
1459   auto method_ref_matcher = id(
1460       "expr", declRefExpr(to(method_decl_matcher),
1461                           // Ignore template substitutions.
1462                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
1463 
1464   MethodRefRewriter method_ref_rewriter(&replacements);
1465   match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter);
1466 
1467   // Method references in a member context ========
1468   // Given
1469   //   S s;
1470   //   s.g();
1471   //   void (S::*p)() = &S::g;
1472   // matches |s.g| but not |&S::g|.
1473   auto method_member_matcher =
1474       id("expr", memberExpr(member(method_decl_matcher)));
1475 
1476   MethodMemberRewriter method_member_rewriter(&replacements);
1477   match_finder.addMatcher(method_member_matcher, &method_member_rewriter);
1478 
1479   // Initializers ========
1480   // Given
1481   //   struct S {
1482   //     int x;
1483   //     S() : x(2) {}
1484   //   };
1485   // matches each initializer in the constructor for S.
1486   auto constructor_initializer_matcher =
1487       cxxConstructorDecl(forEachConstructorInitializer(id(
1488           "initializer",
1489           cxxCtorInitializer(forAnyField(field_decl_matcher), isWritten()))));
1490 
1491   ConstructorInitializerRewriter constructor_initializer_rewriter(
1492       &replacements);
1493   match_finder.addMatcher(constructor_initializer_matcher,
1494                           &constructor_initializer_rewriter);
1495 
1496   // Unresolved lookup expressions ========
1497   // Given
1498   //   template<typename T> void F(T) { }
1499   //   template<void G(T)> H(T) { }
1500   //   H<F<int>>(...);
1501   // matches |F| in |H<F<int>>|.
1502   //
1503   // UnresolvedLookupExprs are similar to DeclRefExprs that reference a
1504   // FunctionDecl, but are used when a candidate FunctionDecl can't be selected.
1505   // This commonly happens inside uninstantiated template definitions for one of
1506   // two reasons:
1507   //
1508   // 1. If the candidate declaration is a dependent FunctionTemplateDecl, the
1509   //    actual overload can't be selected until template instantiation time.
1510   // 2. Alternatively, there might be multiple declarations in the candidate set
1511   //    if the candidate function has overloads. If any of the function
1512   //    arguments has a dependent type, then the actual overload can't be
1513   //    selected until instantiation time either.
1514   //
1515   // Another instance where UnresolvedLookupExprs can appear is in a template
1516   // argument list, like the provided example.
1517   auto function_template_decl_matcher =
1518       id("decl", functionTemplateDecl(templatedDecl(function_decl_matcher)));
1519   auto method_template_decl_matcher =
1520       id("decl", functionTemplateDecl(templatedDecl(method_decl_matcher)));
1521   auto unresolved_lookup_matcher = expr(id(
1522       "expr",
1523       unresolvedLookupExpr(
1524           // In order to automatically rename an unresolved lookup, the lookup
1525           // candidates must either all be Blink functions/function templates or
1526           // all be Blink methods/method templates. Otherwise, we might end up
1527           // in a situation where the naming could change depending on the
1528           // selected candidate.
1529           anyOf(allOverloadsMatch(anyOf(function_decl_matcher,
1530                                         function_template_decl_matcher)),
1531                 // Note: this matches references to methods in a non-member
1532                 // context, e.g. Template<&Class::Method>. This and the
1533                 // UnresolvedMemberExpr matcher below are analogous to how the
1534                 // rewriter has both a MemberRefRewriter matcher to rewrite
1535                 // &T::method and a MethodMemberRewriter matcher to rewriter
1536                 // t.method().
1537                 allOverloadsMatch(anyOf(method_decl_matcher,
1538                                         method_template_decl_matcher))))));
1539   UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements);
1540   match_finder.addMatcher(unresolved_lookup_matcher,
1541                           &unresolved_lookup_rewriter);
1542 
1543   // Unresolved member expressions (for non-dependent fields / methods) ========
1544   // Similar to unresolved lookup expressions, but for methods in a member
1545   // context, e.g. var_with_templated_type.Method().
1546   auto unresolved_member_matcher = expr(id(
1547       "expr",
1548       unresolvedMemberExpr(
1549           // Similar to UnresolvedLookupExprs, all the candidate methods must be
1550           // Blink methods/method templates.
1551           allOverloadsMatch(
1552               anyOf(method_decl_matcher, method_template_decl_matcher)))));
1553   UnresolvedMemberRewriter unresolved_member_rewriter(&replacements);
1554   match_finder.addMatcher(unresolved_member_matcher,
1555                           &unresolved_member_rewriter);
1556 
1557   // Unresolved using value decls ========
1558   // Example:
1559   //  template <typename T>
1560   //  class BaseClass {
1561   //   public:
1562   //    unsigned long m_size;
1563   //  };
1564   //  template <typename T>
1565   //  class DerivedClass : protected BaseClass<T> {
1566   //   private:
1567   //    using Base = BaseClass<T>;
1568   //    using Base::m_size;  // <- |m_size| here is matched by
1569   //    void method() {      //    |unresolved_using_value_decl_matcher|.
1570   //      m_size = 123;  // <- |m_size| here is matched by
1571   //    }                //    |unresolved_dependent_using_matcher|.
1572   //  };
1573   auto unresolved_dependent_using_matcher =
1574       expr(id("expr", unresolvedMemberExpr(allOverloadsMatch(allOf(
1575                           in_blink_namespace, unresolvedUsingValueDecl())))));
1576   UnresolvedDependentMemberRewriter unresolved_dependent_member_rewriter(
1577       &replacements);
1578   match_finder.addMatcher(unresolved_dependent_using_matcher,
1579                           &unresolved_dependent_member_rewriter);
1580   auto unresolved_using_value_decl_matcher =
1581       decl(id("decl", unresolvedUsingValueDecl(in_blink_namespace)));
1582   UnresolvedUsingValueDeclRewriter unresolved_using_value_decl_rewriter(
1583       &replacements);
1584   match_finder.addMatcher(unresolved_using_value_decl_matcher,
1585                           &unresolved_using_value_decl_rewriter);
1586 
1587   // Using declarations ========
1588   // Given
1589   //   using blink::X;
1590   // matches |using blink::X|.
1591   auto using_decl_matcher = id(
1592       "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf(
1593                   var_decl_matcher, field_decl_matcher, function_decl_matcher,
1594                   method_decl_matcher, function_template_decl_matcher,
1595                   method_template_decl_matcher, enum_member_decl_matcher)))));
1596   UsingDeclRewriter using_decl_rewriter(&replacements);
1597   match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter);
1598 
1599   // Matches any QualType that refers to a blink type:
1600   // - const blink::Foo&
1601   // - blink::Foo*
1602   // - blink::Foo<T>
1603   auto blink_qual_type_base_matcher = hasBaseType(hasUnqualifiedDesugaredType(
1604       anyOf(enumType(hasDeclaration(in_blink_namespace)),
1605             injectedClassNameType(hasDeclaration(in_blink_namespace)),
1606             recordType(hasDeclaration(in_blink_namespace)),
1607             templateSpecializationType(hasDeclaration(in_blink_namespace)),
1608             templateTypeParmType(hasDeclaration(in_blink_namespace)))));
1609   auto blink_qual_type_matcher = qualType(anyOf(
1610       blink_qual_type_base_matcher, pointsTo(blink_qual_type_base_matcher),
1611       references(blink_qual_type_base_matcher)));
1612 
1613   // Template-dependent decl lookup ========
1614   // Given
1615   //   template <typename T> void f() { T::foo(); }
1616   // matches |T::foo|.
1617   auto dependent_scope_decl_ref_expr_matcher =
1618       expr(id("expr", dependentScopeDeclRefExpr(has(nestedNameSpecifier(
1619                           specifiesType(blink_qual_type_matcher))))));
1620   DependentScopeDeclRefExprRewriter dependent_scope_decl_ref_expr_rewriter(
1621       &replacements);
1622   match_finder.addMatcher(dependent_scope_decl_ref_expr_matcher,
1623                           &dependent_scope_decl_ref_expr_rewriter);
1624 
1625   // Template-dependent member lookup ========
1626   // Given
1627   //   template <typename T>
1628   //   class Foo {
1629   //     void f() { T::foo(); }
1630   //     void g(T x) { x.bar(); }
1631   //   };
1632   // matches |T::foo| and |x.bar|.
1633   auto cxx_dependent_scope_member_expr_matcher =
1634       expr(id("expr", cxxDependentScopeMemberExpr(
1635                           hasMemberFromType(blink_qual_type_matcher))));
1636   CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter(
1637       &replacements);
1638   match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher,
1639                           &cxx_dependent_scope_member_expr_rewriter);
1640 
1641   // GMock calls lookup ========
1642   // Given
1643   //   EXPECT_CALL(obj, myMethod(...))
1644   // will match obj.gmock_myMethod(...) call generated by the macro
1645   // (but only if it mocks a Blink method).
1646   auto gmock_member_matcher =
1647       id("expr", memberExpr(hasDeclaration(
1648                      decl(cxxMethodDecl(mocksMethod(method_decl_matcher))))));
1649   GMockMemberRewriter gmock_member_rewriter(&replacements);
1650   match_finder.addMatcher(gmock_member_matcher, &gmock_member_rewriter);
1651 
1652   // Prepare and run the tool.
1653   SourceFileCallbacks source_file_callbacks(&gmock_member_rewriter);
1654   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
1655       clang::tooling::newFrontendActionFactory(&match_finder,
1656                                                &source_file_callbacks);
1657   int result = tool.run(factory.get());
1658   if (result != 0)
1659     return result;
1660 
1661   // Supplemental data for the Blink rename rebase helper.
1662   // TODO(dcheng): There's a lot of match rewriters missing from this list.
1663   llvm::outs() << "==== BEGIN TRACKED EDITS ====\n";
1664   field_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs());
1665   var_decl_rewriter.edit_tracker().SerializeTo("var", llvm::outs());
1666   enum_member_decl_rewriter.edit_tracker().SerializeTo("enu", llvm::outs());
1667   function_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs());
1668   method_decl_rewriter.edit_tracker().SerializeTo("fun", llvm::outs());
1669   llvm::outs() << "==== END TRACKED EDITS ====\n";
1670 
1671   // Serialization format is documented in tools/clang/scripts/run_tool.py
1672   llvm::outs() << "==== BEGIN EDITS ====\n";
1673   for (const auto& r : replacements) {
1674     std::string replacement_text = r.getReplacementText().str();
1675     std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
1676     llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
1677                  << ":::" << r.getLength() << ":::" << replacement_text << "\n";
1678   }
1679   llvm::outs() << "==== END EDITS ====\n";
1680 
1681   return 0;
1682 }
1683