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 <fstream>
18 #include <memory>
19 #include <string>
20 #include <unordered_map>
21 
22 #include "clang/AST/ASTContext.h"
23 #include "clang/ASTMatchers/ASTMatchFinder.h"
24 #include "clang/ASTMatchers/ASTMatchers.h"
25 #include "clang/ASTMatchers/ASTMatchersMacros.h"
26 #include "clang/Basic/CharInfo.h"
27 #include "clang/Basic/SourceManager.h"
28 #include "clang/Frontend/FrontendActions.h"
29 #include "clang/Lex/Lexer.h"
30 #include "clang/Tooling/CommonOptionsParser.h"
31 #include "clang/Tooling/Refactoring.h"
32 #include "clang/Tooling/Tooling.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/TargetSelect.h"
35 
36 #if defined(_WIN32)
37 #include <windows.h>
38 #else
39 #include <sys/file.h>
40 #include <unistd.h>
41 #endif
42 
43 using namespace clang::ast_matchers;
44 using clang::tooling::CommonOptionsParser;
45 using clang::tooling::Replacement;
46 using llvm::StringRef;
47 
48 namespace {
49 
50 const char kBlinkFieldPrefix[] = "m_";
51 const char kBlinkStaticMemberPrefix[] = "s_";
52 const char kGeneratedFileRegex[] = "^gen/|/gen/";
53 
54 const clang::ast_matchers::internal::
55     VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr>
56         unresolvedMemberExpr;
57 
AST_MATCHER(clang::FunctionDecl,isOverloadedOperator)58 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) {
59   return Node.isOverloadedOperator();
60 }
61 
AST_MATCHER(clang::CXXMethodDecl,isInstanceMethod)62 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) {
63   return Node.isInstance();
64 }
65 
AST_MATCHER_P(clang::FunctionTemplateDecl,templatedDecl,clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,InnerMatcher)66 AST_MATCHER_P(clang::FunctionTemplateDecl,
67               templatedDecl,
68               clang::ast_matchers::internal::Matcher<clang::FunctionDecl>,
69               InnerMatcher) {
70   return InnerMatcher.matches(*Node.getTemplatedDecl(), Finder, Builder);
71 }
72 
73 // If |InnerMatcher| matches |top|, then the returned matcher will match:
74 // - |top::function|
75 // - |top::Class::method|
76 // - |top::internal::Class::method|
AST_MATCHER_P(clang::NestedNameSpecifier,hasTopLevelPrefix,clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,InnerMatcher)77 AST_MATCHER_P(
78     clang::NestedNameSpecifier,
79     hasTopLevelPrefix,
80     clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,
81     InnerMatcher) {
82   const clang::NestedNameSpecifier* NodeToMatch = &Node;
83   while (NodeToMatch->getPrefix())
84     NodeToMatch = NodeToMatch->getPrefix();
85   return InnerMatcher.matches(*NodeToMatch, Finder, Builder);
86 }
87 
88 // This will narrow CXXCtorInitializers down for both FieldDecls and
89 // IndirectFieldDecls (ie. anonymous unions and such). In both cases
90 // getAnyMember() will return a FieldDecl which we can match against.
AST_MATCHER_P(clang::CXXCtorInitializer,forAnyField,clang::ast_matchers::internal::Matcher<clang::FieldDecl>,InnerMatcher)91 AST_MATCHER_P(clang::CXXCtorInitializer,
92               forAnyField,
93               clang::ast_matchers::internal::Matcher<clang::FieldDecl>,
94               InnerMatcher) {
95   const clang::FieldDecl* NodeAsDecl = Node.getAnyMember();
96   return (NodeAsDecl != nullptr &&
97           InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
98 }
99 
100 // 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)101 AST_MATCHER_P(clang::OverloadExpr,
102               allOverloadsMatch,
103               clang::ast_matchers::internal::Matcher<clang::NamedDecl>,
104               InnerMatcher) {
105   if (Node.getNumDecls() == 0)
106     return false;
107 
108   for (clang::NamedDecl* decl : Node.decls()) {
109     if (!InnerMatcher.matches(*decl, Finder, Builder))
110       return false;
111   }
112   return true;
113 }
114 
115 template <typename T>
MatchAllOverriddenMethods(const clang::CXXMethodDecl & decl,T && inner_matcher,clang::ast_matchers::internal::ASTMatchFinder * finder,clang::ast_matchers::internal::BoundNodesTreeBuilder * builder)116 bool MatchAllOverriddenMethods(
117     const clang::CXXMethodDecl& decl,
118     T&& inner_matcher,
119     clang::ast_matchers::internal::ASTMatchFinder* finder,
120     clang::ast_matchers::internal::BoundNodesTreeBuilder* builder) {
121   bool override_matches = false;
122   bool override_not_matches = false;
123 
124   for (auto it = decl.begin_overridden_methods();
125        it != decl.end_overridden_methods(); ++it) {
126     if (MatchAllOverriddenMethods(**it, inner_matcher, finder, builder))
127       override_matches = true;
128     else
129       override_not_matches = true;
130   }
131 
132   // If this fires we have a class overriding a method that matches, and a
133   // method that does not match the inner matcher. In that case we will match
134   // one ancestor method but not the other. If we rename one of the and not the
135   // other it will break what this class overrides, disconnecting it from the
136   // one we did not rename which creates a behaviour change. So assert and
137   // demand the user to fix the code first (or add the method to our
138   // blacklist T_T).
139   if (override_matches || override_not_matches)
140     assert(override_matches != override_not_matches);
141 
142   // If the method overrides something that doesn't match, so the method itself
143   // doesn't match.
144   if (override_not_matches)
145     return false;
146   // If the method overrides something that matches, so the method ifself
147   // matches.
148   if (override_matches)
149     return true;
150 
151   return inner_matcher.matches(decl, finder, builder);
152 }
153 
AST_MATCHER_P(clang::CXXMethodDecl,includeAllOverriddenMethods,clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,InnerMatcher)154 AST_MATCHER_P(clang::CXXMethodDecl,
155               includeAllOverriddenMethods,
156               clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>,
157               InnerMatcher) {
158   return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder);
159 }
160 
IsMethodOverrideOf(const clang::CXXMethodDecl & decl,const char * class_name)161 bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl,
162                         const char* class_name) {
163   if (decl.getParent()->getQualifiedNameAsString() == class_name)
164     return true;
165   for (auto it = decl.begin_overridden_methods();
166        it != decl.end_overridden_methods(); ++it) {
167     if (IsMethodOverrideOf(**it, class_name))
168       return true;
169   }
170   return false;
171 }
172 
IsBlacklistedFunction(const clang::FunctionDecl & decl)173 bool IsBlacklistedFunction(const clang::FunctionDecl& decl) {
174   // swap() functions should match the signature of std::swap for ADL tricks.
175   return decl.getName() == "swap";
176 }
177 
IsBlacklistedMethod(const clang::CXXMethodDecl & decl)178 bool IsBlacklistedMethod(const clang::CXXMethodDecl& decl) {
179   if (decl.isStatic())
180     return false;
181 
182   clang::StringRef name = decl.getName();
183 
184   // These methods should never be renamed.
185   static const char* kBlacklistMethods[] = {"trace", "traceImpl", "lock",
186                                             "unlock", "try_lock"};
187   for (const auto& b : kBlacklistMethods) {
188     if (name == b)
189       return true;
190   }
191 
192   // Iterator methods shouldn't be renamed to work with stl and range-for
193   // loops.
194   std::string ret_type = decl.getReturnType().getAsString();
195   if (ret_type.find("iterator") != std::string::npos ||
196       ret_type.find("Iterator") != std::string::npos) {
197     static const char* kIteratorBlacklist[] = {"begin", "end", "rbegin",
198                                                "rend"};
199     for (const auto& b : kIteratorBlacklist) {
200       if (name == b)
201         return true;
202     }
203   }
204 
205   // Subclasses of InspectorAgent will subclass "disable()" from both blink and
206   // from gen/, which is problematic, but DevTools folks don't want to rename
207   // it or split this up. So don't rename it at all.
208   if (name.equals("disable") &&
209       IsMethodOverrideOf(decl, "blink::InspectorAgent"))
210     return true;
211 
212   return false;
213 }
214 
AST_MATCHER(clang::FunctionDecl,isBlacklistedFunction)215 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) {
216   return IsBlacklistedFunction(Node);
217 }
218 
AST_MATCHER(clang::CXXMethodDecl,isBlacklistedMethod)219 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) {
220   return IsBlacklistedMethod(Node);
221 }
222 
223 // Helper to convert from a camelCaseName to camel_case_name. It uses some
224 // heuristics to try to handle acronyms in camel case names correctly.
CamelCaseToUnderscoreCase(StringRef input)225 std::string CamelCaseToUnderscoreCase(StringRef input) {
226   std::string output;
227   bool needs_underscore = false;
228   bool was_lowercase = false;
229   bool was_uppercase = false;
230   bool first_char = true;
231   // Iterate in reverse to minimize the amount of backtracking.
232   for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin();
233        --i) {
234     char c = *i;
235     bool is_lowercase = clang::isLowercase(c);
236     bool is_uppercase = clang::isUppercase(c);
237     c = clang::toLowercase(c);
238     // Transitioning from upper to lower case requires an underscore. This is
239     // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_'
240     // in 'dH'. This is a complement to the non-acronym case further down.
241     if (was_uppercase && is_lowercase)
242       needs_underscore = true;
243     if (needs_underscore) {
244       output += '_';
245       needs_underscore = false;
246     }
247     output += c;
248     // Handles the non-acronym case: transitioning from lower to upper case
249     // requires an underscore when emitting the next character, e.g. didLoad
250     // needs a '_' in 'dL'.
251     if (!first_char && was_lowercase && is_uppercase)
252       needs_underscore = true;
253     was_lowercase = is_lowercase;
254     was_uppercase = is_uppercase;
255     first_char = false;
256   }
257   std::reverse(output.begin(), output.end());
258   return output;
259 }
260 
IsProbablyConst(const clang::VarDecl & decl,const clang::ASTContext & context)261 bool IsProbablyConst(const clang::VarDecl& decl,
262                      const clang::ASTContext& context) {
263   clang::QualType type = decl.getType();
264   if (!type.isConstQualified())
265     return false;
266 
267   if (type.isVolatileQualified())
268     return false;
269 
270   // http://google.github.io/styleguide/cppguide.html#Constant_Names
271   // Static variables that are const-qualified should use kConstantStyle naming.
272   if (decl.getStorageDuration() == clang::SD_Static)
273     return true;
274 
275   const clang::Expr* initializer = decl.getInit();
276   if (!initializer)
277     return false;
278 
279   // If the expression is dependent on a template input, then we are not
280   // sure if it can be compile-time generated as calling isEvaluatable() is
281   // not valid on |initializer|.
282   // TODO(crbug.com/581218): We could probably look at each compiled
283   // instantiation of the template and see if they are all compile-time
284   // isEvaluable().
285   if (initializer->isInstantiationDependent())
286     return false;
287 
288   // If the expression can be evaluated at compile time, then it should have a
289   // kFoo style name. Otherwise, not.
290   return initializer->isEvaluatable(context);
291 }
292 
AST_MATCHER_P(clang::QualType,hasString,std::string,ExpectedString)293 AST_MATCHER_P(clang::QualType, hasString, std::string, ExpectedString) {
294   return ExpectedString == Node.getAsString();
295 }
296 
GetNameForDecl(const clang::FunctionDecl & decl,clang::ASTContext & context,std::string & name)297 bool GetNameForDecl(const clang::FunctionDecl& decl,
298                     clang::ASTContext& context,
299                     std::string& name) {
300   name = decl.getName().str();
301   name[0] = clang::toUppercase(name[0]);
302 
303   // Given
304   //   class Foo {};
305   //   using Bar = Foo;
306   //   Bar f1();  // <- |Bar| would be matched by hasString("Bar") below.
307   //   Bar f2();  // <- |Bar| would be matched by hasName("Foo") below.
308   // |type_with_same_name_as_function| matcher matches Bar and Foo return types.
309   auto type_with_same_name_as_function = qualType(anyOf(
310       hasString(name),  // hasString matches the type as spelled (Bar above).
311       hasDeclaration(namedDecl(hasName(name)))));  // hasDeclaration matches
312                                                    // resolved type (Foo above).
313   // |type_containing_same_name_as_function| matcher will match all of the
314   // return types below:
315   // - Foo foo()  // Direct application of |type_with_same_name_as_function|.
316   // - Foo* foo()  // |hasDescendant| traverses references/pointers.
317   // - RefPtr<Foo> foo()  // |hasDescendant| traverses template arguments.
318   auto type_containing_same_name_as_function =
319       qualType(anyOf(type_with_same_name_as_function,
320                      hasDescendant(type_with_same_name_as_function)));
321   // https://crbug.com/582312: Prepend "Get" if method name conflicts with
322   // return type.
323   auto conflict_matcher =
324       functionDecl(returns(type_containing_same_name_as_function));
325   if (!match(conflict_matcher, decl, context).empty())
326     name = "Get" + name;
327 
328   return true;
329 }
330 
GetNameForDecl(const clang::EnumConstantDecl & decl,clang::ASTContext & context,std::string & name)331 bool GetNameForDecl(const clang::EnumConstantDecl& decl,
332                     clang::ASTContext& context,
333                     std::string& name) {
334   StringRef original_name = decl.getName();
335 
336   // If it's already correct leave it alone.
337   if (original_name.size() >= 2 && original_name[0] == 'k' &&
338       clang::isUppercase(original_name[1]))
339     return false;
340 
341   bool is_shouty = true;
342   for (char c : original_name) {
343     if (!clang::isUppercase(c) && !clang::isDigit(c) && c != '_') {
344       is_shouty = false;
345       break;
346     }
347   }
348 
349   if (is_shouty)
350     return false;
351 
352   name = 'k';  // k prefix on enum values.
353   name += original_name;
354   name[1] = clang::toUppercase(name[1]);
355   return true;
356 }
357 
GetNameForDecl(const clang::FieldDecl & decl,clang::ASTContext & context,std::string & name)358 bool GetNameForDecl(const clang::FieldDecl& decl,
359                     clang::ASTContext& context,
360                     std::string& name) {
361   StringRef original_name = decl.getName();
362   bool member_prefix = original_name.startswith(kBlinkFieldPrefix);
363 
364   StringRef rename_part = !member_prefix
365                               ? original_name
366                               : original_name.substr(strlen(kBlinkFieldPrefix));
367   name = CamelCaseToUnderscoreCase(rename_part);
368 
369   // Assume that prefix of m_ was intentional and always replace it with a
370   // suffix _.
371   if (member_prefix && name.back() != '_')
372     name += '_';
373 
374   return true;
375 }
376 
GetNameForDecl(const clang::VarDecl & decl,clang::ASTContext & context,std::string & name)377 bool GetNameForDecl(const clang::VarDecl& decl,
378                     clang::ASTContext& context,
379                     std::string& name) {
380   StringRef original_name = decl.getName();
381 
382   // Nothing to do for unnamed parameters.
383   if (clang::isa<clang::ParmVarDecl>(decl)) {
384     if (original_name.empty())
385       return false;
386 
387     // Check if |decl| and |decl.getLocation| are in sync.  We need to skip
388     // out-of-sync ParmVarDecls to avoid renaming buggy ParmVarDecls that
389     // 1) have decl.getLocation() pointing at a parameter declaration without a
390     // name, but 2) have decl.getName() retained from a template specialization
391     // of a method.  See also: https://llvm.org/bugs/show_bug.cgi?id=29145
392     clang::SourceLocation loc =
393         context.getSourceManager().getSpellingLoc(decl.getLocation());
394     auto parents = context.getParents(decl);
395     bool is_child_location_within_parent_source_range = std::all_of(
396         parents.begin(), parents.end(),
397         [&loc](const clang::ast_type_traits::DynTypedNode& parent) {
398           clang::SourceLocation begin = parent.getSourceRange().getBegin();
399           clang::SourceLocation end = parent.getSourceRange().getEnd();
400           return (begin < loc) && (loc < end);
401         });
402     if (!is_child_location_within_parent_source_range)
403       return false;
404   }
405 
406   // static class members match against VarDecls. Blink style dictates that
407   // these should be prefixed with `s_`, so strip that off. Also check for `m_`
408   // and strip that off too, for code that accidentally uses the wrong prefix.
409   if (original_name.startswith(kBlinkStaticMemberPrefix))
410     original_name = original_name.substr(strlen(kBlinkStaticMemberPrefix));
411   else if (original_name.startswith(kBlinkFieldPrefix))
412     original_name = original_name.substr(strlen(kBlinkFieldPrefix));
413 
414   bool is_const = IsProbablyConst(decl, context);
415   if (is_const) {
416     // Don't try to rename constants that already conform to Chrome style.
417     if (original_name.size() >= 2 && original_name[0] == 'k' &&
418         clang::isUppercase(original_name[1]))
419       return false;
420 
421     name = 'k';
422     name.append(original_name.data(), original_name.size());
423     name[1] = clang::toUppercase(name[1]);
424   } else {
425     name = CamelCaseToUnderscoreCase(original_name);
426 
427     // Non-const variables with static storage duration at namespace scope are
428     // prefixed with `g_' to reduce the likelihood of a naming collision.
429     const clang::DeclContext* decl_context = decl.getDeclContext();
430     if (name.find("g_") != 0 && decl.hasGlobalStorage() &&
431         decl_context->isNamespace())
432       name.insert(0, "g_");
433   }
434 
435   // Static members end with _ just like other members, but constants should
436   // not.
437   if (!is_const && decl.isStaticDataMember()) {
438     name += '_';
439   }
440 
441   return true;
442 }
443 
GetNameForDecl(const clang::FunctionTemplateDecl & decl,clang::ASTContext & context,std::string & name)444 bool GetNameForDecl(const clang::FunctionTemplateDecl& decl,
445                     clang::ASTContext& context,
446                     std::string& name) {
447   clang::FunctionDecl* templated_function = decl.getTemplatedDecl();
448   return GetNameForDecl(*templated_function, context, name);
449 }
450 
GetNameForDecl(const clang::NamedDecl & decl,clang::ASTContext & context,std::string & name)451 bool GetNameForDecl(const clang::NamedDecl& decl,
452                     clang::ASTContext& context,
453                     std::string& name) {
454   if (auto* function = clang::dyn_cast<clang::FunctionDecl>(&decl))
455     return GetNameForDecl(*function, context, name);
456   if (auto* var = clang::dyn_cast<clang::VarDecl>(&decl))
457     return GetNameForDecl(*var, context, name);
458   if (auto* field = clang::dyn_cast<clang::FieldDecl>(&decl))
459     return GetNameForDecl(*field, context, name);
460   if (auto* function_template =
461           clang::dyn_cast<clang::FunctionTemplateDecl>(&decl))
462     return GetNameForDecl(*function_template, context, name);
463   if (auto* enumc = clang::dyn_cast<clang::EnumConstantDecl>(&decl))
464     return GetNameForDecl(*enumc, context, name);
465 
466   return false;
467 }
468 
GetNameForDecl(const clang::UsingDecl & decl,clang::ASTContext & context,std::string & name)469 bool GetNameForDecl(const clang::UsingDecl& decl,
470                     clang::ASTContext& context,
471                     std::string& name) {
472   assert(decl.shadow_size() > 0);
473 
474   // If a using declaration's targeted declaration is a set of overloaded
475   // functions, it can introduce multiple shadowed declarations. Just using the
476   // first one is OK, since overloaded functions have the same name, by
477   // definition.
478   return GetNameForDecl(*decl.shadow_begin()->getTargetDecl(), context, name);
479 }
480 
481 template <typename Type>
482 struct TargetNodeTraits;
483 
484 template <>
485 struct TargetNodeTraits<clang::NamedDecl> {
GetLoc__anonac2fe4870111::TargetNodeTraits486   static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) {
487     return decl.getLocation();
488   }
GetName__anonac2fe4870111::TargetNodeTraits489   static const char* GetName() { return "decl"; }
GetType__anonac2fe4870111::TargetNodeTraits490   static const char* GetType() { return "NamedDecl"; }
491 };
492 
493 template <>
494 struct TargetNodeTraits<clang::MemberExpr> {
GetLoc__anonac2fe4870111::TargetNodeTraits495   static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) {
496     return expr.getMemberLoc();
497   }
GetName__anonac2fe4870111::TargetNodeTraits498   static const char* GetName() { return "expr"; }
GetType__anonac2fe4870111::TargetNodeTraits499   static const char* GetType() { return "MemberExpr"; }
500 };
501 
502 template <>
503 struct TargetNodeTraits<clang::DeclRefExpr> {
GetLoc__anonac2fe4870111::TargetNodeTraits504   static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) {
505     return expr.getLocation();
506   }
GetName__anonac2fe4870111::TargetNodeTraits507   static const char* GetName() { return "expr"; }
GetType__anonac2fe4870111::TargetNodeTraits508   static const char* GetType() { return "DeclRefExpr"; }
509 };
510 
511 template <>
512 struct TargetNodeTraits<clang::CXXCtorInitializer> {
GetLoc__anonac2fe4870111::TargetNodeTraits513   static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) {
514     assert(init.isWritten());
515     return init.getSourceLocation();
516   }
GetName__anonac2fe4870111::TargetNodeTraits517   static const char* GetName() { return "initializer"; }
GetType__anonac2fe4870111::TargetNodeTraits518   static const char* GetType() { return "CXXCtorInitializer"; }
519 };
520 
521 template <>
522 struct TargetNodeTraits<clang::UnresolvedLookupExpr> {
GetLoc__anonac2fe4870111::TargetNodeTraits523   static clang::SourceLocation GetLoc(const clang::UnresolvedLookupExpr& expr) {
524     return expr.getNameLoc();
525   }
GetName__anonac2fe4870111::TargetNodeTraits526   static const char* GetName() { return "expr"; }
GetType__anonac2fe4870111::TargetNodeTraits527   static const char* GetType() { return "UnresolvedLookupExpr"; }
528 };
529 
530 template <>
531 struct TargetNodeTraits<clang::UnresolvedMemberExpr> {
GetLoc__anonac2fe4870111::TargetNodeTraits532   static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) {
533     return expr.getMemberLoc();
534   }
GetName__anonac2fe4870111::TargetNodeTraits535   static const char* GetName() { return "expr"; }
GetType__anonac2fe4870111::TargetNodeTraits536   static const char* GetType() { return "UnresolvedMemberExpr"; }
537 };
538 
539 template <typename DeclNode, typename TargetNode>
540 class RewriterBase : public MatchFinder::MatchCallback {
541  public:
RewriterBase(std::set<Replacement> * replacements)542   explicit RewriterBase(std::set<Replacement>* replacements)
543       : replacements_(replacements) {}
544 
run(const MatchFinder::MatchResult & result)545   void run(const MatchFinder::MatchResult& result) override {
546     const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
547     // If false, there's no name to be renamed.
548     if (!decl->getIdentifier())
549       return;
550     clang::SourceLocation decl_loc =
551         TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
552     if (decl_loc.isMacroID()) {
553       // Get the location of the spelling of the declaration. If token pasting
554       // was used this will be in "scratch space" and we don't know how to get
555       // from there back to/ the actual macro with the foo##bar text. So just
556       // don't replace in that case.
557       clang::SourceLocation spell =
558           result.SourceManager->getSpellingLoc(decl_loc);
559       if (strcmp(result.SourceManager->getBufferName(spell),
560                  "<scratch space>") == 0)
561         return;
562     }
563     clang::ASTContext* context = result.Context;
564     std::string new_name;
565     if (!GetNameForDecl(*decl, *context, new_name))
566       return;  // If false, the name was not suitable for renaming.
567     llvm::StringRef old_name = decl->getName();
568     if (old_name == new_name)
569       return;
570     clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc(
571         *result.Nodes.getNodeAs<TargetNode>(
572             TargetNodeTraits<TargetNode>::GetName()));
573     clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc);
574     replacements_->emplace(*result.SourceManager, range, new_name);
575     replacement_names_.emplace(old_name.str(), std::move(new_name));
576   }
577 
replacement_names() const578   const std::unordered_map<std::string, std::string>& replacement_names()
579       const {
580     return replacement_names_;
581   }
582 
583  private:
584   std::set<Replacement>* const replacements_;
585   std::unordered_map<std::string, std::string> replacement_names_;
586 };
587 
588 using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>;
589 using VarDeclRewriter = RewriterBase<clang::VarDecl, clang::NamedDecl>;
590 using MemberRewriter = RewriterBase<clang::FieldDecl, clang::MemberExpr>;
591 using DeclRefRewriter = RewriterBase<clang::VarDecl, clang::DeclRefExpr>;
592 using FieldDeclRefRewriter = RewriterBase<clang::FieldDecl, clang::DeclRefExpr>;
593 using FunctionDeclRewriter =
594     RewriterBase<clang::FunctionDecl, clang::NamedDecl>;
595 using FunctionRefRewriter =
596     RewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
597 using ConstructorInitializerRewriter =
598     RewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
599 
600 using MethodDeclRewriter = RewriterBase<clang::CXXMethodDecl, clang::NamedDecl>;
601 using MethodRefRewriter =
602     RewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>;
603 using MethodMemberRewriter =
604     RewriterBase<clang::CXXMethodDecl, clang::MemberExpr>;
605 
606 using EnumConstantDeclRewriter =
607     RewriterBase<clang::EnumConstantDecl, clang::NamedDecl>;
608 using EnumConstantDeclRefRewriter =
609     RewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>;
610 
611 using UnresolvedLookupRewriter =
612     RewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>;
613 using UnresolvedMemberRewriter =
614     RewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>;
615 
616 using UsingDeclRewriter = RewriterBase<clang::UsingDecl, clang::NamedDecl>;
617 
618 }  // namespace
619 
620 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
621 
main(int argc,const char * argv[])622 int main(int argc, const char* argv[]) {
623   // TODO(dcheng): Clang tooling should do this itself.
624   // http://llvm.org/bugs/show_bug.cgi?id=21627
625   llvm::InitializeNativeTarget();
626   llvm::InitializeNativeTargetAsmParser();
627   llvm::cl::OptionCategory category(
628       "rewrite_to_chrome_style: convert Blink style to Chrome style.");
629   CommonOptionsParser options(argc, argv, category);
630   clang::tooling::ClangTool tool(options.getCompilations(),
631                                  options.getSourcePathList());
632 
633   MatchFinder match_finder;
634   std::set<Replacement> replacements;
635 
636   // Blink namespace matchers ========
637   auto blink_namespace_decl =
638       namespaceDecl(anyOf(hasName("blink"), hasName("WTF")),
639                     hasParent(translationUnitDecl()));
640 
641   // Given top-level compilation unit:
642   //   namespace WTF {
643   //     void foo() {}
644   //   }
645   // matches |foo|.
646   auto decl_under_blink_namespace = decl(hasAncestor(blink_namespace_decl));
647 
648   // Given top-level compilation unit:
649   //   void WTF::function() {}
650   //   void WTF::Class::method() {}
651   // matches |WTF::function| and |WTF::Class::method| decls.
652   auto decl_has_qualifier_to_blink_namespace =
653       declaratorDecl(has(nestedNameSpecifier(
654           hasTopLevelPrefix(specifiesNamespace(blink_namespace_decl)))));
655 
656   auto in_blink_namespace = decl(
657       anyOf(decl_under_blink_namespace, decl_has_qualifier_to_blink_namespace,
658             hasAncestor(decl_has_qualifier_to_blink_namespace)),
659       unless(isExpansionInFileMatching(kGeneratedFileRegex)));
660 
661   // Field, variable, and enum declarations ========
662   // Given
663   //   int x;
664   //   struct S {
665   //     int y;
666   //     enum { VALUE };
667   //   };
668   // matches |x|, |y|, and |VALUE|.
669   auto field_decl_matcher = id("decl", fieldDecl(in_blink_namespace));
670   auto is_type_trait_value =
671       varDecl(hasName("value"), hasStaticStorageDuration(), isPublic(),
672               hasType(isConstQualified()), hasType(type(anyOf(
673                   booleanType(), enumType()))),
674               unless(hasAncestor(recordDecl(
675                   has(cxxMethodDecl(isUserProvided(), isInstanceMethod()))))));
676   auto var_decl_matcher =
677       id("decl", varDecl(in_blink_namespace, unless(is_type_trait_value)));
678   auto enum_member_decl_matcher =
679       id("decl", enumConstantDecl(in_blink_namespace));
680 
681   FieldDeclRewriter field_decl_rewriter(&replacements);
682   match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter);
683 
684   VarDeclRewriter var_decl_rewriter(&replacements);
685   match_finder.addMatcher(var_decl_matcher, &var_decl_rewriter);
686 
687   EnumConstantDeclRewriter enum_member_decl_rewriter(&replacements);
688   match_finder.addMatcher(enum_member_decl_matcher, &enum_member_decl_rewriter);
689 
690   // Field, variable, and enum references ========
691   // Given
692   //   bool x = true;
693   //   if (x) {
694   //     ...
695   //   }
696   // matches |x| in if (x).
697   auto member_matcher = id(
698       "expr",
699       memberExpr(
700           member(field_decl_matcher),
701           // Needed to avoid matching member references in functions (which will
702           // be an ancestor of the member reference) synthesized by the
703           // compiler, such as a synthesized copy constructor.
704           // This skips explicitly defaulted functions as well, but that's OK:
705           // there's nothing interesting to rewrite in those either.
706           unless(hasAncestor(functionDecl(isDefaulted())))));
707   auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher)));
708   auto enum_member_ref_matcher =
709       id("expr", declRefExpr(to(enum_member_decl_matcher)));
710 
711   MemberRewriter member_rewriter(&replacements);
712   match_finder.addMatcher(member_matcher, &member_rewriter);
713 
714   DeclRefRewriter decl_ref_rewriter(&replacements);
715   match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter);
716 
717   EnumConstantDeclRefRewriter enum_member_ref_rewriter(&replacements);
718   match_finder.addMatcher(enum_member_ref_matcher, &enum_member_ref_rewriter);
719 
720   // Member references in a non-member context ========
721   // Given
722   //   struct S {
723   //     typedef int U::*UnspecifiedBoolType;
724   //     operator UnspecifiedBoolType() { return s_ ? &U::s_ : 0; }
725   //     int s_;
726   //   };
727   // matches |&U::s_| but not |s_|.
728   auto member_ref_matcher = id("expr", declRefExpr(to(field_decl_matcher)));
729 
730   FieldDeclRefRewriter member_ref_rewriter(&replacements);
731   match_finder.addMatcher(member_ref_matcher, &member_ref_rewriter);
732 
733   // Non-method function declarations ========
734   // Given
735   //   void f();
736   //   struct S {
737   //     void g();
738   //   };
739   // matches |f| but not |g|.
740   auto function_decl_matcher = id(
741       "decl",
742       functionDecl(
743           unless(anyOf(
744               // Methods are covered by the method matchers.
745               cxxMethodDecl(),
746               // Out-of-line overloaded operators have special names and should
747               // never be renamed.
748               isOverloadedOperator(),
749               // Must be checked after filtering out overloaded operators to
750               // prevent asserts about the identifier not being a simple name.
751               isBlacklistedFunction())),
752           in_blink_namespace));
753   FunctionDeclRewriter function_decl_rewriter(&replacements);
754   match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter);
755 
756   // Non-method function references ========
757   // Given
758   //   f();
759   //   void (*p)() = &f;
760   // matches |f()| and |&f|.
761   auto function_ref_matcher = id(
762       "expr", declRefExpr(to(function_decl_matcher),
763                           // Ignore template substitutions.
764                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
765   FunctionRefRewriter function_ref_rewriter(&replacements);
766   match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter);
767 
768   // Method declarations ========
769   // Given
770   //   struct S {
771   //     void g();
772   //   };
773   // matches |g|.
774   // For a method to be considered for rewrite, it must not override something
775   // that we're not rewriting. Any methods that we would not normally consider
776   // but that override something we are rewriting should also be rewritten. So
777   // we use includeAllOverriddenMethods() to check these rules not just for the
778   // method being matched but for the methods it overrides also.
779   auto is_blink_method = includeAllOverriddenMethods(
780       allOf(in_blink_namespace, unless(isBlacklistedMethod())));
781   auto method_decl_matcher = id(
782       "decl",
783       cxxMethodDecl(
784           unless(anyOf(
785               // Overloaded operators have special names and should never be
786               // renamed.
787               isOverloadedOperator(),
788               // Similarly, constructors, destructors, and conversion
789               // functions should not be considered for renaming.
790               cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())),
791           // Check this last after excluding things, to avoid
792           // asserts about overriding non-blink and blink for the
793           // same method.
794           is_blink_method));
795   MethodDeclRewriter method_decl_rewriter(&replacements);
796   match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter);
797 
798   // Method references in a non-member context ========
799   // Given
800   //   S s;
801   //   s.g();
802   //   void (S::*p)() = &S::g;
803   // matches |&S::g| but not |s.g()|.
804   auto method_ref_matcher = id(
805       "expr", declRefExpr(to(method_decl_matcher),
806                           // Ignore template substitutions.
807                           unless(hasAncestor(substNonTypeTemplateParmExpr()))));
808 
809   MethodRefRewriter method_ref_rewriter(&replacements);
810   match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter);
811 
812   // Method references in a member context ========
813   // Given
814   //   S s;
815   //   s.g();
816   //   void (S::*p)() = &S::g;
817   // matches |s.g()| but not |&S::g|.
818   auto method_member_matcher =
819       id("expr", memberExpr(member(method_decl_matcher)));
820 
821   MethodMemberRewriter method_member_rewriter(&replacements);
822   match_finder.addMatcher(method_member_matcher, &method_member_rewriter);
823 
824   // Initializers ========
825   // Given
826   //   struct S {
827   //     int x;
828   //     S() : x(2) {}
829   //   };
830   // matches each initializer in the constructor for S.
831   auto constructor_initializer_matcher =
832       cxxConstructorDecl(forEachConstructorInitializer(id(
833           "initializer",
834           cxxCtorInitializer(forAnyField(field_decl_matcher), isWritten()))));
835 
836   ConstructorInitializerRewriter constructor_initializer_rewriter(
837       &replacements);
838   match_finder.addMatcher(constructor_initializer_matcher,
839                           &constructor_initializer_rewriter);
840 
841   // Unresolved lookup expressions ========
842   // Given
843   //   template<typename T> void F(T) { }
844   //   template<void G(T)> H(T) { }
845   //   H<F<int>>(...);
846   // matches |F| in |H<F<int>>|.
847   //
848   // UnresolvedLookupExprs are similar to DeclRefExprs that reference a
849   // FunctionDecl, but are used when a candidate FunctionDecl can't be selected.
850   // This commonly happens inside uninstantiated template definitions for one of
851   // two reasons:
852   //
853   // 1. If the candidate declaration is a dependent FunctionTemplateDecl, the
854   //    actual overload can't be selected until template instantiation time.
855   // 2. Alternatively, there might be multiple declarations in the candidate set
856   //    if the candidate function has overloads. If any of the function
857   //    arguments has a dependent type, then the actual overload can't be
858   //    selected until instantiation time either.
859   //
860   // Another instance where UnresolvedLookupExprs can appear is in a template
861   // argument list, like the provided example.
862   auto function_template_decl_matcher =
863       id("decl", functionTemplateDecl(templatedDecl(function_decl_matcher)));
864   auto method_template_decl_matcher =
865       id("decl", functionTemplateDecl(templatedDecl(method_decl_matcher)));
866   auto unresolved_lookup_matcher = expr(id(
867       "expr",
868       unresolvedLookupExpr(
869           // In order to automatically rename an unresolved lookup, the lookup
870           // candidates must either all be Blink functions/function templates or
871           // all be Blink methods/method templates. Otherwise, we might end up
872           // in a situation where the naming could change depending on the
873           // selected candidate.
874           anyOf(allOverloadsMatch(anyOf(function_decl_matcher,
875                                         function_template_decl_matcher)),
876                 // Note: this matches references to methods in a non-member
877                 // context, e.g. Template<&Class::Method>. This and the
878                 // UnresolvedMemberExpr matcher below are analogous to how the
879                 // rewriter has both a MemberRefRewriter matcher to rewrite
880                 // &T::method and a MethodMemberRewriter matcher to rewriter
881                 // t.method().
882                 allOverloadsMatch(anyOf(method_decl_matcher,
883                                         method_template_decl_matcher))))));
884   UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements);
885   match_finder.addMatcher(unresolved_lookup_matcher,
886                           &unresolved_lookup_rewriter);
887 
888   // Unresolved member expressions ========
889   // Similar to unresolved lookup expressions, but for methods in a member
890   // context, e.g. var_with_templated_type.Method().
891   auto unresolved_member_matcher = expr(id(
892       "expr",
893       unresolvedMemberExpr(
894           // Similar to UnresolvedLookupExprs, all the candidate methods must be
895           // Blink methods/method templates.
896           allOverloadsMatch(
897               anyOf(method_decl_matcher, method_template_decl_matcher)))));
898   UnresolvedMemberRewriter unresolved_member_rewriter(&replacements);
899   match_finder.addMatcher(unresolved_member_matcher,
900                           &unresolved_member_rewriter);
901 
902   // Using declarations ========
903   // Given
904   //   using blink::X;
905   // matches |using blink::X|.
906   auto using_decl_matcher = id(
907       "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf(
908                   var_decl_matcher, field_decl_matcher, function_decl_matcher,
909                   method_decl_matcher, function_template_decl_matcher,
910                   method_template_decl_matcher, enum_member_decl_matcher)))));
911   UsingDeclRewriter using_decl_rewriter(&replacements);
912   match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter);
913 
914   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
915       clang::tooling::newFrontendActionFactory(&match_finder);
916   int result = tool.run(factory.get());
917   if (result != 0)
918     return result;
919 
920 #if defined(_WIN32)
921   HANDLE lockfd = CreateFile("rewrite-sym.lock", GENERIC_READ, FILE_SHARE_READ,
922                              NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
923   OVERLAPPED overlapped = {};
924   LockFileEx(lockfd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &overlapped);
925 #else
926   int lockfd = open("rewrite-sym.lock", O_RDWR | O_CREAT, 0666);
927   while (flock(lockfd, LOCK_EX)) {  // :D
928   }
929 #endif
930 
931   std::ofstream replacement_db_file("rewrite-sym.txt",
932                                     std::ios_base::out | std::ios_base::app);
933   for (const auto& p : field_decl_rewriter.replacement_names())
934     replacement_db_file << "var:" << p.first << ":" << p.second << "\n";
935   for (const auto& p : var_decl_rewriter.replacement_names())
936     replacement_db_file << "var:" << p.first << ":" << p.second << "\n";
937   for (const auto& p : enum_member_decl_rewriter.replacement_names())
938     replacement_db_file << "enu:" << p.first << ":" << p.second << "\n";
939   for (const auto& p : function_decl_rewriter.replacement_names())
940     replacement_db_file << "fun:" << p.first << ":" << p.second << "\n";
941   for (const auto& p : method_decl_rewriter.replacement_names())
942     replacement_db_file << "fun:" << p.first << ":" << p.second << "\n";
943   replacement_db_file.close();
944 
945 #if defined(_WIN32)
946   UnlockFileEx(lockfd, 0, 1, 0, &overlapped);
947   CloseHandle(lockfd);
948 #else
949   flock(lockfd, LOCK_UN);
950   close(lockfd);
951 #endif
952 
953   // Serialization format is documented in tools/clang/scripts/run_tool.py
954   llvm::outs() << "==== BEGIN EDITS ====\n";
955   for (const auto& r : replacements) {
956     std::string replacement_text = r.getReplacementText().str();
957     std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
958     llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
959                  << ":::" << r.getLength() << ":::" << replacement_text << "\n";
960   }
961   llvm::outs() << "==== END EDITS ====\n";
962 
963   return 0;
964 }
965