Author: arphaman Date: Tue Nov 14 15:10:50 2017 New Revision: 318215 URL: http://llvm.org/viewvc/llvm-project?rev=318215&view=rev Log: [refactor][selection] canonicalize decl ref callee to the call expr
We would like to extract the full call when just the callee function is selected Modified: cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp Modified: cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp?rev=318215&r1=318214&r2=318215&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp (original) +++ cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp Tue Nov 14 15:10:50 2017 @@ -259,29 +259,64 @@ struct SelectedNodeWithParents { /// when it makes sense to do so. void canonicalize(); }; -} // end anonymous namespace -void SelectedNodeWithParents::canonicalize() { - const Stmt *S = Node.get().Node.get<Stmt>(); - assert(S && "non statement selection!"); - const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>(); - if (!Parent) - return; +enum SelectionCanonicalizationAction { KeepSelection, SelectParent }; + +/// Returns the canonicalization action which should be applied to the +/// selected statement. +SelectionCanonicalizationAction +getSelectionCanonizalizationAction(const Stmt *S, const Stmt *Parent) { // Select the parent expression when: // - The string literal in ObjC string literal is selected, e.g.: // @"test" becomes @"test" // ~~~~~~ ~~~~~~~ if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent)) - Node = Parents.pop_back_val(); + return SelectParent; // The entire call should be selected when just the member expression - // that refers to the method is selected. + // that refers to the method or the decl ref that refers to the function + // is selected. // f.call(args) becomes f.call(args) // ~~~~ ~~~~~~~~~~~~ - else if (isa<MemberExpr>(S) && isa<CXXMemberCallExpr>(Parent) && - cast<CXXMemberCallExpr>(Parent)->getCallee() == S) - Node = Parents.pop_back_val(); + // func(args) becomes func(args) + // ~~~~ ~~~~~~~~~~ + else if (const auto *CE = dyn_cast<CallExpr>(Parent)) { + if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) && + CE->getCallee()->IgnoreImpCasts() == S) + return SelectParent; + } // FIXME: Syntactic form -> Entire pseudo-object expr. - // FIXME: Callee -> Call. + return KeepSelection; +} + +} // end anonymous namespace + +void SelectedNodeWithParents::canonicalize() { + const Stmt *S = Node.get().Node.get<Stmt>(); + assert(S && "non statement selection!"); + const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>(); + if (!Parent) + return; + + // Look through the implicit casts in the parents. + unsigned ParentIndex = 1; + for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(Parent); + ++ParentIndex) { + const Stmt *NewParent = + Parents[Parents.size() - ParentIndex - 1].get().Node.get<Stmt>(); + if (!NewParent) + break; + Parent = NewParent; + } + + switch (getSelectionCanonizalizationAction(S, Parent)) { + case SelectParent: + Node = Parents[Parents.size() - ParentIndex]; + for (; ParentIndex != 0; --ParentIndex) + Parents.pop_back(); + break; + case KeepSelection: + break; + } } /// Finds the set of bottom-most selected AST nodes that are in the selection Modified: cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp?rev=318215&r1=318214&r2=318215&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp (original) +++ cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp Tue Nov 14 15:10:50 2017 @@ -1056,4 +1056,30 @@ void dontSelectArgument(AClass &a) { }); } +TEST(ASTSelectionFinder, CanonicalizeFuncCalleeToCall) { + StringRef Source = R"( +void function(); + +void test() { + function(); +} + )"; + // Just 'function': + findSelectedASTNodesWithRange( + Source, {5, 3}, FileRange{{5, 3}, {5, 11}}, + [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) { + EXPECT_TRUE(Node); + Node->dump(); + Optional<CodeRangeASTSelection> SelectedCode = + CodeRangeASTSelection::create(SelectionRange, std::move(*Node)); + EXPECT_TRUE(SelectedCode); + EXPECT_EQ(SelectedCode->size(), 1u); + EXPECT_TRUE(isa<CallExpr>((*SelectedCode)[0])); + EXPECT_TRUE(isa<CompoundStmt>( + SelectedCode->getParents()[SelectedCode->getParents().size() - 1] + .get() + .Node.get<Stmt>())); + }); +} + } // end anonymous namespace _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits