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