• 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/Lexer.h"
30 #include "clang/Lex/MacroArgs.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/ErrorOr.h"
38 #include "llvm/Support/LineIterator.h"
39 #include "llvm/Support/MemoryBuffer.h"
40 #include "llvm/Support/Path.h"
41 #include "llvm/Support/TargetSelect.h"
42 
43 #include "EditTracker.h"
44 
45 using namespace clang::ast_matchers;
46 using clang::tooling::CommonOptionsParser;
47 using clang::tooling::Replacement;
48 using llvm::StringRef;
49 
50 namespace {
51 
52 const char kBlinkFieldPrefix[] = "m_";
53 const char kBlinkStaticMemberPrefix[] = "s_";
54 const char kGMockMethodNamePrefix[] = "gmock_";
55 const char kMethodBlocklistParamName[] = "method-blocklist";
56 
GetRewrittenLocs()57 std::set<clang::SourceLocation>& GetRewrittenLocs() {
58   static auto& locations = *new std::set<clang::SourceLocation>();
59   return locations;
60 }
61 
62 template <typename MatcherType, typename NodeType>
IsMatching(const MatcherType & matcher,const NodeType & node,clang::ASTContext & context)63 bool IsMatching(const MatcherType& matcher,
64                 const NodeType& node,
65                 clang::ASTContext& context) {
66   return !match(matcher, node, context).empty();
67 }
68 
69 const clang::ast_matchers::internal::
70     VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr>
71         unresolvedMemberExpr;
72 
73 const clang::ast_matchers::internal::
74     VariadicDynCastAllOfMatcher<clang::Expr, clang::DependentScopeDeclRefExpr>
75         dependentScopeDeclRefExpr;
76 
77 const clang::ast_matchers::internal::
78     VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXDependentScopeMemberExpr>
79         cxxDependentScopeMemberExpr;
80 
AST_MATCHER(clang::FunctionDecl,isOverloadedOperator)81 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) {
82   return Node.isOverloadedOperator();
83 }
84 
AST_MATCHER(clang::CXXMethodDecl,isInstanceMethod)85 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) {
86   return Node.isInstance();
87 }
88 
AST_MATCHER_P(clang::FunctionTemplateDecl,templatedDecl,clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,InnerMatcher)89 AST_MATCHER_P(clang::FunctionTemplateDecl,
90               templatedDecl,
91               clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,
92               InnerMatcher) {
93   return InnerMatcher.matches(*Node.getTemplatedDecl(), Finder, Builder);
94 }
95 
AST_MATCHER_P(clang::Decl,hasCanonicalDecl,clang::ast_matchers::internal::Matcher<clang::Decl>,InnerMatcher)96 AST_MATCHER_P(clang::Decl,
97               hasCanonicalDecl,
98               clang::ast_matchers::internal::Matcher<clang::Decl>,
99               InnerMatcher) {
100   return InnerMatcher.matches(*Node.getCanonicalDecl(), Finder, Builder);
101 }
102 
103 // Matches a CXXMethodDecl of a method declared via MOCK_METHODx macro if such
104 // method mocks a method matched by the InnerMatcher.  For example if "foo"
105 // matcher matches "interfaceMethod", then mocksMethod(foo()) will match
106 // "gmock_interfaceMethod" declared by MOCK_METHOD_x(interfaceMethod).
AST_MATCHER_P(clang::CXXMethodDecl,mocksMethod,clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,InnerMatcher)107 AST_MATCHER_P(clang::CXXMethodDecl,
108               mocksMethod,
109               clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,
110               InnerMatcher) {
111   if (!Node.getDeclName().isIdentifier())
112     return false;
113 
114   llvm::StringRef method_name = Node.getName();
115   if (!method_name.startswith(kGMockMethodNamePrefix))
116     return false;
117 
118   llvm::StringRef mocked_method_name =
119       method_name.substr(strlen(kGMockMethodNamePrefix));
120   for (const auto& potentially_mocked_method : Node.getParent()->methods()) {
121     clang::DeclarationName decl_name = potentially_mocked_method->getDeclName();
122     if (!decl_name.isIdentifier() ||
123         potentially_mocked_method->getName() != mocked_method_name)
124       continue;
125     if (potentially_mocked_method->getNumParams() != Node.getNumParams())
126       continue;
127 
128     if (InnerMatcher.matches(*potentially_mocked_method, Finder, Builder))
129       return true;
130   }
131 
132   return false;
133 }
134 
135 class MethodBlocklist {
136  public:
MethodBlocklist(const std::string & filepath)137   explicit MethodBlocklist(const std::string& filepath) {
138     if (!filepath.empty())
139       ParseInputFile(filepath);
140   }
141 
Contains(const clang::FunctionDecl & method) const142   bool Contains(const clang::FunctionDecl& method) const {
143     if (!method.getDeclName().isIdentifier())
144       return false;
145 
146     auto it = method_to_classes_.find(method.getName());
147     if (it == method_to_classes_.end())
148       return false;
149 
150     // |method_context| is either
151     // 1) a CXXRecordDecl (i.e. blink::Document) or
152     // 2) a NamespaceDecl (i.e. blink::DOMWindowTimers).
153     const clang::NamedDecl* method_context =
154         clang::dyn_cast<clang::NamedDecl>(method.getDeclContext());
155     if (!method_context)
156       return false;
157     if (!method_context->getDeclName().isIdentifier())
158       return false;
159 
160     const llvm::StringSet<>& classes = it->second;
161     auto it2 = classes.find(method_context->getName());
162     if (it2 == classes.end())
163       return false;
164 
165     // No need to verify here that |actual_class| is in the |blink| namespace -
166     // this will be done by other matchers elsewhere.
167 
168     // TODO(lukasza): Do we need to consider return type and/or param types?
169 
170     // TODO(lukasza): Do we need to consider param count?
171 
172     return true;
173   }
174 
175  private:
176   // Each line is expected to have the following format:
177   // <class name>:::<method name>:::<number of arguments>
ParseInputFile(const std::string & filepath)178   void ParseInputFile(const std::string& filepath) {
179     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> file_or_err =
180         llvm::MemoryBuffer::getFile(filepath);
181     if (std::error_code err = file_or_err.getError()) {
182       llvm::errs() << "ERROR: Cannot open the file specified in --"
183                    << kMethodBlocklistParamName << " argument: " << filepath
184                    << ": " << err.message() << "\n";
185       assert(false);
186       return;
187     }
188 
189     llvm::line_iterator it(**file_or_err, true /* SkipBlanks */, '#');
190     for (; !it.is_at_eof(); ++it) {
191       llvm::StringRef line = it->trim();
192       if (line.empty())
193         continue;
194 
195       // Split the line into ':::'-delimited parts.
196       const size_t kExpectedNumberOfParts = 3;
197       llvm::SmallVector<llvm::StringRef, kExpectedNumberOfParts> parts;
198       line.split(parts, ":::");
199       if (parts.size() != kExpectedNumberOfParts) {
200         llvm::errs() << "ERROR: Parsing error - expected "
201                      << kExpectedNumberOfParts
202                      << " ':::'-delimited parts: " << filepath << ":"
203                      << it.line_number() << ": " << line << "\n";
204         assert(false);
205         continue;
206       }
207 
208       // Parse individual parts.
209       llvm::StringRef class_name = parts[0];
210       llvm::StringRef method_name = parts[1];
211       // ignoring parts[2] - the (not so trustworthy) number of parameters.
212 
213       // Store the new entry.
214       method_to_classes_[method_name].insert(class_name);
215     }
216   }
217 
218   // Stores methods to blacklist in a map:
219   // method name -> class name -> set of all allowed numbers of arguments.
220   llvm::StringMap<llvm::StringSet<>> method_to_classes_;
221 };
222 
AST_MATCHER_P(clang::FunctionDecl,isBlocklistedMethod,MethodBlocklist,Blocklist)223 AST_MATCHER_P(clang::FunctionDecl,
224               isBlocklistedMethod,
225               MethodBlocklist,
226               Blocklist) {
227   return Blocklist.Contains(Node);
228 }
229 
230 // If |InnerMatcher| matches |top|, then the returned matcher will match:
231 // - |top::function|
232 // - |top::Class::method|
233 // - |top::internal::Class::method|
AST_MATCHER_P(clang::NestedNameSpecifier,hasTopLevelPrefix,clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,InnerMatcher)234 AST_MATCHER_P(
235     clang::NestedNameSpecifier,
236     hasTopLevelPrefix,
237     clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,
238     InnerMatcher) {
239   const clang::NestedNameSpecifier* NodeToMatch = &Node;
240   while (NodeToMatch->getPrefix())
241     NodeToMatch = NodeToMatch->getPrefix();
242   return InnerMatcher.matches(*NodeToMatch, Finder, Builder);
243 }
244 
245 // This will narrow CXXCtorInitializers down for both FieldDecls and
246 // IndirectFieldDecls (ie. anonymous unions and such). In both cases
247 // getAnyMember() will return a FieldDecl which we can match against.
AST_MATCHER_P(clang::CXXCtorInitializer,forAnyField,clang::ast_matchers::internal::Matcher<clang::FieldDecl>,InnerMatcher)248 AST_MATCHER_P(clang::CXXCtorInitializer,
249               forAnyField,
250               clang::ast_matchers::internal::Matcher<clang::FieldDecl>,
251               InnerMatcher) {
252   const clang::FieldDecl* NodeAsDecl = Node.getAnyMember();
253   return (NodeAsDecl != nullptr &&
254           InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
255 }
256 
257 // 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)258 AST_MATCHER_P(clang::OverloadExpr,
259               allOverloadsMatch,
260               clang::ast_matchers::internal::Matcher<clang::NamedDecl>,
261               InnerMatcher) {
262   if (Node.getNumDecls() == 0)
263     return false;
264 
265   for (clang::NamedDecl* decl : Node.decls()) {
266     if (!InnerMatcher.matches(*decl, Finder, Builder))
267       return false;
268   }
269   return true;
270 }
271 
PrintForDiagnostics(clang::raw_ostream & os,const clang::FunctionDecl & decl)272 void PrintForDiagnostics(clang::raw_ostream& os,
273                          const clang::FunctionDecl& decl) {
274   decl.getLocStart().print(os, decl.getASTContext().getSourceManager());
275   os << ": ";
276   decl.getNameForDiagnostic(os, decl.getASTContext().getPrintingPolicy(), true);
277 }
278 
279 template <typename T>
MatchAllOverriddenMethods(const clang::CXXMethodDecl & decl,T && inner_matcher,clang::ast_matchers::internal::ASTMatchFinder * finder,clang::ast_matchers::internal::BoundNodesTreeBuilder * builder)280 bool MatchAllOverriddenMethods(
281     const clang::CXXMethodDecl& decl,
282     T&& inner_matcher,
283     clang::ast_matchers::internal::ASTMatchFinder* finder,
284     clang::ast_matchers::internal::BoundNodesTreeBuilder* builder) {
285   bool override_matches = false;
286   bool override_not_matches = false;
287 
288   for (auto it = decl.begin_overridden_methods();
289        it != decl.end_overridden_methods(); ++it) {
290     if (MatchAllOverriddenMethods(**it, inner_matcher, finder, builder))
291       override_matches = true;
292     else
293       override_not_matches = true;
294   }
295 
296   // If this fires we have a class overriding a method that matches, and a
297   // method that does not match the inner matcher. In that case we will match
298   // one ancestor method but not the other. If we rename one of the and not the
299   // other it will break what this class overrides, disconnecting it from the
300   // one we did not rename which creates a behaviour change. So assert and
301   // demand the user to fix the code first (or add the method to our
302   // blacklist T_T).
303   if (override_matches && override_not_matches) {
304     // blink::InternalSettings::trace method overrides
305     // 1) blink::InternalSettingsGenerated::trace
306     //    (won't be renamed because it is in generated code)
307     // 2) blink::Supplement<blink::Page>::trace
308     //    (will be renamed).
309     // It is safe to rename blink::InternalSettings::trace, because
310     // both 1 and 2 will both be renamed (#1 via manual changes of the code
311     // generator for DOM bindings and #2 via the clang tool).
312     auto internal_settings_class_decl = cxxRecordDecl(
313         hasName("InternalSettings"),
314         hasParent(namespaceDecl(hasName("blink"),
315                                 hasParent(translationUnitDecl()))));
316     auto is_method_safe_to_rename = cxxMethodDecl(
317         hasName("trace"),
318         anyOf(hasParent(internal_settings_class_decl),  // in .h file
319               has(nestedNameSpecifier(specifiesType(    // in .cpp file
320                   hasDeclaration(internal_settings_class_decl))))));
321     if (IsMatching(is_method_safe_to_rename, decl, decl.getASTContext()))
322       return true;
323 
324     // For previously unknown conflicts, error out and require a human to
325     // analyse the problem (rather than falling back to a potentially unsafe /
326     // code semantics changing rename).
327     llvm::errs() << "ERROR: ";
328     PrintForDiagnostics(llvm::errs(), decl);
329     llvm::errs() << " method overrides "
330                  << "some virtual methods that will be automatically renamed "
331                  << "and some that won't be renamed.";
332     llvm::errs() << "\n";
333     for (auto it = decl.begin_overridden_methods();
334          it != decl.end_overridden_methods(); ++it) {
335       if (MatchAllOverriddenMethods(**it, inner_matcher, finder, builder))
336         llvm::errs() << "Overriden method that will be renamed: ";
337       else
338         llvm::errs() << "Overriden method that will not be renamed: ";
339       PrintForDiagnostics(llvm::errs(), **it);
340       llvm::errs() << "\n";
341     }
342     llvm::errs() << "\n";
343     assert(false);
344   }
345 
346   // If the method overrides something that doesn't match, so the method itself
347   // doesn't match.
348   if (override_not_matches)
349     return false;
350 
351   // If the method overrides something that matches, so the method ifself
352   // matches.
353   if (override_matches)
354     return true;
355 
356   return inner_matcher.matches(decl, finder, builder);
357 }
358 
AST_MATCHER_P(clang::CXXMethodDecl,includeAllOverriddenMethods,clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,InnerMatcher)359 AST_MATCHER_P(clang::CXXMethodDecl,
360               includeAllOverriddenMethods,
361               clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,
362               InnerMatcher) {
363   return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder);
364 }
365 
366 // Matches |T::m| and/or |x->T::m| and/or |x->m| CXXDependentScopeMemberExpr
367 // 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)368 AST_MATCHER_P(clang::CXXDependentScopeMemberExpr,
369               hasMemberFromType,
370               clang::ast_matchers::internal::Matcher<clang::QualType>,
371               InnerMatcher) {
372   // Given |T::m| and/or |x->T::m| and/or |x->m| ...
373   if (clang::NestedNameSpecifier* nestedNameSpecifier = Node.getQualifier()) {
374     // ... if |T| is present, then InnerMatcher has to match |T|.
375     clang::QualType qualType(nestedNameSpecifier->getAsType(), 0);
376     return InnerMatcher.matches(qualType, Finder, Builder);
377   } else {
378     // ... if there is no |T|, then InnerMatcher has to match the type of |x|.
379     clang::Expr* base_expr = Node.isImplicitAccess() ? nullptr : Node.getBase();
380     return base_expr &&
381            InnerMatcher.matches(base_expr->getType(), Finder, Builder);
382   }
383 }
384 
385 // Matches |const Class<T>&| QualType if InnerMatcher matches |Class<T>|.
AST_MATCHER_P(clang::QualType,hasBaseType,clang::ast_matchers::internal::Matcher<clang::Type>,InnerMatcher)386 AST_MATCHER_P(clang::QualType,
387               hasBaseType,
388               clang::ast_matchers::internal::Matcher<clang::Type>,
389               InnerMatcher) {
390   const clang::Type* type = Node.getTypePtrOrNull();
391   return type && InnerMatcher.matches(*type, Finder, Builder);
392 }
393 
IsMethodOverrideOf(const clang::CXXMethodDecl & decl,const char * class_name)394 bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl,
395                         const char* class_name) {
396   if (decl.getParent()->getQualifiedNameAsString() == class_name)
397     return true;
398   for (auto it = decl.begin_overridden_methods();
399        it != decl.end_overridden_methods(); ++it) {
400     if (IsMethodOverrideOf(**it, class_name))
401       return true;
402   }
403   return false;
404 }
405 
IsBlacklistedFunctionName(llvm::StringRef name)406 bool IsBlacklistedFunctionName(llvm::StringRef name) {
407   // https://crbug.com/672902: Method names with an underscore are typically
408   // mimicked after std library / are typically not originating from Blink.
409   // Do not rewrite such names (like push_back, emplace_back, etc.).
410   if (name.find('_') != llvm::StringRef::npos)
411     return true;
412 
413   return false;
414 }
415 
IsBlacklistedFreeFunctionName(llvm::StringRef name)416 bool IsBlacklistedFreeFunctionName(llvm::StringRef name) {
417   // swap() functions should match the signature of std::swap for ADL tricks.
418   return name == "swap";
419 }
420 
IsBlacklistedInstanceMethodName(llvm::StringRef name)421 bool IsBlacklistedInstanceMethodName(llvm::StringRef name) {
422   static const char* kBlacklistedNames[] = {
423       // We should avoid renaming the method names listed below, because
424       // 1. They are used in templated code (e.g. in <algorithms>)
425       // 2. They (begin+end) are used in range-based for syntax sugar
426       //    - for (auto x : foo) { ... }  // <- foo.begin() will be called.
427       "begin", "end", "rbegin", "rend", "lock", "unlock", "try_lock",
428 
429       // https://crbug.com/672902: Should not rewrite names that mimick methods
430       // from std library.
431       "at", "back", "empty", "erase", "front", "insert", "length", "size",
432   };
433   for (const auto& b : kBlacklistedNames) {
434     if (name == b)
435       return true;
436   }
437   return false;
438 }
439 
IsBlacklistedMethodName(llvm::StringRef name)440 bool IsBlacklistedMethodName(llvm::StringRef name) {
441   return IsBlacklistedFunctionName(name) ||
442          IsBlacklistedInstanceMethodName(name);
443 }
444 
IsBlacklistedFunction(const clang::FunctionDecl & decl)445 bool IsBlacklistedFunction(const clang::FunctionDecl& decl) {
446   if (!decl.getDeclName().isIdentifier())
447     return false;
448 
449   clang::StringRef name = decl.getName();
450   return IsBlacklistedFunctionName(name) || IsBlacklistedFreeFunctionName(name);
451 }
452 
IsBlacklistedMethod(const clang::CXXMethodDecl & decl)453 bool IsBlacklistedMethod(const clang::CXXMethodDecl& decl) {
454   if (!decl.getDeclName().isIdentifier())
455     return false;
456 
457   clang::StringRef name = decl.getName();
458   if (IsBlacklistedFunctionName(name))
459     return true;
460 
461   // Remaining cases are only applicable to instance methods.
462   if (decl.isStatic())
463     return false;
464 
465   if (IsBlacklistedInstanceMethodName(name))
466     return true;
467 
468   // Subclasses of InspectorAgent will subclass "disable()" from both blink and
469   // from gen/, which is problematic, but DevTools folks don't want to rename
470   // it or split this up. So don't rename it at all.
471   if (name.equals("disable") &&
472       IsMethodOverrideOf(decl, "blink::InspectorBaseAgent"))
473     return true;
474 
475   return false;
476 }
477 
AST_MATCHER(clang::FunctionDecl,isBlacklistedFunction)478 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) {
479   return IsBlacklistedFunction(Node);
480 }
481 
AST_MATCHER(clang::CXXMethodDecl,isBlacklistedMethod)482 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) {
483   return IsBlacklistedMethod(Node);
484 }
485 
IsKnownTraitName(clang::StringRef name)486 bool IsKnownTraitName(clang::StringRef name) {
487   // This set of names is globally a type trait throughout chromium.
488   return name == "safeToCompareToEmptyOrDeleted";
489 }
490 
AST_MATCHER(clang::VarDecl,isKnownTraitName)491 AST_MATCHER(clang::VarDecl, isKnownTraitName) {
492   return Node.getDeclName().isIdentifier() && IsKnownTraitName(Node.getName());
493 }
494 
AST_MATCHER(clang::Decl,isDeclInGeneratedFile)495 AST_MATCHER(clang::Decl, isDeclInGeneratedFile) {
496   // This matcher mimics the built-in isExpansionInFileMatching matcher from
497   // llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h, except:
498   // - It special cases some files (e.g. doesn't skip renaming of identifiers
499   //   from gen/blink/core/ComputedStyleBase.h)
500 
501   const clang::SourceManager& source_manager =
502       Node.getASTContext().getSourceManager();
503 
504   // TODO(lukasza): Consider using getSpellingLoc below.
505   // The built-in isExpansionInFileMatching matcher uses getExpansionLoc below.
506   // We could consider using getSpellingLoc (which properly handles things like
507   // SETTINGS_GETTERS_AND_SETTERS macro which is defined in generated code
508   // (gen/blink/core/SettingsMacros.h), but expanded in non-generated code
509   // (third_party/WebKit/Source/core/frame/Settings.h).
510   clang::SourceLocation loc =
511       source_manager.getExpansionLoc(Node.getLocStart());
512 
513   // TODO(lukasza): jump out of scratch space if token concatenation was used.
514   if (loc.isInvalid())
515     return false;
516 
517   const clang::FileEntry* file_entry =
518       source_manager.getFileEntryForID(source_manager.getFileID(loc));
519   if (!file_entry)
520     return false;
521 
522   bool is_generated_file = false;
523   bool is_computed_style_base_cpp =
524       llvm::sys::path::filename(file_entry->getName())
525           .equals("ComputedStyleBase.h");
526   for (auto it = llvm::sys::path::begin(file_entry->getName());
527        it != llvm::sys::path::end(file_entry->getName()); ++it) {
528     if (it->equals("gen")) {
529       is_generated_file = true;
530       break;
531     }
532   }
533   // ComputedStyleBase is intentionally not treated as a generated file, since
534   // style definitions are split between generated and non-generated code. It's
535   // easier to have the tool just automatically rewrite references to generated
536   // code as well, with a small manual patch to fix the code generators.
537   return is_generated_file && !is_computed_style_base_cpp;
538 }
539 
540 // Helper to convert from a camelCaseName to camel_case_name. It uses some
541 // heuristics to try to handle acronyms in camel case names correctly.
CamelCaseToUnderscoreCase(StringRef input)542 std::string CamelCaseToUnderscoreCase(StringRef input) {
543   std::string output;
544   bool needs_underscore = false;
545   bool was_lowercase = false;
546   bool was_uppercase = false;
547   bool first_char = true;
548   // Iterate in reverse to minimize the amount of backtracking.
549   for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin();
550        --i) {
551     char c = *i;
552     bool is_lowercase = clang::isLowercase(c);
553     bool is_uppercase = clang::isUppercase(c);
554     c = clang::toLowercase(c);
555     // Transitioning from upper to lower case requires an underscore. This is
556     // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_'
557     // in 'dH'. This is a complement to the non-acronym case further down.
558     if (was_uppercase && is_lowercase)
559       needs_underscore = true;
560     if (needs_underscore) {
561       output += '_';
562       needs_underscore = false;
563     }
564     output += c;
565     // Handles the non-acronym case: transitioning from lower to upper case
566     // requires an underscore when emitting the next character, e.g. didLoad
567     // needs a '_' in 'dL'.
568     if (!first_char && was_lowercase && is_uppercase)
569       needs_underscore = true;
570     was_lowercase = is_lowercase;
571     was_uppercase = is_uppercase;
572     first_char = false;
573   }
574   std::reverse(output.begin(), output.end());
575   return output;
576 }
577 
CanBeEvaluatedAtCompileTime(const clang::Stmt * stmt,const clang::ASTContext & context)578 bool CanBeEvaluatedAtCompileTime(const clang::Stmt* stmt,
579                                  const clang::ASTContext& context) {
580   auto* expr = clang::dyn_cast<clang::Expr>(stmt);
581   if (!expr) {
582     // If the statement is not an expression then it's a constant.
583     return true;
584   }
585 
586   // Function calls create non-consistent behaviour. For some template
587   // instantiations they can be constexpr while for others they are not, which
588   // changes the output of isEvaluatable().
589   if (expr->hasNonTrivialCall(context))
590     return false;
591 
592   // Recurse on children. If they are all const (or are uses of template
593   // input) then the statement can be considered const. For whatever reason the
594   // below checks can give different-and-less-consistent responses if we call
595   // them on a complex expression than if we call them on the most primitive
596   // pieces (some pieces would say false but the whole thing says true).
597   for (auto* child : expr->children()) {
598     if (!CanBeEvaluatedAtCompileTime(child, context))
599       return false;
600   }
601 
602   // If the expression depends on template input, we can not call
603   // isEvaluatable() on it as it will do bad things/crash.
604   if (!expr->isInstantiationDependent()) {
605     // If the expression can be evaluated at compile time, then it should have a
606     // kFoo style name. Otherwise, not.
607     return expr->isEvaluatable(context);
608   }
609 
610   // We do our best to figure out special cases as we come across them here, for
611   // template dependent situations. Some cases in code are only considered
612   // instantiation dependent for some template instantiations! Which is
613   // terrible! So most importantly we try to match isEvaluatable in those cases.
614   switch (expr->getStmtClass()) {
615     case clang::Stmt::CXXThisExprClass:
616       return false;
617     case clang::Stmt::DeclRefExprClass: {
618       auto* declref = clang::dyn_cast<clang::DeclRefExpr>(expr);
619       auto* decl = declref->getDecl();
620       if (auto* vardecl = clang::dyn_cast<clang::VarDecl>(decl)) {
621         if (auto* initializer = vardecl->getInit())
622           return CanBeEvaluatedAtCompileTime(initializer, context);
623         return false;
624       }
625       break;
626     }
627 
628     default:
629       break;
630   }
631 
632   // Otherwise, we consider depending on template parameters to not interfere
633   // with being const.. with exceptions hopefully covered above.
634   return true;
635 }
636 
IsProbablyConst(const clang::VarDecl & decl,const clang::ASTContext & context)637 bool IsProbablyConst(const clang::VarDecl& decl,
638                      const clang::ASTContext& context) {
639   clang::QualType type = decl.getType();
640   if (!type.isConstQualified())
641     return false;
642 
643   if (type.isVolatileQualified())
644     return false;
645 
646   if (decl.isConstexpr())
647     return true;
648 
649   // Parameters should not be renamed to |kFooBar| style (even if they are
650   // const and have an initializer (aka default value)).
651   if (clang::isa<clang::ParmVarDecl>(&decl))
652     return false;
653 
654   // http://google.github.io/styleguide/cppguide.html#Constant_Names
655   // Static variables that are const-qualified should use kConstantStyle naming.
656   if (decl.getStorageDuration() == clang::SD_Static)
657     return true;
658 
659   const clang::Expr* initializer = decl.getInit();
660   if (!initializer)
661     return false;
662 
663   return CanBeEvaluatedAtCompileTime(initializer, context);
664 }
665 
AST_MATCHER_P(clang::QualType,hasString,std::string,ExpectedString)666 AST_MATCHER_P(clang::QualType, hasString, std::string, ExpectedString) {
667   return ExpectedString == Node.getAsString();
668 }
669 
ShouldPrefixFunctionName(const std::string & old_method_name)670 bool ShouldPrefixFunctionName(const std::string& old_method_name) {
671   // Functions that are named similarily to a type - they should be prefixed
672   // with a "Get" prefix.
673   static const char* kConflictingMethods[] = {"accumulatorMap",
674                                               "animationWorklet",
675                                               "attrNodeList",
676                                               "audioWorklet",
677                                               "binaryType",
678                                               "blob",
679                                               "channelCountMode",
680                                               "color",
681                                               "compositorElementId",
682                                               "constructionStack",
683                                               "controlSize",
684                                               "counterDirectives",
685                                               "counterMaps",
686                                               "document",
687                                               "dragOperation",
688                                               "element",
689                                               "emptyChromeClient",
690                                               "emptyEditorClient",
691                                               "emptySpellCheckerClient",
692                                               "entryType",
693                                               "error",
694                                               "eventTargetDataMap",
695                                               "fileUtilities",
696                                               "font",
697                                               "frame",
698                                               "frameBlameContext",
699                                               "frontend",
700                                               "gridCell",
701                                               "harfBuzzFontCache",
702                                               "hash",
703                                               "heapObjectHeader",
704                                               "heapObjectSet",
705                                               "iconURL",
706                                               "image",
707                                               "infoMap",
708                                               "inputMethodController",
709                                               "inputType",
710                                               "interpolationTypes",
711                                               "intervalArena",
712                                               "layout",
713                                               "layoutBlock",
714                                               "layoutObject",
715                                               "layoutSize",
716                                               "lineCap",
717                                               "lineEndings",
718                                               "lineJoin",
719                                               "listItems",
720                                               "locationInBackingMap",
721                                               "matchedProperties",
722                                               "midpointState",
723                                               "modifiers",
724                                               "mouseEvent",
725                                               "name",
726                                               "navigationType",
727                                               "node",
728                                               "notificationManager",
729                                               "originAccessMap",
730                                               "outcome",
731                                               "pagePopup",
732                                               "paintWorklet",
733                                               "path",
734                                               "position",
735                                               "presentationAttributeCache",
736                                               "processingInstruction",
737                                               "qualifiedNameCache",
738                                               "readyState",
739                                               "referrer",
740                                               "referrerPolicy",
741                                               "relList",
742                                               "resource",
743                                               "response",
744                                               "restrictedKeyMap",
745                                               "sandboxSupport",
746                                               "screenInfo",
747                                               "screenOrientationController",
748                                               "scrollAnimator",
749                                               "scrollbarPainterMap",
750                                               "scrollbarSet",
751                                               "selectionInDOMTree",
752                                               "selectionInFlatTree",
753                                               "selectionVisualRectMap",
754                                               "selectorTextCache",
755                                               "settings",
756                                               "shadowRootType",
757                                               "signalingState",
758                                               "snapshotById",
759                                               "state",
760                                               "stickyConstraintsMap",
761                                               "string",
762                                               "styleSharingList",
763                                               "styleSheet",
764                                               "supplementable",
765                                               "text",
766                                               "textAlign",
767                                               "textBaseline",
768                                               "textDirection",
769                                               "theme",
770                                               "thread",
771                                               "timing",
772                                               "topLevelBlameContext",
773                                               "type",
774                                               "vector",
775                                               "visibleSelection",
776                                               "visibleSelectionInFlatTree",
777                                               "weakHeapObjectSet",
778                                               "webFrame",
779                                               "widget",
780                                               "wordBoundaries",
781                                               "workerThread",
782                                               "worldId",
783                                               "worldMap",
784                                               "wrapperTypeInfo"};
785   for (const auto& conflicting_method : kConflictingMethods) {
786     if (old_method_name == conflicting_method)
787       return true;
788   }
789 
790   return false;
791 }
792 
AST_MATCHER(clang::FunctionDecl,shouldPrefixFunctionName)793 AST_MATCHER(clang::FunctionDecl, shouldPrefixFunctionName) {
794   return Node.getDeclName().isIdentifier() &&
795       ShouldPrefixFunctionName(Node.getName().str());
796 }
797 
GetNameForDecl(const clang::FunctionDecl & decl,clang::ASTContext & context,std::string & name)798 bool GetNameForDecl(const clang::FunctionDecl& decl,
799                     clang::ASTContext& context,
800                     std::string& name) {
801   name = decl.getName().str();
802   name[0] = clang::toUppercase(name[0]);
803 
804   // Given
805   //   class Foo {};
806   //   class DerivedFoo : class Foo;
807   //   using Bar = Foo;
808   //   Bar f1();  // <- |Bar| would be matched by hasString("Bar") below.
809   //   Bar f2();  // <- |Bar| would be matched by hasName("Foo") below.
810   //   DerivedFoo f3();  // <- |DerivedFoo| matched by isDerivedFrom(...) below.
811   // |type_with_same_name_as_function| matcher matches Bar and Foo return types.
812   auto type_with_same_name_as_function = qualType(anyOf(
813       // hasString matches the type as spelled (Bar above).
814       hasString(name),
815       // hasDeclaration matches resolved type (Foo or DerivedFoo above).
816       hasDeclaration(namedDecl(hasName(name)))));
817 
818   // |type_containing_same_name_as_function| matcher will match all of the
819   // return types below:
820   // - Foo foo()  // Direct application of |type_with_same_name_as_function|.
821   // - Foo* foo()  // |hasDescendant| traverses references/pointers.
822   // - RefPtr<Foo> foo()  // |hasDescendant| traverses template arguments.
823   auto type_containing_same_name_as_function =
824       qualType(anyOf(type_with_same_name_as_function,
825                      hasDescendant(type_with_same_name_as_function)));
826   // https://crbug.com/582312: Prepend "Get" if method name conflicts with
827   // return type.
828   auto conflict_matcher = functionDecl(anyOf(
829       // For functions and non-virtual or base method implementations just
830       // compare with the immediate return type.
831       functionDecl(returns(type_containing_same_name_as_function),
832                    unless(cxxMethodDecl(isOverride()))),
833       // For methods that override one or more methods, compare with the return
834       // type of the *base* methods.
835       cxxMethodDecl(isOverride(), forEachOverridden(returns(
836                                       type_containing_same_name_as_function))),
837       // And also check hardcoded list of function names to prefix with "Get".
838       shouldPrefixFunctionName()));
839   if (IsMatching(conflict_matcher, decl, context))
840     name = "Get" + name;
841 
842   return true;
843 }
844 
GetNameForDecl(const clang::EnumConstantDecl & decl,clang::ASTContext & context,std::string & name)845 bool GetNameForDecl(const clang::EnumConstantDecl& decl,
846                     clang::ASTContext& context,
847                     std::string& name) {
848   StringRef original_name = decl.getName();
849 
850   // If it's already correct leave it alone.
851   if (original_name.size() >= 2 && original_name[0] == 'k' &&
852       clang::isUppercase(original_name[1]))
853     return false;
854 
855   bool is_shouty = true;
856   for (char c : original_name) {
857     if (!clang::isUppercase(c) && !clang::isDigit(c) && c != '_') {
858       is_shouty = false;
859       break;
860     }
861   }
862 
863   if (is_shouty)
864     return false;
865 
866   name = 'k';  // k prefix on enum values.
867   name += original_name;
868   name[1] = clang::toUppercase(name[1]);
869   return true;
870 }
871 
GetNameForDecl(const clang::FieldDecl & decl,clang::ASTContext & context,std::string & name)872 bool GetNameForDecl(const clang::FieldDecl& decl,
873                     clang::ASTContext& context,
874                     std::string& name) {
875   StringRef original_name = decl.getName();
876   bool member_prefix = original_name.startswith(kBlinkFieldPrefix);
877 
878   StringRef rename_part = !member_prefix
879                               ? original_name
880                               : original_name.substr(strlen(kBlinkFieldPrefix));
881   name = CamelCaseToUnderscoreCase(rename_part);
882 
883   // Assume that prefix of m_ was intentional and always replace it with a
884   // suffix _.
885   if (member_prefix && name.back() != '_')
886     name += '_';
887 
888   return true;
889 }
890 
GetNameForDecl(const clang::VarDecl & decl,clang::ASTContext & context,std::string & name)891 bool GetNameForDecl(const clang::VarDecl& decl,
892                     clang::ASTContext& context,
893                     std::string& name) {
894   StringRef original_name = decl.getName();
895 
896   // Nothing to do for unnamed parameters.
897   if (clang::isa<clang::ParmVarDecl>(decl) && original_name.empty())
898     return false;
899 
900   // This is a type trait that appears in consumers of WTF as well as inside
901   // WTF. We want it to be named in this_style_of_case accordingly.
902   if (IsKnownTraitName(original_name)) {
903     name = CamelCaseToUnderscoreCase(original_name);
904     return true;
905   }
906 
907   // static class members match against VarDecls. Blink style dictates that
908   // these should be prefixed with `s_`, so strip that off. Also check for `m_`
909   // and strip that off too, for code that accidentally uses the wrong prefix.
910   if (original_name.startswith(kBlinkStaticMemberPrefix))
911     original_name = original_name.substr(strlen(kBlinkStaticMemberPrefix));
912   else if (original_name.startswith(kBlinkFieldPrefix))
913     original_name = original_name.substr(strlen(kBlinkFieldPrefix));
914 
915   bool is_const = IsProbablyConst(decl, context);
916   if (is_const) {
917     // Don't try to rename constants that already conform to Chrome style.
918     if (original_name.size() >= 2 && original_name[0] == 'k' &&
919         clang::isUppercase(original_name[1]))
920       return false;
921     // Or names are spelt with underscore casing. While they are actually
922     // compile consts, the author wrote it explicitly as a variable not as
923     // a constant (they would have used kFormat otherwise here), so preserve
924     // it rather than try to mangle a kFormat out of it.
925     if (original_name.find('_') != StringRef::npos)
926       return false;
927 
928     name = 'k';
929     name.append(original_name.data(), original_name.size());
930     name[1] = clang::toUppercase(name[1]);
931   } else {
932     name = CamelCaseToUnderscoreCase(original_name);
933 
934     // Non-const variables with static storage duration at namespace scope are
935     // prefixed with `g_' to reduce the likelihood of a naming collision.
936     const clang::DeclContext* decl_context = decl.getDeclContext();
937     if (name.find("g_") != 0 && decl.hasGlobalStorage() &&
938         decl_context->isNamespace())
939       name.insert(0, "g_");
940   }
941 
942   // Static members end with _ just like other members, but constants should
943   // not.
944   if (!is_const && decl.isStaticDataMember()) {
945     name += '_';
946   }
947 
948   return true;
949 }
950 
GetNameForDecl(const clang::FunctionTemplateDecl & decl,clang::ASTContext & context,std::string & name)951 bool GetNameForDecl(const clang::FunctionTemplateDecl& decl,
952                     clang::ASTContext& context,
953                     std::string& name) {
954   clang::FunctionDecl* templated_function = decl.getTemplatedDecl();
955   return GetNameForDecl(*templated_function, context, name);
956 }
957 
GetNameForDecl(const clang::NamedDecl & decl,clang::ASTContext & context,std::string & name)958 bool GetNameForDecl(const clang::NamedDecl& decl,
959                     clang::ASTContext& context,
960                     std::string& name) {
961   if (auto* function = clang::dyn_cast<clang::FunctionDecl>(&decl))
962     return GetNameForDecl(*function, context, name);
963   if (auto* var = clang::dyn_cast<clang::VarDecl>(&decl))
964     return GetNameForDecl(*var, context, name);
965   if (auto* field = clang::dyn_cast<clang::FieldDecl>(&decl))
966     return GetNameForDecl(*field, context, name);
967   if (auto* function_template =
968           clang::dyn_cast<clang::FunctionTemplateDecl>(&decl))
969     return GetNameForDecl(*function_template, context, name);
970   if (auto* enumc = clang::dyn_cast<clang::EnumConstantDecl>(&decl))
971     return GetNameForDecl(*enumc, context, name);
972 
973   return false;
974 }
975 
GetNameForDecl(const clang::UsingDecl & decl,clang::ASTContext & context,std::string & name)976 bool GetNameForDecl(const clang::UsingDecl& decl,
977                     clang::ASTContext& context,
978                     std::string& name) {
979   assert(decl.shadow_size() > 0);
980 
981   // If a using declaration's targeted declaration is a set of overloaded
982   // functions, it can introduce multiple shadowed declarations. Just using the
983   // first one is OK, since overloaded functions have the same name, by
984   // definition.
985   return GetNameForDecl(*decl.shadow_begin()->getTargetDecl(), context, name);
986 }
987 
988 template <typename Type>
989 struct TargetNodeTraits;
990 
991 template <>
992 struct TargetNodeTraits<clang::NamedDecl> {
GetLoc__anon405ffcd00111::TargetNodeTraits993   static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) {
994     return decl.getLocation();
995   }
GetName__anon405ffcd00111::TargetNodeTraits996   static const char* GetName() { return "decl"; }
GetType__anon405ffcd00111::TargetNodeTraits997   static const char* GetType() { return "NamedDecl"; }
998 };
999 
1000 template <>
1001 struct TargetNodeTraits<clang::MemberExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1002   static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) {
1003     return expr.getMemberLoc();
1004   }
GetName__anon405ffcd00111::TargetNodeTraits1005   static const char* GetName() { return "expr"; }
GetType__anon405ffcd00111::TargetNodeTraits1006   static const char* GetType() { return "MemberExpr"; }
1007 };
1008 
1009 template <>
1010 struct TargetNodeTraits<clang::DeclRefExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1011   static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) {
1012     return expr.getLocation();
1013   }
GetName__anon405ffcd00111::TargetNodeTraits1014   static const char* GetName() { return "expr"; }
GetType__anon405ffcd00111::TargetNodeTraits1015   static const char* GetType() { return "DeclRefExpr"; }
1016 };
1017 
1018 template <>
1019 struct TargetNodeTraits<clang::DependentScopeDeclRefExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1020   static clang::SourceLocation GetLoc(
1021       const clang::DependentScopeDeclRefExpr& expr) {
1022     return expr.getLocation();
1023   }
GetName__anon405ffcd00111::TargetNodeTraits1024   static const char* GetName() { return "expr"; }
1025 };
1026 
1027 template <>
1028 struct TargetNodeTraits<clang::CXXDependentScopeMemberExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1029   static clang::SourceLocation GetLoc(
1030       const clang::CXXDependentScopeMemberExpr& expr) {
1031     return expr.getMemberLoc();
1032   }
GetName__anon405ffcd00111::TargetNodeTraits1033   static const char* GetName() { return "expr"; }
1034 };
1035 
1036 template <>
1037 struct TargetNodeTraits<clang::CXXCtorInitializer> {
GetLoc__anon405ffcd00111::TargetNodeTraits1038   static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) {
1039     assert(init.isWritten());
1040     return init.getSourceLocation();
1041   }
GetName__anon405ffcd00111::TargetNodeTraits1042   static const char* GetName() { return "initializer"; }
GetType__anon405ffcd00111::TargetNodeTraits1043   static const char* GetType() { return "CXXCtorInitializer"; }
1044 };
1045 
1046 template <>
1047 struct TargetNodeTraits<clang::UnresolvedLookupExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1048   static clang::SourceLocation GetLoc(const clang::UnresolvedLookupExpr& expr) {
1049     return expr.getNameLoc();
1050   }
GetName__anon405ffcd00111::TargetNodeTraits1051   static const char* GetName() { return "expr"; }
GetType__anon405ffcd00111::TargetNodeTraits1052   static const char* GetType() { return "UnresolvedLookupExpr"; }
1053 };
1054 
1055 template <>
1056 struct TargetNodeTraits<clang::UnresolvedMemberExpr> {
GetLoc__anon405ffcd00111::TargetNodeTraits1057   static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) {
1058     return expr.getMemberLoc();
1059   }
GetName__anon405ffcd00111::TargetNodeTraits1060   static const char* GetName() { return "expr"; }
GetType__anon405ffcd00111::TargetNodeTraits1061   static const char* GetType() { return "UnresolvedMemberExpr"; }
1062 };
1063 
1064 template <>
1065 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> {
GetLoc__anon405ffcd00111::TargetNodeTraits1066   static clang::SourceLocation GetLoc(
1067       const clang::UnresolvedUsingValueDecl& decl) {
1068     return decl.getNameInfo().getLoc();
1069   }
GetName__anon405ffcd00111::TargetNodeTraits1070   static const char* GetName() { return "decl"; }
GetType__anon405ffcd00111::TargetNodeTraits1071   static const char* GetType() { return "UnresolvedUsingValueDecl"; }
1072 };
1073 
1074 template <typename TargetNode>
1075 class RewriterBase : public MatchFinder::MatchCallback {
1076  public:
RewriterBase(std::set<Replacement> * replacements,RenameCategory category)1077   explicit RewriterBase(std::set<Replacement>* replacements,
1078                         RenameCategory category)
1079       : replacements_(replacements), edit_tracker_(category) {}
1080 
GetTargetNode(const MatchFinder::MatchResult & result)1081   const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) {
1082     const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>(
1083         TargetNodeTraits<TargetNode>::GetName());
1084     assert(target_node);
1085     return *target_node;
1086   }
1087 
GenerateReplacement(const MatchFinder::MatchResult & result,clang::SourceLocation loc,llvm::StringRef old_name,std::string new_name,Replacement * replacement)1088   bool GenerateReplacement(const MatchFinder::MatchResult& result,
1089                            clang::SourceLocation loc,
1090                            llvm::StringRef old_name,
1091                            std::string new_name,
1092                            Replacement* replacement) {
1093     const clang::ASTContext& context = *result.Context;
1094     const clang::SourceManager& source_manager = *result.SourceManager;
1095 
1096     if (loc.isMacroID()) {
1097       // Try to jump "above" the scratch buffer if |loc| is inside
1098       // token##Concatenation.
1099       const int kMaxJumps = 5;
1100       bool verified_out_of_scratch_space = false;
1101       for (int i = 0; i < kMaxJumps && !verified_out_of_scratch_space; i++) {
1102         clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
1103         verified_out_of_scratch_space =
1104             source_manager.getBufferName(spell) != "<scratch space>";
1105         if (!verified_out_of_scratch_space)
1106           loc = source_manager.getImmediateMacroCallerLoc(loc);
1107       }
1108       if (!verified_out_of_scratch_space)
1109         return false;
1110     }
1111 
1112     // If the edit affects only the first character of the identifier, then
1113     // narrow down the edit to only this single character.  This is important
1114     // for dealing with toFooBar -> ToFooBar method renaming when the method
1115     // name is built using macro token concatenation like to##macroArgument - in
1116     // this case we should only rewrite "t" -> "T" and leave "o##macroArgument"
1117     // untouched.
1118     llvm::StringRef expected_old_text = old_name;
1119     llvm::StringRef new_text = new_name;
1120     if (loc.isMacroID() && expected_old_text.substr(1) == new_text.substr(1)) {
1121       expected_old_text = expected_old_text.substr(0, 1);
1122       new_text = new_text.substr(0, 1);
1123     }
1124     clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
1125     clang::CharSourceRange range = clang::CharSourceRange::getCharRange(
1126         spell, spell.getLocWithOffset(expected_old_text.size()));
1127 
1128     // We need to ensure that |actual_old_text| is the same as
1129     // |expected_old_text| - it can be different if |actual_old_text| contains
1130     // a macro argument (see DEFINE_WITH_TOKEN_CONCATENATION2 in
1131     // macros-original.cc testcase).
1132     StringRef actual_old_text = clang::Lexer::getSourceText(
1133         range, source_manager, context.getLangOpts());
1134     if (actual_old_text != expected_old_text)
1135       return false;
1136 
1137     if (replacement) {
1138       // If there's already a replacement for this location, don't emit any
1139       // other replacements to avoid potential naming conflicts. This is
1140       // primarily to avoid problems when a function and a parameter are defined
1141       // by the same macro argument.
1142       if (!GetRewrittenLocs().emplace(spell).second)
1143         return false;
1144 
1145       *replacement = Replacement(source_manager, range, new_text);
1146     }
1147     return true;
1148   }
1149 
GetTargetLoc(const MatchFinder::MatchResult & result)1150   virtual clang::SourceLocation GetTargetLoc(
1151       const MatchFinder::MatchResult& result) {
1152     return TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result));
1153   }
1154 
AddReplacement(const MatchFinder::MatchResult & result,llvm::StringRef old_name,std::string new_name)1155   void AddReplacement(const MatchFinder::MatchResult& result,
1156                       llvm::StringRef old_name,
1157                       std::string new_name) {
1158     if (old_name == new_name)
1159       return;
1160 
1161     clang::SourceLocation loc = GetTargetLoc(result);
1162     if (loc.isInvalid())
1163       return;
1164 
1165     Replacement replacement;
1166     if (!GenerateReplacement(result, loc, old_name, new_name, &replacement))
1167       return;
1168 
1169     replacements_->insert(std::move(replacement));
1170     edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name);
1171   }
1172 
edit_tracker() const1173   const EditTracker* edit_tracker() const { return &edit_tracker_; }
1174 
1175  private:
1176   std::set<Replacement>* const replacements_;
1177   EditTracker edit_tracker_;
1178 };
1179 
1180 template <typename DeclNode>
1181 RenameCategory GetCategory();
1182 template <>
GetCategory()1183 RenameCategory GetCategory<clang::FieldDecl>() {
1184   return RenameCategory::kField;
1185 }
1186 template <>
GetCategory()1187 RenameCategory GetCategory<clang::VarDecl>() {
1188   return RenameCategory::kVariable;
1189 }
1190 template <>
GetCategory()1191 RenameCategory GetCategory<clang::FunctionDecl>() {
1192   return RenameCategory::kFunction;
1193 }
1194 template <>
GetCategory()1195 RenameCategory GetCategory<clang::CXXMethodDecl>() {
1196   return RenameCategory::kFunction;
1197 }
1198 template <>
GetCategory()1199 RenameCategory GetCategory<clang::EnumConstantDecl>() {
1200   return RenameCategory::kEnumValue;
1201 }
1202 template <>
GetCategory()1203 RenameCategory GetCategory<clang::NamedDecl>() {
1204   return RenameCategory::kUnresolved;
1205 }
1206 template <>
GetCategory()1207 RenameCategory GetCategory<clang::UsingDecl>() {
1208   return RenameCategory::kUnresolved;
1209 }
1210 
1211 template <typename DeclNode, typename TargetNode>
1212 class DeclRewriterBase : public RewriterBase<TargetNode> {
1213  public:
1214   using Base = RewriterBase<TargetNode>;
1215 
DeclRewriterBase(std::set<Replacement> * replacements)1216   explicit DeclRewriterBase(std::set<Replacement>* replacements)
1217       : Base(replacements, GetCategory<DeclNode>()) {}
1218 
run(const MatchFinder::MatchResult & result)1219   void run(const MatchFinder::MatchResult& result) override {
1220     const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
1221     if (!decl->getDeclName().isIdentifier())
1222       return;
1223 
1224     assert(decl);
1225     llvm::StringRef old_name = decl->getName();
1226 
1227     // Return early if there's no name to be renamed.
1228     if (!decl->getIdentifier())
1229       return;
1230 
1231     // Get the new name.
1232     std::string new_name;
1233     if (!GetNameForDecl(*decl, *result.Context, new_name))
1234       return;  // If false, the name was not suitable for renaming.
1235 
1236     // Check if we are able to rewrite the decl (to avoid rewriting if the
1237     // decl's identifier is part of macro##Token##Concatenation).
1238     clang::SourceLocation decl_loc =
1239         TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
1240     if (!Base::GenerateReplacement(result, decl_loc, old_name, new_name,
1241                                    nullptr))
1242       return;
1243 
1244     Base::AddReplacement(result, old_name, std::move(new_name));
1245   }
1246 };
1247 
1248 using FieldDeclRewriter = DeclRewriterBase<clang::FieldDecl, clang::NamedDecl>;
1249 using VarDeclRewriter = DeclRewriterBase<clang::VarDecl, clang::NamedDecl>;
1250 using MemberRewriter = DeclRewriterBase<clang::FieldDecl, clang::MemberExpr>;
1251 using DeclRefRewriter = DeclRewriterBase<clang::VarDecl, clang::DeclRefExpr>;
1252 using FieldDeclRefRewriter =
1253     DeclRewriterBase<clang::FieldDecl, clang::DeclRefExpr>;
1254 using FunctionDeclRewriter =
1255     DeclRewriterBase<clang::FunctionDecl, clang::NamedDecl>;
1256 using FunctionRefRewriter =
1257     DeclRewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
1258 using ConstructorInitializerRewriter =
1259     DeclRewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
1260 
1261 using MethodDeclRewriter =
1262     DeclRewriterBase<clang::CXXMethodDecl, clang::NamedDecl>;
1263 using MethodRefRewriter =
1264     DeclRewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>;
1265 using MethodMemberRewriter =
1266     DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
1267 
1268 using EnumConstantDeclRewriter =
1269     DeclRewriterBase<clang::EnumConstantDecl, clang::NamedDecl>;
1270 using EnumConstantDeclRefRewriter =
1271     DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>;
1272 
1273 using UnresolvedLookupRewriter =
1274     DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>;
1275 using UnresolvedMemberRewriter =
1276     DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>;
1277 
1278 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>;
1279 
1280 class GMockMemberRewriter
1281     : public DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr> {
1282  public:
1283   using Base = DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
1284 
GMockMemberRewriter(std::set<Replacement> * replacements)1285   explicit GMockMemberRewriter(std::set<Replacement>* replacements)
1286       : Base(replacements) {}
1287 
CreatePreprocessorCallbacks()1288   std::unique_ptr<clang::PPCallbacks> CreatePreprocessorCallbacks() {
1289     return llvm::make_unique<GMockMemberRewriter::PPCallbacks>(this);
1290   }
1291 
GetTargetLoc(const MatchFinder::MatchResult & result)1292   clang::SourceLocation GetTargetLoc(
1293       const MatchFinder::MatchResult& result) override {
1294     // Find location of the gmock_##MockedMethod identifier.
1295     clang::SourceLocation target_loc = Base::GetTargetLoc(result);
1296 
1297     // Find location of EXPECT_CALL or ON_CALL macro invocation.
1298     clang::SourceLocation macro_call_loc =
1299         result.SourceManager->getExpansionLoc(target_loc);
1300 
1301     // Map |macro_call_loc| to argument location (location of the method name
1302     // that needs renaming).
1303     auto it = gmock_macro_call_to_2nd_arg.find(macro_call_loc);
1304     if (it == gmock_macro_call_to_2nd_arg.end())
1305       return clang::SourceLocation();
1306     return it->second;
1307   }
1308 
1309  private:
1310   std::map<clang::SourceLocation, clang::SourceLocation>
1311       gmock_macro_call_to_2nd_arg;
1312 
1313   // Called from PPCallbacks with the locations of EXPECT_CALL and ON_CALL macro
1314   // invocation.  Example:
1315   //   EXPECT_CALL(my_mock, myMethod(123, 456));
1316   //   ^- expansion_loc     ^- actual_arg_loc
RecordGMockMacroInvocation(clang::SourceLocation expansion_loc,clang::SourceLocation second_arg_loc)1317   void RecordGMockMacroInvocation(clang::SourceLocation expansion_loc,
1318                                   clang::SourceLocation second_arg_loc) {
1319     gmock_macro_call_to_2nd_arg[expansion_loc] = second_arg_loc;
1320   }
1321 
1322   class PPCallbacks : public clang::PPCallbacks {
1323    public:
PPCallbacks(GMockMemberRewriter * rewriter)1324     explicit PPCallbacks(GMockMemberRewriter* rewriter) : rewriter_(rewriter) {}
~PPCallbacks()1325     ~PPCallbacks() override {}
MacroExpands(const clang::Token & name,const clang::MacroDefinition & def,clang::SourceRange range,const clang::MacroArgs * args)1326     void MacroExpands(const clang::Token& name,
1327                       const clang::MacroDefinition& def,
1328                       clang::SourceRange range,
1329                       const clang::MacroArgs* args) override {
1330       clang::IdentifierInfo* id = name.getIdentifierInfo();
1331       if (!id)
1332         return;
1333 
1334       if (id->getName() != "EXPECT_CALL" && id->getName() != "ON_CALL")
1335         return;
1336 
1337       if (def.getMacroInfo()->getNumParams() != 2)
1338         return;
1339 
1340       // TODO(lukasza): Should check if def.getMacroInfo()->getDefinitionLoc()
1341       // is in testing/gmock/include/gmock/gmock-spec-builders.h but I don't
1342       // know how to get clang::SourceManager to call getFileName.
1343 
1344       rewriter_->RecordGMockMacroInvocation(
1345           name.getLocation(), args->getUnexpArgument(1)->getLocation());
1346     }
1347 
1348    private:
1349     GMockMemberRewriter* rewriter_;
1350   };
1351 };
1352 
GetUnresolvedName(const clang::UnresolvedMemberExpr & expr)1353 clang::DeclarationName GetUnresolvedName(
1354     const clang::UnresolvedMemberExpr& expr) {
1355   return expr.getMemberName();
1356 }
1357 
GetUnresolvedName(const clang::DependentScopeDeclRefExpr & expr)1358 clang::DeclarationName GetUnresolvedName(
1359     const clang::DependentScopeDeclRefExpr& expr) {
1360   return expr.getDeclName();
1361 }
1362 
GetUnresolvedName(const clang::CXXDependentScopeMemberExpr & expr)1363 clang::DeclarationName GetUnresolvedName(
1364     const clang::CXXDependentScopeMemberExpr& expr) {
1365   return expr.getMember();
1366 }
1367 
GetUnresolvedName(const clang::UnresolvedUsingValueDecl & decl)1368 clang::DeclarationName GetUnresolvedName(
1369     const clang::UnresolvedUsingValueDecl& decl) {
1370   return decl.getDeclName();
1371 }
1372 
1373 // Returns whether |expr_node| is used as a callee in the AST (i.e. if
1374 // |expr_node| needs to resolve to a method or a function).
IsCallee(const clang::Expr & expr,clang::ASTContext & context)1375 bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) {
1376   auto matcher = stmt(hasParent(callExpr(callee(equalsNode(&expr)))));
1377   return IsMatching(matcher, expr, context);
1378 }
1379 
1380 // Returns whether |decl| will be used as a callee in the AST (i.e. if the value
1381 // brought by the using declaration will resolve to a method or a function).
IsCallee(const clang::UnresolvedUsingValueDecl & decl,clang::ASTContext &)1382 bool IsCallee(const clang::UnresolvedUsingValueDecl& decl,
1383               clang::ASTContext& /* context */) {
1384   // Caller (i.e. GuessNameForUnresolvedDependentNode) should have already
1385   // filtered out fields before calling |IsCallee|.
1386   clang::IdentifierInfo* info = GetUnresolvedName(decl).getAsIdentifierInfo();
1387   assert(info);
1388   bool name_looks_like_a_field = info->getName().startswith(kBlinkFieldPrefix);
1389   assert(!name_looks_like_a_field);
1390 
1391   // Looking just at clang::UnresolvedUsingValueDecl, we cannot tell whether it
1392   // refers to something callable or not.  Since fields should have been already
1393   // filtered out before calling IsCallee (see the assert above), let's assume
1394   // that |using Base::foo| refers to a method.
1395   return true;
1396 }
1397 
1398 template <typename TargetNode>
1399 class UnresolvedRewriterBase : public RewriterBase<TargetNode> {
1400  public:
1401   using Base = RewriterBase<TargetNode>;
1402 
UnresolvedRewriterBase(std::set<Replacement> * replacements)1403   explicit UnresolvedRewriterBase(std::set<Replacement>* replacements)
1404       : RewriterBase<TargetNode>(replacements, RenameCategory::kUnresolved) {}
1405 
run(const MatchFinder::MatchResult & result)1406   void run(const MatchFinder::MatchResult& result) override {
1407     const TargetNode& node = Base::GetTargetNode(result);
1408 
1409     clang::DeclarationName decl_name = GetUnresolvedName(node);
1410     switch (decl_name.getNameKind()) {
1411       // Do not rewrite this:
1412       //   return operator T*();
1413       // into this:
1414       //   return Operator type - parameter - 0 - 0 * T * ();
1415       case clang::DeclarationName::NameKind::CXXConversionFunctionName:
1416       case clang::DeclarationName::NameKind::CXXOperatorName:
1417       case clang::DeclarationName::NameKind::CXXLiteralOperatorName:
1418         return;
1419       default:
1420         break;
1421     }
1422 
1423     // Make sure there is an old name + extract the old name.
1424     clang::IdentifierInfo* info = GetUnresolvedName(node).getAsIdentifierInfo();
1425     if (!info)
1426       return;
1427     llvm::StringRef old_name = info->getName();
1428 
1429     // Try to guess a new name.
1430     std::string new_name;
1431     if (GuessNameForUnresolvedDependentNode(node, *result.Context, old_name,
1432                                             new_name))
1433       Base::AddReplacement(result, old_name, std::move(new_name));
1434   }
1435 
1436  private:
1437   // This method calculates a new name for nodes that depend on template
1438   // parameters (http://en.cppreference.com/w/cpp/language/dependent_name).  The
1439   // renaming is based on crude heuristics, because such nodes are not bound to
1440   // a specific decl until template instantiation - at the point of rename, one
1441   // cannot tell whether the node will eventually resolve to a field / method /
1442   // constant / etc.
1443   //
1444   // The method returns false if no renaming should be done.
1445   // Otherwise the method returns true and sets |new_name|.
GuessNameForUnresolvedDependentNode(const TargetNode & node,clang::ASTContext & context,llvm::StringRef old_name,std::string & new_name)1446   bool GuessNameForUnresolvedDependentNode(const TargetNode& node,
1447                                            clang::ASTContext& context,
1448                                            llvm::StringRef old_name,
1449                                            std::string& new_name) {
1450     // |m_fieldName| -> |field_name_|.
1451     if (old_name.startswith(kBlinkFieldPrefix)) {
1452       std::string field_name = old_name.substr(strlen(kBlinkFieldPrefix));
1453       if (field_name.find('_') == std::string::npos) {
1454         new_name = CamelCaseToUnderscoreCase(field_name) + "_";
1455         return true;
1456       }
1457     }
1458 
1459     // |T::myMethod(...)| -> |T::MyMethod(...)|.
1460     if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) &&
1461         !IsBlacklistedMethodName(old_name)) {
1462       new_name = old_name;
1463       new_name[0] = clang::toUppercase(old_name[0]);
1464       if (ShouldPrefixFunctionName(old_name))
1465         new_name = "Get" + new_name;
1466       return true;
1467     }
1468 
1469     // In the future we can consider more heuristics:
1470     // - "s_" and "g_" prefixes
1471     // - "ALL_CAPS"
1472     // - |T::myStaticField| -> |T::kMyStaticField|
1473     //   (but have to be careful not to rename |value| in WTF/TypeTraits.h?)
1474     return false;
1475   }
1476 };
1477 
1478 using UnresolvedDependentMemberRewriter =
1479     UnresolvedRewriterBase<clang::UnresolvedMemberExpr>;
1480 
1481 using UnresolvedUsingValueDeclRewriter =
1482     UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>;
1483 
1484 using DependentScopeDeclRefExprRewriter =
1485     UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>;
1486 
1487 using CXXDependentScopeMemberExprRewriter =
1488     UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>;
1489 
1490 class SourceFileCallbacks : public clang::tooling::SourceFileCallbacks {
1491  public:
SourceFileCallbacks(GMockMemberRewriter * gmock_member_rewriter)1492   explicit SourceFileCallbacks(GMockMemberRewriter* gmock_member_rewriter)
1493       : gmock_member_rewriter_(gmock_member_rewriter) {
1494     assert(gmock_member_rewriter);
1495   }
1496 
~SourceFileCallbacks()1497   ~SourceFileCallbacks() override {}
1498 
1499   // clang::tooling::SourceFileCallbacks override:
handleBeginSource(clang::CompilerInstance & compiler)1500   bool handleBeginSource(clang::CompilerInstance& compiler) override {
1501     compiler.getPreprocessor().addPPCallbacks(
1502         gmock_member_rewriter_->CreatePreprocessorCallbacks());
1503     return true;
1504   }
1505 
1506  private:
1507   GMockMemberRewriter* gmock_member_rewriter_;
1508 };
1509 
1510 }  // namespace
1511 
1512 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
1513 
main(int argc,const char * argv[])1514 int main(int argc, const char* argv[]) {
1515   // TODO(dcheng): Clang tooling should do this itself.
1516   // http://llvm.org/bugs/show_bug.cgi?id=21627
1517   llvm::InitializeNativeTarget();
1518   llvm::InitializeNativeTargetAsmParser();
1519   llvm::cl::OptionCategory category(
1520       "rewrite_to_chrome_style: convert Blink style to Chrome style.");
1521   llvm::cl::opt<std::string> blocklisted_methods_file(
1522       kMethodBlocklistParamName, llvm::cl::value_desc("filepath"),
1523       llvm::cl::desc("file listing methods to be blocked (not renamed)"));
1524   CommonOptionsParser options(argc, argv, category);
1525   MethodBlocklist method_blocklist(blocklisted_methods_file);
1526   clang::tooling::ClangTool tool(options.getCompilations(),
1527                                  options.getSourcePathList());
1528 
1529   MatchFinder match_finder;
1530   std::set<Replacement> replacements;
1531 
1532   // Blink namespace matchers ========
1533   auto blink_namespace_decl =
1534       namespaceDecl(anyOf(hasName("blink"), hasName("WTF")),
1535                     hasParent(translationUnitDecl()));
1536   auto protocol_namespace_decl =
1537       namespaceDecl(hasName("protocol"),
1538                     hasParent(namespaceDecl(hasName("blink"),
1539                                             hasParent(translationUnitDecl()))));
1540 
1541   // Given top-level compilation unit:
1542   //   namespace WTF {
1543   //     void foo() {}
1544   //   }
1545   // matches |foo|.
1546   auto decl_under_blink_namespace =
1547       decl(hasAncestor(blink_namespace_decl),
1548            unless(hasAncestor(protocol_namespace_decl)));
1549 
1550   // Given top-level compilation unit:
1551   //   void WTF::function() {}
1552   //   void WTF::Class::method() {}
1553   // matches |WTF::function| and |WTF::Class::method| decls.
1554   auto decl_has_qualifier_to_blink_namespace =
1555       declaratorDecl(has(nestedNameSpecifier(
1556           hasTopLevelPrefix(specifiesNamespace(blink_namespace_decl)))));
1557 
1558   auto in_blink_namespace = decl(
1559       anyOf(decl_under_blink_namespace, decl_has_qualifier_to_blink_namespace,
1560             hasAncestor(decl_has_qualifier_to_blink_namespace)),
1561       unless(hasCanonicalDecl(isDeclInGeneratedFile())));
1562 
1563   // Field, variable, and enum declarations ========
1564   // Given
1565   //   int x;
1566   //   struct S {
1567   //     int y;
1568   //     enum { VALUE };
1569   //   };
1570   // matches |x|, |y|, and |VALUE|.
1571   auto field_decl_matcher = id("decl", fieldDecl(in_blink_namespace));
1572   auto is_type_trait_value =
1573       varDecl(hasName("value"), hasStaticStorageDuration(), isPublic(),
1574               hasType(isConstQualified()),
1575               hasType(type(anyOf(builtinType(), enumType()))),
1576               unless(hasAncestor(recordDecl(
1577                   has(cxxMethodDecl(isUserProvided(), isInstanceMethod()))))));
1578   auto var_decl_matcher =
1579       id("decl", varDecl(in_blink_namespace, unless(is_type_trait_value)));
1580   // For known trait names, rename every instance anywhere in the codebase.
1581   auto type_trait_decl_matcher = id("decl", varDecl(isKnownTraitName()));
1582   auto enum_member_decl_matcher =
1583       id("decl", enumConstantDecl(in_blink_namespace));
1584 
1585   FieldDeclRewriter field_decl_rewriter(&replacements);
1586   match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter);
1587 
1588   VarDeclRewriter var_decl_rewriter(&replacements);
1589   match_finder.addMatcher(var_decl_matcher, &var_decl_rewriter);
1590   match_finder.addMatcher(type_trait_decl_matcher, &var_decl_rewriter);
1591 
1592   EnumConstantDeclRewriter enum_member_decl_rewriter(&replacements);
1593   match_finder.addMatcher(enum_member_decl_matcher, &enum_member_decl_rewriter);
1594 
1595   // Field, variable, and enum references ========
1596   // Given
1597   //   bool x = true;
1598   //   if (x) {
1599   //     ...
1600   //   }
1601   // matches |x| in if (x).
1602   auto member_matcher = id(
1603       "expr",
1604       memberExpr(
1605           member(field_decl_matcher),
1606           // Needed to avoid matching member references in functions (which will
1607           // be an ancestor of the member reference) synthesized by the
1608           // compiler, such as a synthesized copy constructor.
1609           // This skips explicitly defaulted functions as well, but that's OK:
1610           // there's nothing interesting to rewrite in those either.
1611           unless(hasAncestor(functionDecl(isDefaulted())))));
1612   auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher)));
1613   auto type_trait_ref_matcher =
1614       id("expr", declRefExpr(to(type_trait_decl_matcher)));
1615   auto enum_member_ref_matcher =
1616       id("expr", declRefExpr(to(enum_member_decl_matcher)));
1617 
1618   MemberRewriter member_rewriter(&replacements);
1619   match_finder.addMatcher(member_matcher, &member_rewriter);
1620 
1621   DeclRefRewriter decl_ref_rewriter(&replacements);
1622   match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter);
1623   match_finder.addMatcher(type_trait_ref_matcher, &decl_ref_rewriter);
1624 
1625   EnumConstantDeclRefRewriter enum_member_ref_rewriter(&replacements);
1626   match_finder.addMatcher(enum_member_ref_matcher, &enum_member_ref_rewriter);
1627 
1628   // Member references in a non-member context ========
1629   // Given
1630   //   struct S {
1631   //     typedef int U::*UnspecifiedBoolType;
1632   //     operator UnspecifiedBoolType() { return s_ ? &U::s_ : 0; }
1633   //     int s_;
1634   //   };
1635   // matches |&U::s_| but not |s_|.
1636   auto member_ref_matcher = id("expr", declRefExpr(to(field_decl_matcher)));
1637 
1638   FieldDeclRefRewriter member_ref_rewriter(&replacements);
1639   match_finder.addMatcher(member_ref_matcher, &member_ref_rewriter);
1640 
1641   // Non-method function declarations ========
1642   // Given
1643   //   void f();
1644   //   struct S {
1645   //     void g();
1646   //   };
1647   // matches |f| but not |g|.
1648   auto function_decl_matcher = id(
1649       "decl",
1650       functionDecl(
1651           unless(anyOf(
1652               // Methods are covered by the method matchers.
1653               cxxMethodDecl(),
1654               // Out-of-line overloaded operators have special names and should
1655               // never be renamed.
1656               isOverloadedOperator(),
1657               // Must be checked after filtering out overloaded operators to
1658               // prevent asserts about the identifier not being a simple name.
1659               isBlacklistedFunction(),
1660               // Functions that look like blocked static methods.
1661               isBlocklistedMethod(method_blocklist))),
1662           in_blink_namespace));
1663   FunctionDeclRewriter function_decl_rewriter(&replacements);
1664   match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter);
1665 
1666   // Non-method function references ========
1667   // Given
1668   //   f();
1669   //   void (*p)() = &f;
1670   // matches |f()| and |&f|.
1671   auto function_ref_matcher = id(
1672       "expr", declRefExpr(to(function_decl_matcher),
1673                           // Ignore template substitutions.
1674                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
1675   FunctionRefRewriter function_ref_rewriter(&replacements);
1676   match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter);
1677 
1678   // Method declarations ========
1679   // Given
1680   //   struct S {
1681   //     void g();
1682   //   };
1683   // matches |g|.
1684   // For a method to be considered for rewrite, it must not override something
1685   // that we're not rewriting. Any methods that we would not normally consider
1686   // but that override something we are rewriting should also be rewritten. So
1687   // we use includeAllOverriddenMethods() to check these rules not just for the
1688   // method being matched but for the methods it overrides also.
1689   auto is_blink_method = includeAllOverriddenMethods(
1690       allOf(in_blink_namespace,
1691             unless(anyOf(isBlacklistedMethod(),
1692                          isBlocklistedMethod(method_blocklist)))));
1693   auto method_decl_matcher = id(
1694       "decl",
1695       cxxMethodDecl(
1696           unless(anyOf(
1697               // Overloaded operators have special names and should never be
1698               // renamed.
1699               isOverloadedOperator(),
1700               // Similarly, constructors, destructors, and conversion
1701               // functions should not be considered for renaming.
1702               cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())),
1703           // Check this last after excluding things, to avoid
1704           // asserts about overriding non-blink and blink for the
1705           // same method.
1706           is_blink_method));
1707   MethodDeclRewriter method_decl_rewriter(&replacements);
1708   match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter);
1709 
1710   // Method references in a non-member context ========
1711   // Given
1712   //   S s;
1713   //   s.g();
1714   //   void (S::*p)() = &S::g;
1715   // matches |&S::g| but not |s.g|.
1716   auto method_ref_matcher = id(
1717       "expr", declRefExpr(to(method_decl_matcher),
1718                           // Ignore template substitutions.
1719                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
1720 
1721   MethodRefRewriter method_ref_rewriter(&replacements);
1722   match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter);
1723 
1724   // Method references in a member context ========
1725   // Given
1726   //   S s;
1727   //   s.g();
1728   //   void (S::*p)() = &S::g;
1729   // matches |s.g| but not |&S::g|.
1730   auto method_member_matcher =
1731       id("expr", memberExpr(member(method_decl_matcher)));
1732 
1733   MethodMemberRewriter method_member_rewriter(&replacements);
1734   match_finder.addMatcher(method_member_matcher, &method_member_rewriter);
1735 
1736   // Initializers ========
1737   // Given
1738   //   struct S {
1739   //     int x;
1740   //     S() : x(2) {}
1741   //   };
1742   // matches each initializer in the constructor for S.
1743   auto constructor_initializer_matcher =
1744       cxxConstructorDecl(forEachConstructorInitializer(id(
1745           "initializer",
1746           cxxCtorInitializer(forAnyField(field_decl_matcher), isWritten()))));
1747 
1748   ConstructorInitializerRewriter constructor_initializer_rewriter(
1749       &replacements);
1750   match_finder.addMatcher(constructor_initializer_matcher,
1751                           &constructor_initializer_rewriter);
1752 
1753   // Unresolved lookup expressions ========
1754   // Given
1755   //   template<typename T> void F(T) { }
1756   //   template<void G(T)> H(T) { }
1757   //   H<F<int>>(...);
1758   // matches |F| in |H<F<int>>|.
1759   //
1760   // UnresolvedLookupExprs are similar to DeclRefExprs that reference a
1761   // FunctionDecl, but are used when a candidate FunctionDecl can't be selected.
1762   // This commonly happens inside uninstantiated template definitions for one of
1763   // two reasons:
1764   //
1765   // 1. If the candidate declaration is a dependent FunctionTemplateDecl, the
1766   //    actual overload can't be selected until template instantiation time.
1767   // 2. Alternatively, there might be multiple declarations in the candidate set
1768   //    if the candidate function has overloads. If any of the function
1769   //    arguments has a dependent type, then the actual overload can't be
1770   //    selected until instantiation time either.
1771   //
1772   // Another instance where UnresolvedLookupExprs can appear is in a template
1773   // argument list, like the provided example.
1774   auto function_template_decl_matcher =
1775       id("decl", functionTemplateDecl(templatedDecl(function_decl_matcher)));
1776   auto method_template_decl_matcher =
1777       id("decl", functionTemplateDecl(templatedDecl(method_decl_matcher)));
1778   auto unresolved_lookup_matcher = expr(id(
1779       "expr",
1780       unresolvedLookupExpr(
1781           // In order to automatically rename an unresolved lookup, the lookup
1782           // candidates must either all be Blink functions/function templates or
1783           // all be Blink methods/method templates. Otherwise, we might end up
1784           // in a situation where the naming could change depending on the
1785           // selected candidate.
1786           anyOf(allOverloadsMatch(anyOf(function_decl_matcher,
1787                                         function_template_decl_matcher)),
1788                 // Note: this matches references to methods in a non-member
1789                 // context, e.g. Template<&Class::Method>. This and the
1790                 // UnresolvedMemberExpr matcher below are analogous to how the
1791                 // rewriter has both a MemberRefRewriter matcher to rewrite
1792                 // &T::method and a MethodMemberRewriter matcher to rewriter
1793                 // t.method().
1794                 allOverloadsMatch(anyOf(method_decl_matcher,
1795                                         method_template_decl_matcher))))));
1796   UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements);
1797   match_finder.addMatcher(unresolved_lookup_matcher,
1798                           &unresolved_lookup_rewriter);
1799 
1800   // Unresolved member expressions (for non-dependent fields / methods) ========
1801   // Similar to unresolved lookup expressions, but for methods in a member
1802   // context, e.g. var_with_templated_type.Method().
1803   auto unresolved_member_matcher = expr(id(
1804       "expr",
1805       unresolvedMemberExpr(
1806           // Similar to UnresolvedLookupExprs, all the candidate methods must be
1807           // Blink methods/method templates.
1808           allOverloadsMatch(
1809               anyOf(method_decl_matcher, method_template_decl_matcher)))));
1810   UnresolvedMemberRewriter unresolved_member_rewriter(&replacements);
1811   match_finder.addMatcher(unresolved_member_matcher,
1812                           &unresolved_member_rewriter);
1813 
1814   // Unresolved using value decls ========
1815   // Example:
1816   //  template <typename T>
1817   //  class BaseClass {
1818   //   public:
1819   //    unsigned long m_size;
1820   //  };
1821   //  template <typename T>
1822   //  class DerivedClass : protected BaseClass<T> {
1823   //   private:
1824   //    using Base = BaseClass<T>;
1825   //    using Base::m_size;  // <- |m_size| here is matched by
1826   //    void method() {      //    |unresolved_using_value_decl_matcher|.
1827   //      m_size = 123;  // <- |m_size| here is matched by
1828   //    }                //    |unresolved_dependent_using_matcher|.
1829   //  };
1830   auto unresolved_dependent_using_matcher =
1831       expr(id("expr", unresolvedMemberExpr(allOverloadsMatch(allOf(
1832                           in_blink_namespace, unresolvedUsingValueDecl())))));
1833   UnresolvedDependentMemberRewriter unresolved_dependent_member_rewriter(
1834       &replacements);
1835   match_finder.addMatcher(unresolved_dependent_using_matcher,
1836                           &unresolved_dependent_member_rewriter);
1837   auto unresolved_using_value_decl_matcher =
1838       decl(id("decl", unresolvedUsingValueDecl(in_blink_namespace)));
1839   UnresolvedUsingValueDeclRewriter unresolved_using_value_decl_rewriter(
1840       &replacements);
1841   match_finder.addMatcher(unresolved_using_value_decl_matcher,
1842                           &unresolved_using_value_decl_rewriter);
1843 
1844   // Using declarations ========
1845   // Given
1846   //   using blink::X;
1847   // matches |using blink::X|.
1848   auto using_decl_matcher = id(
1849       "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf(
1850                   var_decl_matcher, field_decl_matcher, function_decl_matcher,
1851                   method_decl_matcher, function_template_decl_matcher,
1852                   method_template_decl_matcher, enum_member_decl_matcher)))));
1853   UsingDeclRewriter using_decl_rewriter(&replacements);
1854   match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter);
1855 
1856   // Matches any QualType that refers to a blink type:
1857   // - const blink::Foo&
1858   // - blink::Foo*
1859   // - blink::Foo<T>
1860   auto blink_qual_type_base_matcher = hasBaseType(hasUnqualifiedDesugaredType(
1861       anyOf(enumType(hasDeclaration(in_blink_namespace)),
1862             injectedClassNameType(hasDeclaration(in_blink_namespace)),
1863             recordType(hasDeclaration(in_blink_namespace)),
1864             templateSpecializationType(hasDeclaration(in_blink_namespace)),
1865             templateTypeParmType(hasDeclaration(in_blink_namespace)))));
1866   auto blink_qual_type_matcher = qualType(anyOf(
1867       blink_qual_type_base_matcher, pointsTo(blink_qual_type_base_matcher),
1868       references(blink_qual_type_base_matcher)));
1869 
1870   // Template-dependent decl lookup ========
1871   // Given
1872   //   template <typename T> void f() { T::foo(); }
1873   // matches |T::foo|.
1874   auto dependent_scope_decl_ref_expr_matcher =
1875       expr(id("expr", dependentScopeDeclRefExpr(has(nestedNameSpecifier(
1876                           specifiesType(blink_qual_type_matcher))))));
1877   DependentScopeDeclRefExprRewriter dependent_scope_decl_ref_expr_rewriter(
1878       &replacements);
1879   match_finder.addMatcher(dependent_scope_decl_ref_expr_matcher,
1880                           &dependent_scope_decl_ref_expr_rewriter);
1881 
1882   // Template-dependent member lookup ========
1883   // Given
1884   //   template <typename T>
1885   //   class Foo {
1886   //     void f() { T::foo(); }
1887   //     void g(T x) { x.bar(); }
1888   //   };
1889   // matches |T::foo| and |x.bar|.
1890   auto cxx_dependent_scope_member_expr_matcher =
1891       expr(id("expr", cxxDependentScopeMemberExpr(
1892                           hasMemberFromType(blink_qual_type_matcher))));
1893   CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter(
1894       &replacements);
1895   match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher,
1896                           &cxx_dependent_scope_member_expr_rewriter);
1897 
1898   // GMock calls lookup ========
1899   // Given
1900   //   EXPECT_CALL(obj, myMethod(...))
1901   // or
1902   //   ON_CALL(obj, myMethod(...))
1903   // will match obj.gmock_myMethod(...) call generated by the macros
1904   // (but only if it mocks a Blink method).
1905   auto gmock_member_matcher =
1906       id("expr", memberExpr(hasDeclaration(
1907                      decl(cxxMethodDecl(mocksMethod(method_decl_matcher))))));
1908   GMockMemberRewriter gmock_member_rewriter(&replacements);
1909   match_finder.addMatcher(gmock_member_matcher, &gmock_member_rewriter);
1910 
1911   // Prepare and run the tool.
1912   SourceFileCallbacks source_file_callbacks(&gmock_member_rewriter);
1913   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
1914       clang::tooling::newFrontendActionFactory(&match_finder,
1915                                                &source_file_callbacks);
1916   int result = tool.run(factory.get());
1917   if (result != 0)
1918     return result;
1919 
1920   // Supplemental data for the Blink rename rebase helper.
1921   std::vector<const EditTracker*> all_edit_trackers{
1922       field_decl_rewriter.edit_tracker(),
1923       var_decl_rewriter.edit_tracker(),
1924       enum_member_decl_rewriter.edit_tracker(),
1925       member_rewriter.edit_tracker(),
1926       decl_ref_rewriter.edit_tracker(),
1927       enum_member_ref_rewriter.edit_tracker(),
1928       member_ref_rewriter.edit_tracker(),
1929       function_decl_rewriter.edit_tracker(),
1930       function_ref_rewriter.edit_tracker(),
1931       method_decl_rewriter.edit_tracker(),
1932       method_ref_rewriter.edit_tracker(),
1933       method_member_rewriter.edit_tracker(),
1934       constructor_initializer_rewriter.edit_tracker(),
1935       unresolved_lookup_rewriter.edit_tracker(),
1936       unresolved_member_rewriter.edit_tracker(),
1937       unresolved_dependent_member_rewriter.edit_tracker(),
1938       unresolved_using_value_decl_rewriter.edit_tracker(),
1939       using_decl_rewriter.edit_tracker(),
1940       dependent_scope_decl_ref_expr_rewriter.edit_tracker(),
1941       cxx_dependent_scope_member_expr_rewriter.edit_tracker(),
1942       gmock_member_rewriter.edit_tracker(),
1943   };
1944   llvm::outs() << "==== BEGIN TRACKED EDITS ====\n";
1945   for (const EditTracker* edit_tracker : all_edit_trackers)
1946     edit_tracker->SerializeTo(llvm::outs());
1947   llvm::outs() << "==== END TRACKED EDITS ====\n";
1948 
1949   // Serialization format is documented in tools/clang/scripts/run_tool.py
1950   llvm::outs() << "==== BEGIN EDITS ====\n";
1951   for (const auto& r : replacements) {
1952     std::string replacement_text = r.getReplacementText().str();
1953     std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
1954     llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
1955                  << ":::" << r.getLength() << ":::" << replacement_text << "\n";
1956   }
1957   llvm::outs() << "==== END EDITS ====\n";
1958 
1959   return 0;
1960 }
1961