| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Changes Blink-style names to Chrome-style names. Currently transforms: | 5 // Changes Blink-style names to Chrome-style names. Currently transforms: |
| 6 // fields: | 6 // fields: |
| 7 // int m_operationCount => int operation_count_ | 7 // int m_operationCount => int operation_count_ |
| 8 // variables (including parameters): | 8 // variables (including parameters): |
| 9 // int mySuperVariable => int my_super_variable | 9 // int mySuperVariable => int my_super_variable |
| 10 // constants: | 10 // constants: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 using namespace clang::ast_matchers; | 43 using namespace clang::ast_matchers; |
| 44 using clang::tooling::CommonOptionsParser; | 44 using clang::tooling::CommonOptionsParser; |
| 45 using clang::tooling::Replacement; | 45 using clang::tooling::Replacement; |
| 46 using clang::tooling::Replacements; | 46 using clang::tooling::Replacements; |
| 47 using llvm::StringRef; | 47 using llvm::StringRef; |
| 48 | 48 |
| 49 namespace { | 49 namespace { |
| 50 | 50 |
| 51 // Hack: prevent the custom isDefaulted() from conflicting with the one defined | |
| 52 // in newer revisions of Clang. | |
| 53 namespace internal_hack { | |
| 54 | |
| 55 // This is available in newer clang revisions... but alas, Chrome has not rolled | |
| 56 // that far yet. | |
| 57 AST_MATCHER(clang::FunctionDecl, isDefaulted) { | |
| 58 return Node.isDefaulted(); | |
| 59 } | |
| 60 | |
| 61 } // namespace internal_hack | |
| 62 | |
| 63 const char kBlinkFieldPrefix[] = "m_"; | 51 const char kBlinkFieldPrefix[] = "m_"; |
| 64 const char kBlinkStaticMemberPrefix[] = "s_"; | 52 const char kBlinkStaticMemberPrefix[] = "s_"; |
| 65 const char kGeneratedFileRegex[] = "^gen/|/gen/"; | 53 const char kGeneratedFileRegex[] = "^gen/|/gen/"; |
| 66 | 54 |
| 67 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { | 55 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { |
| 68 return Node.isOverloadedOperator(); | 56 return Node.isOverloadedOperator(); |
| 69 } | 57 } |
| 70 | 58 |
| 71 AST_MATCHER_P(clang::FunctionTemplateDecl, | 59 AST_MATCHER_P(clang::FunctionTemplateDecl, |
| 72 templatedDecl, | 60 templatedDecl, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { | 184 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { |
| 197 return IsBlacklistedMethod(Node); | 185 return IsBlacklistedMethod(Node); |
| 198 } | 186 } |
| 199 | 187 |
| 200 // Helper to convert from a camelCaseName to camel_case_name. It uses some | 188 // Helper to convert from a camelCaseName to camel_case_name. It uses some |
| 201 // heuristics to try to handle acronyms in camel case names correctly. | 189 // heuristics to try to handle acronyms in camel case names correctly. |
| 202 std::string CamelCaseToUnderscoreCase(StringRef input) { | 190 std::string CamelCaseToUnderscoreCase(StringRef input) { |
| 203 std::string output; | 191 std::string output; |
| 204 bool needs_underscore = false; | 192 bool needs_underscore = false; |
| 205 bool was_lowercase = false; | 193 bool was_lowercase = false; |
| 206 bool was_number = false; | |
| 207 bool was_uppercase = false; | 194 bool was_uppercase = false; |
| 208 bool first_char = true; | 195 bool first_char = true; |
| 209 // Iterate in reverse to minimize the amount of backtracking. | 196 // Iterate in reverse to minimize the amount of backtracking. |
| 210 for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin(); | 197 for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin(); |
| 211 --i) { | 198 --i) { |
| 212 char c = *i; | 199 char c = *i; |
| 213 bool is_lowercase = clang::isLowercase(c); | 200 bool is_lowercase = clang::isLowercase(c); |
| 214 bool is_number = clang::isDigit(c); | |
| 215 bool is_uppercase = clang::isUppercase(c); | 201 bool is_uppercase = clang::isUppercase(c); |
| 216 c = clang::toLowercase(c); | 202 c = clang::toLowercase(c); |
| 217 // Transitioning from upper to lower case requires an underscore. This is | 203 // Transitioning from upper to lower case requires an underscore. This is |
| 218 // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_' | 204 // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_' |
| 219 // in 'dH'. This is a complement to the non-acronym case further down. | 205 // in 'dH'. This is a complement to the non-acronym case further down. |
| 220 if (was_uppercase && is_lowercase) | 206 if (was_uppercase && is_lowercase) |
| 221 needs_underscore = true; | 207 needs_underscore = true; |
| 222 if (needs_underscore) { | 208 if (needs_underscore) { |
| 223 output += '_'; | 209 output += '_'; |
| 224 needs_underscore = false; | 210 needs_underscore = false; |
| 225 } | 211 } |
| 226 output += c; | 212 output += c; |
| 227 // Handles the non-acronym case: transitioning from lower to upper case | 213 // Handles the non-acronym case: transitioning from lower to upper case |
| 228 // requires an underscore when emitting the next character, e.g. didLoad | 214 // requires an underscore when emitting the next character, e.g. didLoad |
| 229 // needs a '_' in 'dL'. | 215 // needs a '_' in 'dL'. |
| 230 if (!first_char && was_lowercase && is_uppercase) | 216 if (!first_char && was_lowercase && is_uppercase) |
| 231 needs_underscore = true; | 217 needs_underscore = true; |
| 232 was_lowercase = is_lowercase; | 218 was_lowercase = is_lowercase; |
| 233 was_number = is_number; | |
| 234 was_uppercase = is_uppercase; | 219 was_uppercase = is_uppercase; |
| 235 first_char = false; | 220 first_char = false; |
| 236 } | 221 } |
| 237 std::reverse(output.begin(), output.end()); | 222 std::reverse(output.begin(), output.end()); |
| 238 return output; | 223 return output; |
| 239 } | 224 } |
| 240 | 225 |
| 241 bool IsProbablyConst(const clang::VarDecl& decl, | 226 bool IsProbablyConst(const clang::VarDecl& decl, |
| 242 const clang::ASTContext& context) { | 227 const clang::ASTContext& context) { |
| 243 clang::QualType type = decl.getType(); | 228 clang::QualType type = decl.getType(); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 378 |
| 394 bool GetNameForDecl(const clang::FunctionTemplateDecl& decl, | 379 bool GetNameForDecl(const clang::FunctionTemplateDecl& decl, |
| 395 const clang::ASTContext& context, | 380 const clang::ASTContext& context, |
| 396 std::string& name) { | 381 std::string& name) { |
| 397 clang::FunctionDecl* templated_function = decl.getTemplatedDecl(); | 382 clang::FunctionDecl* templated_function = decl.getTemplatedDecl(); |
| 398 if (auto* method = clang::dyn_cast<clang::CXXMethodDecl>(templated_function)) | 383 if (auto* method = clang::dyn_cast<clang::CXXMethodDecl>(templated_function)) |
| 399 return GetNameForDecl(*method, context, name); | 384 return GetNameForDecl(*method, context, name); |
| 400 return GetNameForDecl(*templated_function, context, name); | 385 return GetNameForDecl(*templated_function, context, name); |
| 401 } | 386 } |
| 402 | 387 |
| 388 bool GetNameForDecl(const clang::NamedDecl& decl, |
| 389 const clang::ASTContext& context, |
| 390 std::string& name) { |
| 391 // Note: CXXMethodDecl must be checked before FunctionDecl, because |
| 392 // CXXMethodDecl is derived from FunctionDecl. |
| 393 if (auto* method = clang::dyn_cast<clang::CXXMethodDecl>(&decl)) |
| 394 return GetNameForDecl(*method, context, name); |
| 395 if (auto* function = clang::dyn_cast<clang::FunctionDecl>(&decl)) |
| 396 return GetNameForDecl(*function, context, name); |
| 397 if (auto* var = clang::dyn_cast<clang::VarDecl>(&decl)) |
| 398 return GetNameForDecl(*var, context, name); |
| 399 if (auto* field = clang::dyn_cast<clang::FieldDecl>(&decl)) |
| 400 return GetNameForDecl(*field, context, name); |
| 401 if (auto* function_template = |
| 402 clang::dyn_cast<clang::FunctionTemplateDecl>(&decl)) |
| 403 return GetNameForDecl(*function_template, context, name); |
| 404 if (auto* enumc = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) |
| 405 return GetNameForDecl(*enumc, context, name); |
| 406 |
| 407 return false; |
| 408 } |
| 409 |
| 403 bool GetNameForDecl(const clang::UsingDecl& decl, | 410 bool GetNameForDecl(const clang::UsingDecl& decl, |
| 404 const clang::ASTContext& context, | 411 const clang::ASTContext& context, |
| 405 std::string& name) { | 412 std::string& name) { |
| 406 assert(decl.shadow_size() > 0); | 413 assert(decl.shadow_size() > 0); |
| 407 | 414 |
| 408 // If a using declaration's targeted declaration is a set of overloaded | 415 // If a using declaration's targeted declaration is a set of overloaded |
| 409 // functions, it can introduce multiple shadowed declarations. Just using the | 416 // functions, it can introduce multiple shadowed declarations. Just using the |
| 410 // first one is OK, since overloaded functions have the same name, by | 417 // first one is OK, since overloaded functions have the same name, by |
| 411 // definition. | 418 // definition. |
| 412 clang::NamedDecl* shadowed_name = decl.shadow_begin()->getTargetDecl(); | 419 return GetNameForDecl(*decl.shadow_begin()->getTargetDecl(), context, name); |
| 413 // Note: CXXMethodDecl must be checked before FunctionDecl, because | |
| 414 // CXXMethodDecl is derived from FunctionDecl. | |
| 415 if (auto* method = clang::dyn_cast<clang::CXXMethodDecl>(shadowed_name)) | |
| 416 return GetNameForDecl(*method, context, name); | |
| 417 if (auto* function = clang::dyn_cast<clang::FunctionDecl>(shadowed_name)) | |
| 418 return GetNameForDecl(*function, context, name); | |
| 419 if (auto* var = clang::dyn_cast<clang::VarDecl>(shadowed_name)) | |
| 420 return GetNameForDecl(*var, context, name); | |
| 421 if (auto* field = clang::dyn_cast<clang::FieldDecl>(shadowed_name)) | |
| 422 return GetNameForDecl(*field, context, name); | |
| 423 if (auto* function_template = | |
| 424 clang::dyn_cast<clang::FunctionTemplateDecl>(shadowed_name)) | |
| 425 return GetNameForDecl(*function_template, context, name); | |
| 426 if (auto* enumc = clang::dyn_cast<clang::EnumConstantDecl>(shadowed_name)) | |
| 427 return GetNameForDecl(*enumc, context, name); | |
| 428 | |
| 429 return false; | |
| 430 } | 420 } |
| 431 | 421 |
| 432 template <typename Type> | 422 template <typename Type> |
| 433 struct TargetNodeTraits; | 423 struct TargetNodeTraits; |
| 434 | 424 |
| 435 template <> | 425 template <> |
| 436 struct TargetNodeTraits<clang::NamedDecl> { | 426 struct TargetNodeTraits<clang::NamedDecl> { |
| 437 static const char kName[]; | |
| 438 static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) { | 427 static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) { |
| 439 return decl.getLocation(); | 428 return decl.getLocation(); |
| 440 } | 429 } |
| 430 static const char* GetName() { return "decl"; } |
| 441 static const char* GetType() { return "NamedDecl"; } | 431 static const char* GetType() { return "NamedDecl"; } |
| 442 }; | 432 }; |
| 443 const char TargetNodeTraits<clang::NamedDecl>::kName[] = "decl"; | |
| 444 | 433 |
| 445 template <> | 434 template <> |
| 446 struct TargetNodeTraits<clang::MemberExpr> { | 435 struct TargetNodeTraits<clang::MemberExpr> { |
| 447 static const char kName[]; | |
| 448 static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) { | 436 static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) { |
| 449 return expr.getMemberLoc(); | 437 return expr.getMemberLoc(); |
| 450 } | 438 } |
| 439 static const char* GetName() { return "expr"; } |
| 451 static const char* GetType() { return "MemberExpr"; } | 440 static const char* GetType() { return "MemberExpr"; } |
| 452 }; | 441 }; |
| 453 const char TargetNodeTraits<clang::MemberExpr>::kName[] = "expr"; | |
| 454 | 442 |
| 455 template <> | 443 template <> |
| 456 struct TargetNodeTraits<clang::DeclRefExpr> { | 444 struct TargetNodeTraits<clang::DeclRefExpr> { |
| 457 static const char kName[]; | |
| 458 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { | 445 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { |
| 459 return expr.getLocation(); | 446 return expr.getLocation(); |
| 460 } | 447 } |
| 448 static const char* GetName() { return "expr"; } |
| 461 static const char* GetType() { return "DeclRefExpr"; } | 449 static const char* GetType() { return "DeclRefExpr"; } |
| 462 }; | 450 }; |
| 463 const char TargetNodeTraits<clang::DeclRefExpr>::kName[] = "expr"; | |
| 464 | 451 |
| 465 template <> | 452 template <> |
| 466 struct TargetNodeTraits<clang::CXXCtorInitializer> { | 453 struct TargetNodeTraits<clang::CXXCtorInitializer> { |
| 467 static const char kName[]; | |
| 468 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { | 454 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { |
| 469 assert(init.isWritten()); | 455 assert(init.isWritten()); |
| 470 return init.getSourceLocation(); | 456 return init.getSourceLocation(); |
| 471 } | 457 } |
| 458 static const char* GetName() { return "initializer"; } |
| 472 static const char* GetType() { return "CXXCtorInitializer"; } | 459 static const char* GetType() { return "CXXCtorInitializer"; } |
| 473 }; | 460 }; |
| 474 const char TargetNodeTraits<clang::CXXCtorInitializer>::kName[] = "initializer"; | |
| 475 | 461 |
| 476 template <typename DeclNode, typename TargetNode> | 462 template <typename DeclNode, typename TargetNode> |
| 477 class RewriterBase : public MatchFinder::MatchCallback { | 463 class RewriterBase : public MatchFinder::MatchCallback { |
| 478 public: | 464 public: |
| 479 explicit RewriterBase(Replacements* replacements) | 465 explicit RewriterBase(Replacements* replacements) |
| 480 : replacements_(replacements) {} | 466 : replacements_(replacements) {} |
| 481 | 467 |
| 482 void run(const MatchFinder::MatchResult& result) override { | 468 void run(const MatchFinder::MatchResult& result) override { |
| 483 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); | 469 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); |
| 484 // If false, there's no name to be renamed. | 470 // If false, there's no name to be renamed. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 499 } | 485 } |
| 500 clang::ASTContext* context = result.Context; | 486 clang::ASTContext* context = result.Context; |
| 501 std::string new_name; | 487 std::string new_name; |
| 502 if (!GetNameForDecl(*decl, *context, new_name)) | 488 if (!GetNameForDecl(*decl, *context, new_name)) |
| 503 return; // If false, the name was not suitable for renaming. | 489 return; // If false, the name was not suitable for renaming. |
| 504 llvm::StringRef old_name = decl->getName(); | 490 llvm::StringRef old_name = decl->getName(); |
| 505 if (old_name == new_name) | 491 if (old_name == new_name) |
| 506 return; | 492 return; |
| 507 clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc( | 493 clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc( |
| 508 *result.Nodes.getNodeAs<TargetNode>( | 494 *result.Nodes.getNodeAs<TargetNode>( |
| 509 TargetNodeTraits<TargetNode>::kName)); | 495 TargetNodeTraits<TargetNode>::GetName())); |
| 510 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); | 496 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); |
| 511 replacements_->emplace(*result.SourceManager, range, new_name); | 497 replacements_->emplace(*result.SourceManager, range, new_name); |
| 512 replacement_names_.emplace(old_name.str(), std::move(new_name)); | 498 replacement_names_.emplace(old_name.str(), std::move(new_name)); |
| 513 } | 499 } |
| 514 | 500 |
| 515 const std::unordered_map<std::string, std::string>& replacement_names() | 501 const std::unordered_map<std::string, std::string>& replacement_names() |
| 516 const { | 502 const { |
| 517 return replacement_names_; | 503 return replacement_names_; |
| 518 } | 504 } |
| 519 | 505 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 // matches |x| in if (x). | 587 // matches |x| in if (x). |
| 602 auto member_matcher = id( | 588 auto member_matcher = id( |
| 603 "expr", | 589 "expr", |
| 604 memberExpr( | 590 memberExpr( |
| 605 member(field_decl_matcher), | 591 member(field_decl_matcher), |
| 606 // Needed to avoid matching member references in functions (which will | 592 // Needed to avoid matching member references in functions (which will |
| 607 // be an ancestor of the member reference) synthesized by the | 593 // be an ancestor of the member reference) synthesized by the |
| 608 // compiler, such as a synthesized copy constructor. | 594 // compiler, such as a synthesized copy constructor. |
| 609 // This skips explicitly defaulted functions as well, but that's OK: | 595 // This skips explicitly defaulted functions as well, but that's OK: |
| 610 // there's nothing interesting to rewrite in those either. | 596 // there's nothing interesting to rewrite in those either. |
| 611 unless(hasAncestor(functionDecl(internal_hack::isDefaulted()))))); | 597 unless(hasAncestor(functionDecl(isDefaulted()))))); |
| 612 auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher))); | 598 auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher))); |
| 613 auto enum_member_ref_matcher = | 599 auto enum_member_ref_matcher = |
| 614 id("expr", declRefExpr(to(enum_member_decl_matcher))); | 600 id("expr", declRefExpr(to(enum_member_decl_matcher))); |
| 615 | 601 |
| 616 MemberRewriter member_rewriter(&replacements); | 602 MemberRewriter member_rewriter(&replacements); |
| 617 match_finder.addMatcher(member_matcher, &member_rewriter); | 603 match_finder.addMatcher(member_matcher, &member_rewriter); |
| 618 | 604 |
| 619 DeclRefRewriter decl_ref_rewriter(&replacements); | 605 DeclRefRewriter decl_ref_rewriter(&replacements); |
| 620 match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter); | 606 match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter); |
| 621 | 607 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 isOverloadedOperator())), | 639 isOverloadedOperator())), |
| 654 in_blink_namespace)); | 640 in_blink_namespace)); |
| 655 FunctionDeclRewriter function_decl_rewriter(&replacements); | 641 FunctionDeclRewriter function_decl_rewriter(&replacements); |
| 656 match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter); | 642 match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter); |
| 657 | 643 |
| 658 // Non-method function references ======== | 644 // Non-method function references ======== |
| 659 // Given | 645 // Given |
| 660 // f(); | 646 // f(); |
| 661 // void (*p)() = &f; | 647 // void (*p)() = &f; |
| 662 // matches |f()| and |&f|. | 648 // matches |f()| and |&f|. |
| 663 auto function_ref_matcher = | 649 auto function_ref_matcher = id( |
| 664 id("expr", declRefExpr(to(function_decl_matcher))); | 650 "expr", declRefExpr(to(function_decl_matcher), |
| 651 // Ignore template substitutions. |
| 652 unless(hasAncestor(substNonTypeTemplateParmExpr())))); |
| 665 FunctionRefRewriter function_ref_rewriter(&replacements); | 653 FunctionRefRewriter function_ref_rewriter(&replacements); |
| 666 match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter); | 654 match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter); |
| 667 | 655 |
| 668 // Method declarations ======== | 656 // Method declarations ======== |
| 669 // Given | 657 // Given |
| 670 // struct S { | 658 // struct S { |
| 671 // void g(); | 659 // void g(); |
| 672 // }; | 660 // }; |
| 673 // matches |g|. | 661 // matches |g|. |
| 674 // For a method to be considered for rewrite, it must not override something | 662 // For a method to be considered for rewrite, it must not override something |
| 675 // that we're not rewriting. Any methods that we would not normally consider | 663 // that we're not rewriting. Any methods that we would not normally consider |
| 676 // but that override something we are rewriting should also be rewritten. So | 664 // but that override something we are rewriting should also be rewritten. So |
| 677 // we use includeAllOverriddenMethods() to check these rules not just for the | 665 // we use includeAllOverriddenMethods() to check these rules not just for the |
| 678 // method being matched but for the methods it overrides also. | 666 // method being matched but for the methods it overrides also. |
| 679 auto is_blink_method = includeAllOverriddenMethods( | 667 auto is_blink_method = includeAllOverriddenMethods( |
| 680 allOf(in_blink_namespace, unless(isBlacklistedMethod()))); | 668 allOf(in_blink_namespace, unless(isBlacklistedMethod()))); |
| 681 auto method_decl_matcher = id( | 669 auto method_decl_matcher = id( |
| 682 "decl", | 670 "decl", |
| 683 cxxMethodDecl( | 671 cxxMethodDecl( |
| 684 unless(anyOf( | 672 unless(anyOf( |
| 685 // Overloaded operators have special names and should never be | 673 // Overloaded operators have special names and should never be |
| 686 // renamed. | 674 // renamed. |
| 687 isOverloadedOperator(), | 675 isOverloadedOperator(), |
| 688 // Similarly, constructors, destructors, and conversion functions | 676 // Similarly, constructors, destructors, and conversion |
| 689 // should not be considered for renaming. | 677 // functions should not be considered for renaming. |
| 690 cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())), | 678 cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())), |
| 691 // Check this last after excluding things, to avoid | 679 // Check this last after excluding things, to avoid |
| 692 // asserts about overriding non-blink and blink for the | 680 // asserts about overriding non-blink and blink for the |
| 693 // same method. | 681 // same method. |
| 694 is_blink_method)); | 682 is_blink_method)); |
| 695 MethodDeclRewriter method_decl_rewriter(&replacements); | 683 MethodDeclRewriter method_decl_rewriter(&replacements); |
| 696 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); | 684 match_finder.addMatcher(method_decl_matcher, &method_decl_rewriter); |
| 697 | 685 |
| 698 // Method references in a non-member context ======== | 686 // Method references in a non-member context ======== |
| 699 // Given | 687 // Given |
| 700 // S s; | 688 // S s; |
| 701 // s.g(); | 689 // s.g(); |
| 702 // void (S::*p)() = &S::g; | 690 // void (S::*p)() = &S::g; |
| 703 // matches |&S::g| but not |s.g()|. | 691 // matches |&S::g| but not |s.g()|. |
| 704 auto method_ref_matcher = id("expr", declRefExpr(to(method_decl_matcher))); | 692 auto method_ref_matcher = id( |
| 693 "expr", declRefExpr(to(method_decl_matcher), |
| 694 // Ignore template substitutions. |
| 695 unless(hasAncestor(substNonTypeTemplateParmExpr())))); |
| 705 | 696 |
| 706 MethodRefRewriter method_ref_rewriter(&replacements); | 697 MethodRefRewriter method_ref_rewriter(&replacements); |
| 707 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); | 698 match_finder.addMatcher(method_ref_matcher, &method_ref_rewriter); |
| 708 | 699 |
| 709 // Method references in a member context ======== | 700 // Method references in a member context ======== |
| 710 // Given | 701 // Given |
| 711 // S s; | 702 // S s; |
| 712 // s.g(); | 703 // s.g(); |
| 713 // void (S::*p)() = &S::g; | 704 // void (S::*p)() = &S::g; |
| 714 // matches |s.g()| but not |&S::g|. | 705 // matches |s.g()| but not |&S::g|. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 for (const auto& r : replacements) { | 787 for (const auto& r : replacements) { |
| 797 std::string replacement_text = r.getReplacementText().str(); | 788 std::string replacement_text = r.getReplacementText().str(); |
| 798 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 789 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
| 799 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 790 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
| 800 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 791 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
| 801 } | 792 } |
| 802 llvm::outs() << "==== END EDITS ====\n"; | 793 llvm::outs() << "==== END EDITS ====\n"; |
| 803 | 794 |
| 804 return 0; | 795 return 0; |
| 805 } | 796 } |
| OLD | NEW |