From 8337f81f68365b2b2f8efb46a45a70fe54545351 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 14 Nov 2017 23:10:50 +0000 Subject: [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 llvm-svn: 318215 --- clang/lib/Tooling/Refactoring/ASTSelection.cpp | 61 ++++++++++++++++++++------ 1 file changed, 48 insertions(+), 13 deletions(-) (limited to 'clang/lib/Tooling/Refactoring/ASTSelection.cpp') diff --git a/clang/lib/Tooling/Refactoring/ASTSelection.cpp b/clang/lib/Tooling/Refactoring/ASTSelection.cpp index ae8a3cb7c58..7123fc32cec 100644 --- a/clang/lib/Tooling/Refactoring/ASTSelection.cpp +++ b/clang/lib/Tooling/Refactoring/ASTSelection.cpp @@ -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(); - assert(S && "non statement selection!"); - const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get(); - 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(S) && isa(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(S) && isa(Parent) && - cast(Parent)->getCallee() == S) - Node = Parents.pop_back_val(); + // func(args) becomes func(args) + // ~~~~ ~~~~~~~~~~ + else if (const auto *CE = dyn_cast(Parent)) { + if ((isa(S) || isa(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(); + assert(S && "non statement selection!"); + const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get(); + if (!Parent) + return; + + // Look through the implicit casts in the parents. + unsigned ParentIndex = 1; + for (; (ParentIndex + 1) <= Parents.size() && isa(Parent); + ++ParentIndex) { + const Stmt *NewParent = + Parents[Parents.size() - ParentIndex - 1].get().Node.get(); + 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 -- cgit v1.2.3