Chromium Code Reviews| 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 return true; | 168 return true; |
| 169 } | 169 } |
| 170 return false; | 170 return false; |
| 171 } | 171 } |
| 172 | 172 |
| 173 bool 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. | 174 // swap() functions should match the signature of std::swap for ADL tricks. |
| 175 return decl.getName() == "swap"; | 175 return decl.getName() == "swap"; |
| 176 } | 176 } |
| 177 | 177 |
| 178 bool IsBlacklistedMethod(const clang::CXXMethodDecl& decl) { | 178 bool IsBlacklistedMethod(const std::string& name, |
|
dcheng
2016/09/10 04:00:55
Pass as llvm::StringRef here, so we don't need to
Łukasz Anforowicz
2016/09/12 19:52:56
Done.
This is how I started actually, but then go
| |
| 179 if (decl.isStatic()) | 179 const clang::CXXMethodDecl* decl) { |
| 180 if (decl && decl->isStatic()) | |
|
dcheng
2016/09/10 04:00:55
It feels like we should just have two versions of
Łukasz Anforowicz
2016/09/12 19:52:56
In the latest patchset I have 1) reverted changes
| |
| 180 return false; | 181 return false; |
| 181 | 182 |
| 182 clang::StringRef name = decl.getName(); | 183 if (decl) |
| 184 assert(decl->getName().str() == name); | |
| 183 | 185 |
| 184 // These methods should never be renamed. | 186 // These methods should never be renamed. |
| 185 static const char* kBlacklistMethods[] = {"trace", "traceImpl", "lock", | 187 static const char* kBlacklistMethods[] = {"trace", "traceImpl", "lock", |
| 186 "unlock", "try_lock"}; | 188 "unlock", "try_lock"}; |
| 187 for (const auto& b : kBlacklistMethods) { | 189 for (const auto& b : kBlacklistMethods) { |
| 188 if (name == b) | 190 if (name == b) |
| 189 return true; | 191 return true; |
| 190 } | 192 } |
| 191 | 193 |
| 192 // Iterator methods shouldn't be renamed to work with stl and range-for | 194 // Iterator methods shouldn't be renamed to work with stl and range-for |
| 193 // loops. | 195 // loops. |
| 194 std::string ret_type = decl.getReturnType().getAsString(); | 196 bool is_iterator = false; |
| 195 if (ret_type.find("iterator") != std::string::npos || | 197 if (decl) { |
| 196 ret_type.find("Iterator") != std::string::npos) { | 198 std::string ret_type = decl->getReturnType().getAsString(); |
| 199 is_iterator = ret_type.find("iterator") != std::string::npos || | |
| 200 ret_type.find("Iterator") != std::string::npos; | |
|
dcheng
2016/09/10 04:00:55
For this, we can just have a simple shared method
Łukasz Anforowicz
2016/09/12 19:52:56
I think this comment is not applicable to the most
| |
| 201 } else { | |
| 202 is_iterator = true; | |
| 203 } | |
| 204 if (is_iterator) { | |
| 197 static const char* kIteratorBlacklist[] = {"begin", "end", "rbegin", | 205 static const char* kIteratorBlacklist[] = {"begin", "end", "rbegin", |
| 198 "rend"}; | 206 "rend"}; |
| 199 for (const auto& b : kIteratorBlacklist) { | 207 for (const auto& b : kIteratorBlacklist) { |
| 200 if (name == b) | 208 if (name == b) |
| 201 return true; | 209 return true; |
| 202 } | 210 } |
| 203 } | 211 } |
| 204 | 212 |
| 205 // Subclasses of InspectorAgent will subclass "disable()" from both blink and | 213 // Subclasses of InspectorAgent will subclass "disable()" from both blink and |
| 206 // from gen/, which is problematic, but DevTools folks don't want to rename | 214 // 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. | 215 // it or split this up. So don't rename it at all. |
| 208 if (name.equals("disable") && | 216 if (name == "disable" && |
| 209 IsMethodOverrideOf(decl, "blink::InspectorAgent")) | 217 (!decl || IsMethodOverrideOf(*decl, "blink::InspectorAgent"))) |
| 210 return true; | 218 return true; |
| 211 | 219 |
| 212 return false; | 220 return false; |
| 213 } | 221 } |
| 214 | 222 |
| 215 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) { | 223 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) { |
| 216 return IsBlacklistedFunction(Node); | 224 return IsBlacklistedFunction(Node); |
| 217 } | 225 } |
| 218 | 226 |
| 219 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { | 227 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { |
| 220 return IsBlacklistedMethod(Node); | 228 return IsBlacklistedMethod(Node.getName().str(), &Node); |
| 221 } | 229 } |
| 222 | 230 |
| 223 // Helper to convert from a camelCaseName to camel_case_name. It uses some | 231 // 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. | 232 // heuristics to try to handle acronyms in camel case names correctly. |
| 225 std::string CamelCaseToUnderscoreCase(StringRef input) { | 233 std::string CamelCaseToUnderscoreCase(StringRef input) { |
| 226 std::string output; | 234 std::string output; |
| 227 bool needs_underscore = false; | 235 bool needs_underscore = false; |
| 228 bool was_lowercase = false; | 236 bool was_lowercase = false; |
| 229 bool was_uppercase = false; | 237 bool was_uppercase = false; |
| 230 bool first_char = true; | 238 bool first_char = true; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 | 465 |
| 458 template <typename Type> | 466 template <typename Type> |
| 459 struct TargetNodeTraits; | 467 struct TargetNodeTraits; |
| 460 | 468 |
| 461 template <> | 469 template <> |
| 462 struct TargetNodeTraits<clang::NamedDecl> { | 470 struct TargetNodeTraits<clang::NamedDecl> { |
| 463 static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) { | 471 static clang::SourceLocation GetLoc(const clang::NamedDecl& decl) { |
| 464 return decl.getLocation(); | 472 return decl.getLocation(); |
| 465 } | 473 } |
| 466 static const char* GetName() { return "decl"; } | 474 static const char* GetName() { return "decl"; } |
| 467 static const char* GetType() { return "NamedDecl"; } | |
|
dcheng
2016/09/10 04:00:55
While unused, these were helpful for debugging in
Łukasz Anforowicz
2016/09/12 19:52:56
Done.
| |
| 468 }; | 475 }; |
| 469 | 476 |
| 470 template <> | 477 template <> |
| 471 struct TargetNodeTraits<clang::MemberExpr> { | 478 struct TargetNodeTraits<clang::MemberExpr> { |
| 472 static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) { | 479 static clang::SourceLocation GetLoc(const clang::MemberExpr& expr) { |
| 473 return expr.getMemberLoc(); | 480 return expr.getMemberLoc(); |
| 474 } | 481 } |
| 475 static const char* GetName() { return "expr"; } | 482 static const char* GetName() { return "expr"; } |
| 476 static const char* GetType() { return "MemberExpr"; } | |
| 477 }; | 483 }; |
| 478 | 484 |
| 479 template <> | 485 template <> |
| 480 struct TargetNodeTraits<clang::DeclRefExpr> { | 486 struct TargetNodeTraits<clang::DeclRefExpr> { |
| 481 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { | 487 static clang::SourceLocation GetLoc(const clang::DeclRefExpr& expr) { |
| 482 return expr.getLocation(); | 488 return expr.getLocation(); |
| 483 } | 489 } |
| 484 static const char* GetName() { return "expr"; } | 490 static const char* GetName() { return "expr"; } |
| 485 static const char* GetType() { return "DeclRefExpr"; } | |
| 486 }; | 491 }; |
| 487 | 492 |
| 488 template <> | 493 template <> |
| 489 struct TargetNodeTraits<clang::CXXCtorInitializer> { | 494 struct TargetNodeTraits<clang::CXXCtorInitializer> { |
| 490 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { | 495 static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { |
| 491 assert(init.isWritten()); | 496 assert(init.isWritten()); |
| 492 return init.getSourceLocation(); | 497 return init.getSourceLocation(); |
| 493 } | 498 } |
| 494 static const char* GetName() { return "initializer"; } | 499 static const char* GetName() { return "initializer"; } |
| 495 static const char* GetType() { return "CXXCtorInitializer"; } | |
| 496 }; | 500 }; |
| 497 | 501 |
| 498 template <> | 502 template <> |
| 499 struct TargetNodeTraits<clang::UnresolvedLookupExpr> { | 503 struct TargetNodeTraits<clang::UnresolvedLookupExpr> { |
| 500 static clang::SourceLocation GetLoc(const clang::UnresolvedLookupExpr& expr) { | 504 static clang::SourceLocation GetLoc(const clang::UnresolvedLookupExpr& expr) { |
| 501 return expr.getNameLoc(); | 505 return expr.getNameLoc(); |
| 502 } | 506 } |
| 503 static const char* GetName() { return "expr"; } | 507 static const char* GetName() { return "expr"; } |
| 504 static const char* GetType() { return "UnresolvedLookupExpr"; } | |
| 505 }; | 508 }; |
| 506 | 509 |
| 507 template <> | 510 template <> |
| 508 struct TargetNodeTraits<clang::UnresolvedMemberExpr> { | 511 struct TargetNodeTraits<clang::UnresolvedMemberExpr> { |
| 509 static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) { | 512 static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) { |
| 510 return expr.getMemberLoc(); | 513 return expr.getMemberLoc(); |
| 511 } | 514 } |
| 512 static const char* GetName() { return "expr"; } | 515 static const char* GetName() { return "expr"; } |
| 513 static const char* GetType() { return "UnresolvedMemberExpr"; } | |
| 514 }; | 516 }; |
| 515 | 517 |
| 516 template <typename DeclNode, typename TargetNode> | 518 template <> |
| 519 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> { | |
| 520 static clang::SourceLocation GetLoc( | |
| 521 const clang::UnresolvedUsingValueDecl& decl) { | |
| 522 return decl.getNameInfo().getLoc(); | |
| 523 } | |
| 524 static const char* GetName() { return "decl"; } | |
| 525 }; | |
| 526 | |
| 527 template <typename TargetNode> | |
| 517 class RewriterBase : public MatchFinder::MatchCallback { | 528 class RewriterBase : public MatchFinder::MatchCallback { |
| 518 public: | 529 public: |
| 519 explicit RewriterBase(std::set<Replacement>* replacements) | 530 explicit RewriterBase(std::set<Replacement>* replacements) |
| 520 : replacements_(replacements) {} | 531 : replacements_(replacements) {} |
| 521 | 532 |
| 533 const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) { | |
| 534 const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>( | |
| 535 TargetNodeTraits<TargetNode>::GetName()); | |
| 536 assert(target_node); | |
| 537 return *target_node; | |
| 538 } | |
| 539 | |
| 540 void AddReplacement(const MatchFinder::MatchResult& result, | |
| 541 llvm::StringRef old_name, | |
| 542 std::string new_name) { | |
| 543 if (old_name == new_name) | |
| 544 return; | |
| 545 | |
| 546 clang::SourceLocation loc = | |
| 547 TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | |
| 548 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); | |
| 549 replacements_->emplace(*result.SourceManager, range, new_name); | |
| 550 replacement_names_.emplace(old_name.str(), std::move(new_name)); | |
| 551 } | |
| 552 | |
| 553 const std::unordered_map<std::string, std::string>& replacement_names() | |
| 554 const { | |
| 555 return replacement_names_; | |
| 556 } | |
| 557 | |
| 558 private: | |
| 559 std::set<Replacement>* const replacements_; | |
| 560 std::unordered_map<std::string, std::string> replacement_names_; | |
| 561 }; | |
| 562 | |
| 563 template <typename DeclNode, typename TargetNode> | |
| 564 class DeclRewriterBase : public RewriterBase<TargetNode> { | |
| 565 public: | |
| 566 using Base = RewriterBase<TargetNode>; | |
| 567 | |
| 568 explicit DeclRewriterBase(std::set<Replacement>* replacements) | |
| 569 : Base(replacements) {} | |
| 570 | |
| 522 void run(const MatchFinder::MatchResult& result) override { | 571 void run(const MatchFinder::MatchResult& result) override { |
| 523 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); | 572 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); |
| 573 assert(decl); | |
| 524 // If false, there's no name to be renamed. | 574 // If false, there's no name to be renamed. |
| 525 if (!decl->getIdentifier()) | 575 if (!decl->getIdentifier()) |
| 526 return; | 576 return; |
| 527 clang::SourceLocation decl_loc = | 577 clang::SourceLocation decl_loc = |
| 528 TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl); | 578 TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl); |
| 529 if (decl_loc.isMacroID()) { | 579 if (decl_loc.isMacroID()) { |
| 530 // Get the location of the spelling of the declaration. If token pasting | 580 // Get the location of the spelling of the declaration. If token pasting |
| 531 // was used this will be in "scratch space" and we don't know how to get | 581 // was used this will be in "scratch space" and we don't know how to get |
| 532 // from there back to/ the actual macro with the foo##bar text. So just | 582 // from there back to/ the actual macro with the foo##bar text. So just |
| 533 // don't replace in that case. | 583 // don't replace in that case. |
| 534 clang::SourceLocation spell = | 584 clang::SourceLocation spell = |
| 535 result.SourceManager->getSpellingLoc(decl_loc); | 585 result.SourceManager->getSpellingLoc(decl_loc); |
| 536 if (strcmp(result.SourceManager->getBufferName(spell), | 586 if (strcmp(result.SourceManager->getBufferName(spell), |
| 537 "<scratch space>") == 0) | 587 "<scratch space>") == 0) |
| 538 return; | 588 return; |
| 539 } | 589 } |
| 540 clang::ASTContext* context = result.Context; | 590 clang::ASTContext* context = result.Context; |
| 541 std::string new_name; | 591 std::string new_name; |
| 542 if (!GetNameForDecl(*decl, *context, new_name)) | 592 if (!GetNameForDecl(*decl, *context, new_name)) |
| 543 return; // If false, the name was not suitable for renaming. | 593 return; // If false, the name was not suitable for renaming. |
| 544 llvm::StringRef old_name = decl->getName(); | 594 llvm::StringRef old_name = decl->getName(); |
| 545 if (old_name == new_name) | 595 Base::AddReplacement(result, old_name, std::move(new_name)); |
| 546 return; | |
| 547 clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc( | |
| 548 *result.Nodes.getNodeAs<TargetNode>( | |
| 549 TargetNodeTraits<TargetNode>::GetName())); | |
| 550 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); | |
| 551 replacements_->emplace(*result.SourceManager, range, new_name); | |
| 552 replacement_names_.emplace(old_name.str(), std::move(new_name)); | |
| 553 } | 596 } |
| 597 }; | |
|
dcheng
2016/09/10 04:00:55
Nit: let's move the DeclRewriterBase using decls u
Łukasz Anforowicz
2016/09/12 19:52:56
Done.
| |
| 554 | 598 |
| 555 const std::unordered_map<std::string, std::string>& replacement_names() | 599 clang::DeclarationName GetUnresolvedName( |
| 556 const { | 600 const clang::UnresolvedMemberExpr& expr) { |
| 557 return replacement_names_; | 601 return expr.getMemberName(); |
| 602 } | |
| 603 | |
| 604 clang::DeclarationName GetUnresolvedName( | |
| 605 const clang::UnresolvedUsingValueDecl& decl) { | |
| 606 return decl.getDeclName(); | |
| 607 } | |
| 608 | |
| 609 // Returns whether |expr| is a callee of a method or function call. | |
| 610 bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) { | |
|
dcheng
2016/09/10 04:00:55
Can this logic be encapsulated into a matcher?
Łukasz Anforowicz
2016/09/12 19:52:56
Done. Thanks for helping figure out that I need |
| |
| 611 auto parents = context.getParents(expr); | |
| 612 return std::all_of( | |
| 613 parents.begin(), parents.end(), | |
| 614 [&expr](const clang::ast_type_traits::DynTypedNode& parent) { | |
| 615 const clang::CallExpr* call = parent.get<clang::CallExpr>(); | |
| 616 return call && call->getCallee() == &expr; | |
| 617 }); | |
| 618 } | |
| 619 | |
| 620 bool IsCallee(const clang::UnresolvedUsingValueDecl& /* decl */, | |
| 621 clang::ASTContext& /* context */) { | |
| 622 // Heuristic - assuming that |using Base::foo| refers to a method. | |
|
dcheng
2016/09/10 04:00:55
We can guess from the name though, right?
Łukasz Anforowicz
2016/09/12 19:52:56
Yes, we can guess from the name - we do it in Gues
| |
| 623 return true; | |
| 624 } | |
| 625 | |
| 626 template <typename TargetNode> | |
| 627 class UnresolvedRewriterBase : public RewriterBase<TargetNode> { | |
| 628 public: | |
| 629 using Base = RewriterBase<TargetNode>; | |
| 630 | |
| 631 explicit UnresolvedRewriterBase(std::set<Replacement>* replacements) | |
| 632 : RewriterBase<TargetNode>(replacements) {} | |
| 633 | |
| 634 void run(const MatchFinder::MatchResult& result) override { | |
| 635 const TargetNode& expr = Base::GetTargetNode(result); | |
| 636 llvm::StringRef old_name = GetUnresolvedName(expr).getAsString(); | |
| 637 std::string new_name; | |
| 638 if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name, | |
| 639 new_name)) { | |
| 640 Base::AddReplacement(result, old_name, std::move(new_name)); | |
| 641 } | |
| 558 } | 642 } |
| 559 | 643 |
| 560 private: | 644 private: |
| 561 std::set<Replacement>* const replacements_; | 645 // This method calculates a new name for nodes that depend on template |
| 562 std::unordered_map<std::string, std::string> replacement_names_; | 646 // parameters (http://en.cppreference.com/w/cpp/language/dependent_name). The |
| 647 // renaming is based on crude heuristics, because such nodes are not bound to | |
| 648 // a specific decl until template instantiation - at the point of rename, one | |
| 649 // cannot tell whether the node will eventually resolve to a field / method / | |
| 650 // constant / etc. | |
| 651 bool GuessNameForUnresolvedDependentNode(const TargetNode& node, | |
| 652 clang::ASTContext& context, | |
| 653 const std::string& old_name, | |
|
dcheng
2016/09/10 04:00:56
Pass this as a llvm::StringRef.
Łukasz Anforowicz
2016/09/12 19:52:56
Done.
| |
| 654 std::string& new_name) { | |
| 655 // |m_fieldName| -> |field_name_|. | |
| 656 if (old_name.substr(0, strlen(kBlinkFieldPrefix)) == kBlinkFieldPrefix) { | |
|
dcheng
2016/09/10 04:00:55
Then this can just use llvm::StringRef::startswith
Łukasz Anforowicz
2016/09/12 19:52:56
Done.
| |
| 657 std::string field_name = old_name.substr(strlen(kBlinkFieldPrefix)); | |
|
Łukasz Anforowicz
2016/09/12 19:52:56
This is the reason why in the end I've used std::s
| |
| 658 if (field_name.find('_') == std::string::npos) { | |
| 659 new_name = CamelCaseToUnderscoreCase(field_name) + "_"; | |
| 660 return true; | |
| 661 } | |
| 662 } | |
| 663 | |
| 664 if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) && | |
| 665 !IsBlacklistedMethod(old_name, nullptr)) { | |
| 666 // |T::myMethod(...)| -> |T::MyMethod(...)|. | |
| 667 new_name = old_name; | |
| 668 new_name[0] = clang::toUppercase(new_name[0]); | |
| 669 return true; | |
| 670 } | |
| 671 | |
| 672 // In the future we can consider more heuristics: | |
| 673 // - "s_" and "g_" prefixes | |
| 674 // - "ALL_CAPS" | |
| 675 // - |T::myStaticField| -> |T::kMyStaticField| | |
| 676 // (but have to be careful not to rename |value| in WTF/TypeTraits.h?) | |
| 677 return false; | |
| 678 } | |
| 563 }; | 679 }; |
| 564 | 680 |
| 565 using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>; | 681 using FieldDeclRewriter = DeclRewriterBase<clang::FieldDecl, clang::NamedDecl>; |
| 566 using VarDeclRewriter = RewriterBase<clang::VarDecl, clang::NamedDecl>; | 682 using VarDeclRewriter = DeclRewriterBase<clang::VarDecl, clang::NamedDecl>; |
| 567 using MemberRewriter = RewriterBase<clang::FieldDecl, clang::MemberExpr>; | 683 using MemberRewriter = DeclRewriterBase<clang::FieldDecl, clang::MemberExpr>; |
| 568 using DeclRefRewriter = RewriterBase<clang::VarDecl, clang::DeclRefExpr>; | 684 using DeclRefRewriter = DeclRewriterBase<clang::VarDecl, clang::DeclRefExpr>; |
| 569 using FieldDeclRefRewriter = RewriterBase<clang::FieldDecl, clang::DeclRefExpr>; | 685 using FieldDeclRefRewriter = |
| 686 DeclRewriterBase<clang::FieldDecl, clang::DeclRefExpr>; | |
| 570 using FunctionDeclRewriter = | 687 using FunctionDeclRewriter = |
| 571 RewriterBase<clang::FunctionDecl, clang::NamedDecl>; | 688 DeclRewriterBase<clang::FunctionDecl, clang::NamedDecl>; |
| 572 using FunctionRefRewriter = | 689 using FunctionRefRewriter = |
| 573 RewriterBase<clang::FunctionDecl, clang::DeclRefExpr>; | 690 DeclRewriterBase<clang::FunctionDecl, clang::DeclRefExpr>; |
| 574 using ConstructorInitializerRewriter = | 691 using ConstructorInitializerRewriter = |
| 575 RewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>; | 692 DeclRewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>; |
| 576 | 693 |
| 577 using MethodDeclRewriter = RewriterBase<clang::CXXMethodDecl, clang::NamedDecl>; | 694 using MethodDeclRewriter = |
| 695 DeclRewriterBase<clang::CXXMethodDecl, clang::NamedDecl>; | |
| 578 using MethodRefRewriter = | 696 using MethodRefRewriter = |
| 579 RewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>; | 697 DeclRewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>; |
| 580 using MethodMemberRewriter = | 698 using MethodMemberRewriter = |
| 581 RewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; | 699 DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; |
| 582 | 700 |
| 583 using EnumConstantDeclRewriter = | 701 using EnumConstantDeclRewriter = |
| 584 RewriterBase<clang::EnumConstantDecl, clang::NamedDecl>; | 702 DeclRewriterBase<clang::EnumConstantDecl, clang::NamedDecl>; |
| 585 using EnumConstantDeclRefRewriter = | 703 using EnumConstantDeclRefRewriter = |
| 586 RewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; | 704 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; |
| 587 | 705 |
| 588 using UnresolvedLookupRewriter = | 706 using UnresolvedLookupRewriter = |
| 589 RewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; | 707 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; |
| 590 using UnresolvedMemberRewriter = | 708 using UnresolvedMemberRewriter = |
| 591 RewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | 709 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; |
| 592 | 710 |
| 593 using UsingDeclRewriter = RewriterBase<clang::UsingDecl, clang::NamedDecl>; | 711 using UnresolvedDependentMemberRewriter = |
| 712 UnresolvedRewriterBase<clang::UnresolvedMemberExpr>; | |
| 713 | |
| 714 using UnresolvedUsingValueDeclRewriter = | |
| 715 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; | |
| 716 | |
| 717 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; | |
| 594 | 718 |
| 595 } // namespace | 719 } // namespace |
| 596 | 720 |
| 597 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); | 721 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); |
| 598 | 722 |
| 599 int main(int argc, const char* argv[]) { | 723 int main(int argc, const char* argv[]) { |
| 600 // TODO(dcheng): Clang tooling should do this itself. | 724 // TODO(dcheng): Clang tooling should do this itself. |
| 601 // http://llvm.org/bugs/show_bug.cgi?id=21627 | 725 // http://llvm.org/bugs/show_bug.cgi?id=21627 |
| 602 llvm::InitializeNativeTarget(); | 726 llvm::InitializeNativeTarget(); |
| 603 llvm::InitializeNativeTargetAsmParser(); | 727 llvm::InitializeNativeTargetAsmParser(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 855 // UnresolvedMemberExpr matcher below are analogous to how the | 979 // UnresolvedMemberExpr matcher below are analogous to how the |
| 856 // rewriter has both a MemberRefRewriter matcher to rewrite | 980 // rewriter has both a MemberRefRewriter matcher to rewrite |
| 857 // &T::method and a MethodMemberRewriter matcher to rewriter | 981 // &T::method and a MethodMemberRewriter matcher to rewriter |
| 858 // t.method(). | 982 // t.method(). |
| 859 allOverloadsMatch(anyOf(method_decl_matcher, | 983 allOverloadsMatch(anyOf(method_decl_matcher, |
| 860 method_template_decl_matcher)))))); | 984 method_template_decl_matcher)))))); |
| 861 UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements); | 985 UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements); |
| 862 match_finder.addMatcher(unresolved_lookup_matcher, | 986 match_finder.addMatcher(unresolved_lookup_matcher, |
| 863 &unresolved_lookup_rewriter); | 987 &unresolved_lookup_rewriter); |
| 864 | 988 |
| 865 // Unresolved member expressions ======== | 989 // Unresolved member expressions (for non-dependent fields / methods) ======== |
| 866 // Similar to unresolved lookup expressions, but for methods in a member | 990 // Similar to unresolved lookup expressions, but for methods in a member |
| 867 // context, e.g. var_with_templated_type.Method(). | 991 // context, e.g. var_with_templated_type.Method(). |
| 868 auto unresolved_member_matcher = expr(id( | 992 auto unresolved_member_matcher = expr(id( |
| 869 "expr", | 993 "expr", |
| 870 unresolvedMemberExpr( | 994 unresolvedMemberExpr( |
| 871 // Similar to UnresolvedLookupExprs, all the candidate methods must be | 995 // Similar to UnresolvedLookupExprs, all the candidate methods must be |
| 872 // Blink methods/method templates. | 996 // Blink methods/method templates. |
| 873 allOverloadsMatch( | 997 allOverloadsMatch( |
| 874 anyOf(method_decl_matcher, method_template_decl_matcher))))); | 998 anyOf(method_decl_matcher, method_template_decl_matcher))))); |
| 875 UnresolvedMemberRewriter unresolved_member_rewriter(&replacements); | 999 UnresolvedMemberRewriter unresolved_member_rewriter(&replacements); |
| 876 match_finder.addMatcher(unresolved_member_matcher, | 1000 match_finder.addMatcher(unresolved_member_matcher, |
| 877 &unresolved_member_rewriter); | 1001 &unresolved_member_rewriter); |
| 878 | 1002 |
| 1003 // Unresolved using value decls ======== | |
| 1004 // Example: | |
| 1005 // template <typename T> | |
| 1006 // class BaseClass { | |
| 1007 // public: | |
| 1008 // unsigned long m_size; | |
| 1009 // }; | |
| 1010 // template <typename T> | |
| 1011 // class DerivedClass : protected BaseClass<T> { | |
| 1012 // private: | |
| 1013 // using Base = BaseClass<T>; | |
| 1014 // using Base::m_size; <- matched by |unresolved_using_value_decl_matcher|. | |
| 1015 // void method() { | |
| 1016 // m_size = 123; // <- |m_size| matched by | |
| 1017 // } // |unresolved_dependent_using_matcher|. | |
| 1018 // }; | |
| 1019 auto unresolved_dependent_using_matcher = | |
| 1020 expr(id("expr", unresolvedMemberExpr(allOverloadsMatch(allOf( | |
| 1021 in_blink_namespace, unresolvedUsingValueDecl()))))); | |
| 1022 UnresolvedDependentMemberRewriter unresolved_dependent_member_rewriter( | |
| 1023 &replacements); | |
| 1024 match_finder.addMatcher(unresolved_dependent_using_matcher, | |
| 1025 &unresolved_dependent_member_rewriter); | |
| 1026 auto unresolved_using_value_decl_matcher = | |
| 1027 decl(id("decl", unresolvedUsingValueDecl(in_blink_namespace))); | |
| 1028 UnresolvedUsingValueDeclRewriter unresolved_using_value_decl_rewriter( | |
| 1029 &replacements); | |
| 1030 match_finder.addMatcher(unresolved_using_value_decl_matcher, | |
| 1031 &unresolved_using_value_decl_rewriter); | |
| 1032 | |
| 879 // Using declarations ======== | 1033 // Using declarations ======== |
| 880 // Given | 1034 // Given |
| 881 // using blink::X; | 1035 // using blink::X; |
| 882 // matches |using blink::X|. | 1036 // matches |using blink::X|. |
| 883 auto using_decl_matcher = id( | 1037 auto using_decl_matcher = id( |
| 884 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( | 1038 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( |
| 885 var_decl_matcher, field_decl_matcher, function_decl_matcher, | 1039 var_decl_matcher, field_decl_matcher, function_decl_matcher, |
| 886 method_decl_matcher, function_template_decl_matcher, | 1040 method_decl_matcher, function_template_decl_matcher, |
| 887 method_template_decl_matcher, enum_member_decl_matcher))))); | 1041 method_template_decl_matcher, enum_member_decl_matcher))))); |
| 888 UsingDeclRewriter using_decl_rewriter(&replacements); | 1042 UsingDeclRewriter using_decl_rewriter(&replacements); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 for (const auto& r : replacements) { | 1086 for (const auto& r : replacements) { |
| 933 std::string replacement_text = r.getReplacementText().str(); | 1087 std::string replacement_text = r.getReplacementText().str(); |
| 934 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 1088 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
| 935 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 1089 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
| 936 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 1090 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
| 937 } | 1091 } |
| 938 llvm::outs() << "==== END EDITS ====\n"; | 1092 llvm::outs() << "==== END EDITS ====\n"; |
| 939 | 1093 |
| 940 return 0; | 1094 return 0; |
| 941 } | 1095 } |
| OLD | NEW |