r318215 - [refactor][selection] canonicalize decl ref callee to the call expr

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 14 15:10:50 PST 2017


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




More information about the cfe-commits mailing list