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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 using clang::tooling::CommonOptionsParser; | 44 using clang::tooling::CommonOptionsParser; |
45 using clang::tooling::Replacement; | 45 using clang::tooling::Replacement; |
46 using llvm::StringRef; | 46 using llvm::StringRef; |
47 | 47 |
48 namespace { | 48 namespace { |
49 | 49 |
50 const char kBlinkFieldPrefix[] = "m_"; | 50 const char kBlinkFieldPrefix[] = "m_"; |
51 const char kBlinkStaticMemberPrefix[] = "s_"; | 51 const char kBlinkStaticMemberPrefix[] = "s_"; |
52 const char kGeneratedFileRegex[] = "^gen/|/gen/"; | 52 const char kGeneratedFileRegex[] = "^gen/|/gen/"; |
53 | 53 |
54 template <typename MatcherType, typename NodeType> | |
55 bool IsMatching(const MatcherType& matcher, | |
56 const NodeType& node, | |
57 clang::ASTContext& context) { | |
58 return !match(matcher, node, context).empty(); | |
59 } | |
60 | |
54 const clang::ast_matchers::internal:: | 61 const clang::ast_matchers::internal:: |
55 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> | 62 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> |
56 unresolvedMemberExpr; | 63 unresolvedMemberExpr; |
57 | 64 |
58 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { | 65 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { |
59 return Node.isOverloadedOperator(); | 66 return Node.isOverloadedOperator(); |
60 } | 67 } |
61 | 68 |
62 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) { | 69 AST_MATCHER(clang::CXXMethodDecl, isInstanceMethod) { |
63 return Node.isInstance(); | 70 return Node.isInstance(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 // Subclasses of InspectorAgent will subclass "disable()" from both blink and | 212 // Subclasses of InspectorAgent will subclass "disable()" from both blink and |
206 // from gen/, which is problematic, but DevTools folks don't want to rename | 213 // 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. | 214 // it or split this up. So don't rename it at all. |
208 if (name.equals("disable") && | 215 if (name.equals("disable") && |
209 IsMethodOverrideOf(decl, "blink::InspectorAgent")) | 216 IsMethodOverrideOf(decl, "blink::InspectorAgent")) |
210 return true; | 217 return true; |
211 | 218 |
212 return false; | 219 return false; |
213 } | 220 } |
214 | 221 |
222 bool IsBlacklistedFunctionOrMethodName(llvm::StringRef name) { | |
223 static const char* kBlacklistedNames[] = { | |
224 // From IsBlacklistedFunction: | |
225 "swap", | |
226 // From IsBlacklistedMethod: | |
227 "trace", "traceImpl", "lock", "unlock", "try_lock", "begin", "end", | |
228 "rbegin", "rend", "disable", | |
229 }; | |
230 for (const auto& b : kBlacklistedNames) { | |
231 if (name == b) | |
232 return true; | |
233 } | |
234 return false; | |
235 } | |
236 | |
215 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) { | 237 AST_MATCHER(clang::FunctionDecl, isBlacklistedFunction) { |
216 return IsBlacklistedFunction(Node); | 238 return IsBlacklistedFunction(Node); |
217 } | 239 } |
218 | 240 |
219 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { | 241 AST_MATCHER(clang::CXXMethodDecl, isBlacklistedMethod) { |
220 return IsBlacklistedMethod(Node); | 242 return IsBlacklistedMethod(Node); |
221 } | 243 } |
222 | 244 |
223 // Helper to convert from a camelCaseName to camel_case_name. It uses some | 245 // 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. | 246 // heuristics to try to handle acronyms in camel case names correctly. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 // - Foo foo() // Direct application of |type_with_same_name_as_function|. | 337 // - Foo foo() // Direct application of |type_with_same_name_as_function|. |
316 // - Foo* foo() // |hasDescendant| traverses references/pointers. | 338 // - Foo* foo() // |hasDescendant| traverses references/pointers. |
317 // - RefPtr<Foo> foo() // |hasDescendant| traverses template arguments. | 339 // - RefPtr<Foo> foo() // |hasDescendant| traverses template arguments. |
318 auto type_containing_same_name_as_function = | 340 auto type_containing_same_name_as_function = |
319 qualType(anyOf(type_with_same_name_as_function, | 341 qualType(anyOf(type_with_same_name_as_function, |
320 hasDescendant(type_with_same_name_as_function))); | 342 hasDescendant(type_with_same_name_as_function))); |
321 // https://crbug.com/582312: Prepend "Get" if method name conflicts with | 343 // https://crbug.com/582312: Prepend "Get" if method name conflicts with |
322 // return type. | 344 // return type. |
323 auto conflict_matcher = | 345 auto conflict_matcher = |
324 functionDecl(returns(type_containing_same_name_as_function)); | 346 functionDecl(returns(type_containing_same_name_as_function)); |
325 if (!match(conflict_matcher, decl, context).empty()) | 347 if (IsMatching(conflict_matcher, decl, context)) |
326 name = "Get" + name; | 348 name = "Get" + name; |
327 | 349 |
328 return true; | 350 return true; |
329 } | 351 } |
330 | 352 |
331 bool GetNameForDecl(const clang::EnumConstantDecl& decl, | 353 bool GetNameForDecl(const clang::EnumConstantDecl& decl, |
332 clang::ASTContext& context, | 354 clang::ASTContext& context, |
333 std::string& name) { | 355 std::string& name) { |
334 StringRef original_name = decl.getName(); | 356 StringRef original_name = decl.getName(); |
335 | 357 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
529 | 551 |
530 template <> | 552 template <> |
531 struct TargetNodeTraits<clang::UnresolvedMemberExpr> { | 553 struct TargetNodeTraits<clang::UnresolvedMemberExpr> { |
532 static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) { | 554 static clang::SourceLocation GetLoc(const clang::UnresolvedMemberExpr& expr) { |
533 return expr.getMemberLoc(); | 555 return expr.getMemberLoc(); |
534 } | 556 } |
535 static const char* GetName() { return "expr"; } | 557 static const char* GetName() { return "expr"; } |
536 static const char* GetType() { return "UnresolvedMemberExpr"; } | 558 static const char* GetType() { return "UnresolvedMemberExpr"; } |
537 }; | 559 }; |
538 | 560 |
539 template <typename DeclNode, typename TargetNode> | 561 template <> |
562 struct TargetNodeTraits<clang::UnresolvedUsingValueDecl> { | |
563 static clang::SourceLocation GetLoc( | |
564 const clang::UnresolvedUsingValueDecl& decl) { | |
565 return decl.getNameInfo().getLoc(); | |
566 } | |
567 static const char* GetName() { return "decl"; } | |
568 static const char* GetType() { return "UnresolvedUsingValueDecl"; } | |
569 }; | |
570 | |
571 template <typename TargetNode> | |
540 class RewriterBase : public MatchFinder::MatchCallback { | 572 class RewriterBase : public MatchFinder::MatchCallback { |
541 public: | 573 public: |
542 explicit RewriterBase(std::set<Replacement>* replacements) | 574 explicit RewriterBase(std::set<Replacement>* replacements) |
543 : replacements_(replacements) {} | 575 : replacements_(replacements) {} |
544 | 576 |
577 const TargetNode& GetTargetNode(const MatchFinder::MatchResult& result) { | |
578 const TargetNode* target_node = result.Nodes.getNodeAs<TargetNode>( | |
579 TargetNodeTraits<TargetNode>::GetName()); | |
580 assert(target_node); | |
581 return *target_node; | |
582 } | |
583 | |
584 void AddReplacement(const MatchFinder::MatchResult& result, | |
585 llvm::StringRef old_name, | |
586 std::string new_name) { | |
587 if (old_name == new_name) | |
588 return; | |
589 | |
590 clang::SourceLocation loc = | |
591 TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result)); | |
592 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); | |
593 replacements_->emplace(*result.SourceManager, range, new_name); | |
594 replacement_names_.emplace(old_name.str(), std::move(new_name)); | |
595 } | |
596 | |
597 const std::unordered_map<std::string, std::string>& replacement_names() | |
598 const { | |
599 return replacement_names_; | |
600 } | |
601 | |
602 private: | |
603 std::set<Replacement>* const replacements_; | |
604 std::unordered_map<std::string, std::string> replacement_names_; | |
605 }; | |
606 | |
607 template <typename DeclNode, typename TargetNode> | |
608 class DeclRewriterBase : public RewriterBase<TargetNode> { | |
609 public: | |
610 using Base = RewriterBase<TargetNode>; | |
611 | |
612 explicit DeclRewriterBase(std::set<Replacement>* replacements) | |
613 : Base(replacements) {} | |
614 | |
545 void run(const MatchFinder::MatchResult& result) override { | 615 void run(const MatchFinder::MatchResult& result) override { |
546 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); | 616 const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl"); |
617 assert(decl); | |
547 // If false, there's no name to be renamed. | 618 // If false, there's no name to be renamed. |
548 if (!decl->getIdentifier()) | 619 if (!decl->getIdentifier()) |
549 return; | 620 return; |
550 clang::SourceLocation decl_loc = | 621 clang::SourceLocation decl_loc = |
551 TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl); | 622 TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl); |
552 if (decl_loc.isMacroID()) { | 623 if (decl_loc.isMacroID()) { |
553 // Get the location of the spelling of the declaration. If token pasting | 624 // Get the location of the spelling of the declaration. If token pasting |
554 // was used this will be in "scratch space" and we don't know how to get | 625 // was used this will be in "scratch space" and we don't know how to get |
555 // from there back to/ the actual macro with the foo##bar text. So just | 626 // from there back to/ the actual macro with the foo##bar text. So just |
556 // don't replace in that case. | 627 // don't replace in that case. |
557 clang::SourceLocation spell = | 628 clang::SourceLocation spell = |
558 result.SourceManager->getSpellingLoc(decl_loc); | 629 result.SourceManager->getSpellingLoc(decl_loc); |
559 if (strcmp(result.SourceManager->getBufferName(spell), | 630 if (strcmp(result.SourceManager->getBufferName(spell), |
560 "<scratch space>") == 0) | 631 "<scratch space>") == 0) |
561 return; | 632 return; |
562 } | 633 } |
563 clang::ASTContext* context = result.Context; | 634 clang::ASTContext* context = result.Context; |
564 std::string new_name; | 635 std::string new_name; |
565 if (!GetNameForDecl(*decl, *context, new_name)) | 636 if (!GetNameForDecl(*decl, *context, new_name)) |
566 return; // If false, the name was not suitable for renaming. | 637 return; // If false, the name was not suitable for renaming. |
567 llvm::StringRef old_name = decl->getName(); | 638 llvm::StringRef old_name = decl->getName(); |
568 if (old_name == new_name) | 639 Base::AddReplacement(result, old_name, std::move(new_name)); |
569 return; | |
570 clang::SourceLocation loc = TargetNodeTraits<TargetNode>::GetLoc( | |
571 *result.Nodes.getNodeAs<TargetNode>( | |
572 TargetNodeTraits<TargetNode>::GetName())); | |
573 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc); | |
574 replacements_->emplace(*result.SourceManager, range, new_name); | |
575 replacement_names_.emplace(old_name.str(), std::move(new_name)); | |
576 } | 640 } |
641 }; | |
577 | 642 |
578 const std::unordered_map<std::string, std::string>& replacement_names() | 643 using FieldDeclRewriter = DeclRewriterBase<clang::FieldDecl, clang::NamedDecl>; |
579 const { | 644 using VarDeclRewriter = DeclRewriterBase<clang::VarDecl, clang::NamedDecl>; |
580 return replacement_names_; | 645 using MemberRewriter = DeclRewriterBase<clang::FieldDecl, clang::MemberExpr>; |
646 using DeclRefRewriter = DeclRewriterBase<clang::VarDecl, clang::DeclRefExpr>; | |
647 using FieldDeclRefRewriter = | |
648 DeclRewriterBase<clang::FieldDecl, clang::DeclRefExpr>; | |
649 using FunctionDeclRewriter = | |
650 DeclRewriterBase<clang::FunctionDecl, clang::NamedDecl>; | |
651 using FunctionRefRewriter = | |
652 DeclRewriterBase<clang::FunctionDecl, clang::DeclRefExpr>; | |
653 using ConstructorInitializerRewriter = | |
654 DeclRewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>; | |
655 | |
656 using MethodDeclRewriter = | |
657 DeclRewriterBase<clang::CXXMethodDecl, clang::NamedDecl>; | |
658 using MethodRefRewriter = | |
659 DeclRewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>; | |
660 using MethodMemberRewriter = | |
661 DeclRewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; | |
662 | |
663 using EnumConstantDeclRewriter = | |
664 DeclRewriterBase<clang::EnumConstantDecl, clang::NamedDecl>; | |
665 using EnumConstantDeclRefRewriter = | |
666 DeclRewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; | |
667 | |
668 using UnresolvedLookupRewriter = | |
669 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; | |
670 using UnresolvedMemberRewriter = | |
671 DeclRewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | |
672 | |
673 using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; | |
674 | |
675 clang::DeclarationName GetUnresolvedName( | |
676 const clang::UnresolvedMemberExpr& expr) { | |
677 return expr.getMemberName(); | |
678 } | |
679 | |
680 clang::DeclarationName GetUnresolvedName( | |
681 const clang::UnresolvedUsingValueDecl& decl) { | |
682 return decl.getDeclName(); | |
683 } | |
684 | |
685 // Returns whether |expr_node| is used as a callee in the AST (i.e. if | |
686 // |expr_node| needs to resolve to a method or a function). | |
687 bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) { | |
688 auto matcher = stmt(hasParent(callExpr(callee(equalsNode(&expr))))); | |
dcheng
2016/11/28 22:05:48
Why is it important to test this for UnresolvedMem
Łukasz Anforowicz
2016/11/29 00:45:42
I don't remember :-(. I should have added tests w
Łukasz Anforowicz
2016/11/29 20:01:05
Found it! I've added a regression test in the fol
| |
689 return IsMatching(matcher, expr, context); | |
690 } | |
691 | |
692 // Returns whether |decl| will be used as a callee in the AST (i.e. if the value | |
693 // brought by the using declaration will resolve to a method or a function). | |
694 bool IsCallee(const clang::UnresolvedUsingValueDecl& /* decl */, | |
695 clang::ASTContext& /* context */) { | |
696 // Heuristic - looking only at the shape of AST, let's assume that |using | |
697 // Base::foo| refers to a method. This heuristic can be refined by also | |
698 // looking at the name of |decl| (this is done both for | |
699 // UnresolvedUsingValueDecl and for clang::Expr in | |
700 // GuessNameForUnresolvedDependentNode method). | |
701 return true; | |
702 } | |
703 | |
704 template <typename TargetNode> | |
705 class UnresolvedRewriterBase : public RewriterBase<TargetNode> { | |
706 public: | |
707 using Base = RewriterBase<TargetNode>; | |
708 | |
709 explicit UnresolvedRewriterBase(std::set<Replacement>* replacements) | |
710 : RewriterBase<TargetNode>(replacements) {} | |
711 | |
712 void run(const MatchFinder::MatchResult& result) override { | |
713 const TargetNode& expr = Base::GetTargetNode(result); | |
714 llvm::StringRef old_name = GetUnresolvedName(expr).getAsString(); | |
715 std::string new_name; | |
716 if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name, | |
717 new_name)) { | |
718 Base::AddReplacement(result, old_name, std::move(new_name)); | |
719 } | |
581 } | 720 } |
582 | 721 |
583 private: | 722 private: |
584 std::set<Replacement>* const replacements_; | 723 // This method calculates a new name for nodes that depend on template |
585 std::unordered_map<std::string, std::string> replacement_names_; | 724 // parameters (http://en.cppreference.com/w/cpp/language/dependent_name). The |
725 // renaming is based on crude heuristics, because such nodes are not bound to | |
726 // a specific decl until template instantiation - at the point of rename, one | |
727 // cannot tell whether the node will eventually resolve to a field / method / | |
728 // constant / etc. | |
729 bool GuessNameForUnresolvedDependentNode(const TargetNode& node, | |
730 clang::ASTContext& context, | |
731 llvm::StringRef old_name, | |
732 std::string& new_name) { | |
733 // |m_fieldName| -> |field_name_|. | |
734 if (old_name.startswith(kBlinkFieldPrefix)) { | |
735 std::string field_name = old_name.str().substr(strlen(kBlinkFieldPrefix)); | |
736 if (field_name.find('_') == std::string::npos) { | |
737 new_name = CamelCaseToUnderscoreCase(field_name) + "_"; | |
738 return true; | |
739 } | |
740 } | |
741 | |
742 // |T::myMethod(...)| -> |T::MyMethod(...)|. | |
743 if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) && | |
744 !IsBlacklistedFunctionOrMethodName(old_name)) { | |
745 new_name = old_name; | |
746 new_name[0] = clang::toUppercase(new_name[0]); | |
747 return true; | |
748 } | |
749 | |
750 // In the future we can consider more heuristics: | |
751 // - "s_" and "g_" prefixes | |
752 // - "ALL_CAPS" | |
753 // - |T::myStaticField| -> |T::kMyStaticField| | |
754 // (but have to be careful not to rename |value| in WTF/TypeTraits.h?) | |
755 return false; | |
756 } | |
586 }; | 757 }; |
587 | 758 |
588 using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>; | 759 using UnresolvedDependentMemberRewriter = |
589 using VarDeclRewriter = RewriterBase<clang::VarDecl, clang::NamedDecl>; | 760 UnresolvedRewriterBase<clang::UnresolvedMemberExpr>; |
590 using MemberRewriter = RewriterBase<clang::FieldDecl, clang::MemberExpr>; | |
591 using DeclRefRewriter = RewriterBase<clang::VarDecl, clang::DeclRefExpr>; | |
592 using FieldDeclRefRewriter = RewriterBase<clang::FieldDecl, clang::DeclRefExpr>; | |
593 using FunctionDeclRewriter = | |
594 RewriterBase<clang::FunctionDecl, clang::NamedDecl>; | |
595 using FunctionRefRewriter = | |
596 RewriterBase<clang::FunctionDecl, clang::DeclRefExpr>; | |
597 using ConstructorInitializerRewriter = | |
598 RewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>; | |
599 | 761 |
600 using MethodDeclRewriter = RewriterBase<clang::CXXMethodDecl, clang::NamedDecl>; | 762 using UnresolvedUsingValueDeclRewriter = |
601 using MethodRefRewriter = | 763 UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; |
602 RewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>; | |
603 using MethodMemberRewriter = | |
604 RewriterBase<clang::CXXMethodDecl, clang::MemberExpr>; | |
605 | |
606 using EnumConstantDeclRewriter = | |
607 RewriterBase<clang::EnumConstantDecl, clang::NamedDecl>; | |
608 using EnumConstantDeclRefRewriter = | |
609 RewriterBase<clang::EnumConstantDecl, clang::DeclRefExpr>; | |
610 | |
611 using UnresolvedLookupRewriter = | |
612 RewriterBase<clang::NamedDecl, clang::UnresolvedLookupExpr>; | |
613 using UnresolvedMemberRewriter = | |
614 RewriterBase<clang::NamedDecl, clang::UnresolvedMemberExpr>; | |
615 | |
616 using UsingDeclRewriter = RewriterBase<clang::UsingDecl, clang::NamedDecl>; | |
617 | 764 |
618 } // namespace | 765 } // namespace |
619 | 766 |
620 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); | 767 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); |
621 | 768 |
622 int main(int argc, const char* argv[]) { | 769 int main(int argc, const char* argv[]) { |
623 // TODO(dcheng): Clang tooling should do this itself. | 770 // TODO(dcheng): Clang tooling should do this itself. |
624 // http://llvm.org/bugs/show_bug.cgi?id=21627 | 771 // http://llvm.org/bugs/show_bug.cgi?id=21627 |
625 llvm::InitializeNativeTarget(); | 772 llvm::InitializeNativeTarget(); |
626 llvm::InitializeNativeTargetAsmParser(); | 773 llvm::InitializeNativeTargetAsmParser(); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 // UnresolvedMemberExpr matcher below are analogous to how the | 1025 // UnresolvedMemberExpr matcher below are analogous to how the |
879 // rewriter has both a MemberRefRewriter matcher to rewrite | 1026 // rewriter has both a MemberRefRewriter matcher to rewrite |
880 // &T::method and a MethodMemberRewriter matcher to rewriter | 1027 // &T::method and a MethodMemberRewriter matcher to rewriter |
881 // t.method(). | 1028 // t.method(). |
882 allOverloadsMatch(anyOf(method_decl_matcher, | 1029 allOverloadsMatch(anyOf(method_decl_matcher, |
883 method_template_decl_matcher)))))); | 1030 method_template_decl_matcher)))))); |
884 UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements); | 1031 UnresolvedLookupRewriter unresolved_lookup_rewriter(&replacements); |
885 match_finder.addMatcher(unresolved_lookup_matcher, | 1032 match_finder.addMatcher(unresolved_lookup_matcher, |
886 &unresolved_lookup_rewriter); | 1033 &unresolved_lookup_rewriter); |
887 | 1034 |
888 // Unresolved member expressions ======== | 1035 // Unresolved member expressions (for non-dependent fields / methods) ======== |
889 // Similar to unresolved lookup expressions, but for methods in a member | 1036 // Similar to unresolved lookup expressions, but for methods in a member |
890 // context, e.g. var_with_templated_type.Method(). | 1037 // context, e.g. var_with_templated_type.Method(). |
891 auto unresolved_member_matcher = expr(id( | 1038 auto unresolved_member_matcher = expr(id( |
892 "expr", | 1039 "expr", |
893 unresolvedMemberExpr( | 1040 unresolvedMemberExpr( |
894 // Similar to UnresolvedLookupExprs, all the candidate methods must be | 1041 // Similar to UnresolvedLookupExprs, all the candidate methods must be |
895 // Blink methods/method templates. | 1042 // Blink methods/method templates. |
896 allOverloadsMatch( | 1043 allOverloadsMatch( |
897 anyOf(method_decl_matcher, method_template_decl_matcher))))); | 1044 anyOf(method_decl_matcher, method_template_decl_matcher))))); |
898 UnresolvedMemberRewriter unresolved_member_rewriter(&replacements); | 1045 UnresolvedMemberRewriter unresolved_member_rewriter(&replacements); |
899 match_finder.addMatcher(unresolved_member_matcher, | 1046 match_finder.addMatcher(unresolved_member_matcher, |
900 &unresolved_member_rewriter); | 1047 &unresolved_member_rewriter); |
901 | 1048 |
1049 // Unresolved using value decls ======== | |
1050 // Example: | |
1051 // template <typename T> | |
1052 // class BaseClass { | |
1053 // public: | |
1054 // unsigned long m_size; | |
1055 // }; | |
1056 // template <typename T> | |
1057 // class DerivedClass : protected BaseClass<T> { | |
1058 // private: | |
1059 // using Base = BaseClass<T>; | |
1060 // using Base::m_size; <- matched by |unresolved_using_value_decl_matcher|. | |
dcheng
2016/11/28 22:05:48
Super minor nit: Add a // here, or consider just m
Łukasz Anforowicz
2016/11/29 00:45:42
Done. (this also unifies the formatting of the co
| |
1061 // void method() { | |
1062 // m_size = 123; // <- |m_size| matched by | |
1063 // } // |unresolved_dependent_using_matcher|. | |
1064 // }; | |
1065 auto unresolved_dependent_using_matcher = | |
1066 expr(id("expr", unresolvedMemberExpr(allOverloadsMatch(allOf( | |
1067 in_blink_namespace, unresolvedUsingValueDecl()))))); | |
1068 UnresolvedDependentMemberRewriter unresolved_dependent_member_rewriter( | |
1069 &replacements); | |
1070 match_finder.addMatcher(unresolved_dependent_using_matcher, | |
1071 &unresolved_dependent_member_rewriter); | |
1072 auto unresolved_using_value_decl_matcher = | |
1073 decl(id("decl", unresolvedUsingValueDecl(in_blink_namespace))); | |
1074 UnresolvedUsingValueDeclRewriter unresolved_using_value_decl_rewriter( | |
1075 &replacements); | |
1076 match_finder.addMatcher(unresolved_using_value_decl_matcher, | |
1077 &unresolved_using_value_decl_rewriter); | |
1078 | |
902 // Using declarations ======== | 1079 // Using declarations ======== |
903 // Given | 1080 // Given |
904 // using blink::X; | 1081 // using blink::X; |
905 // matches |using blink::X|. | 1082 // matches |using blink::X|. |
906 auto using_decl_matcher = id( | 1083 auto using_decl_matcher = id( |
907 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( | 1084 "decl", usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf( |
908 var_decl_matcher, field_decl_matcher, function_decl_matcher, | 1085 var_decl_matcher, field_decl_matcher, function_decl_matcher, |
909 method_decl_matcher, function_template_decl_matcher, | 1086 method_decl_matcher, function_template_decl_matcher, |
910 method_template_decl_matcher, enum_member_decl_matcher))))); | 1087 method_template_decl_matcher, enum_member_decl_matcher))))); |
911 UsingDeclRewriter using_decl_rewriter(&replacements); | 1088 UsingDeclRewriter using_decl_rewriter(&replacements); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
955 for (const auto& r : replacements) { | 1132 for (const auto& r : replacements) { |
956 std::string replacement_text = r.getReplacementText().str(); | 1133 std::string replacement_text = r.getReplacementText().str(); |
957 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 1134 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
958 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 1135 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
959 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 1136 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
960 } | 1137 } |
961 llvm::outs() << "==== END EDITS ====\n"; | 1138 llvm::outs() << "==== END EDITS ====\n"; |
962 | 1139 |
963 return 0; | 1140 return 0; |
964 } | 1141 } |
OLD | NEW |