SelectedNodeWithParents &operator=(SelectedNodeWithParents &&) = default;
SelectedASTNode::ReferenceType Node;
llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
+
+ /// Canonicalizes the given selection by selecting different related AST nodes
+ /// 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;
+ // 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();
+ // FIXME: Syntactic form -> Entire pseudo-object expr.
+ // FIXME: Callee -> Call.
+ // FIXME: Callee member expr -> Call.
+}
+
/// Finds the set of bottom-most selected AST nodes that are in the selection
/// tree with the specified selection kind.
///
return None;
const Stmt *CodeRangeStmt = Selected.Node.get().Node.get<Stmt>();
if (!isa<CompoundStmt>(CodeRangeStmt)) {
- // FIXME (Alex L): Canonicalize.
+ Selected.canonicalize();
return CodeRangeASTSelection(Selected.Node, Selected.Parents,
/*AreChildrenSelected=*/false);
}
SelectionFinderVisitor::Lang_OBJC);
}
+TEST(ASTSelectionFinder, CanonicalizeObjCStringLiteral) {
+ StringRef Source = R"(
+void foo() {
+ (void)@"test";
+}
+ )";
+ // Just '"test"':
+ findSelectedASTNodesWithRange(
+ Source, {3, 10}, FileRange{{3, 10}, {3, 16}},
+ [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
+ EXPECT_TRUE(Node);
+ Optional<CodeRangeASTSelection> SelectedCode =
+ CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
+ EXPECT_TRUE(SelectedCode);
+ EXPECT_EQ(SelectedCode->size(), 1u);
+ EXPECT_TRUE(isa<ObjCStringLiteral>((*SelectedCode)[0]));
+ },
+ SelectionFinderVisitor::Lang_OBJC);
+ // Just 'test':
+ findSelectedASTNodesWithRange(
+ Source, {3, 11}, FileRange{{3, 11}, {3, 15}},
+ [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
+ EXPECT_TRUE(Node);
+ Optional<CodeRangeASTSelection> SelectedCode =
+ CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
+ EXPECT_TRUE(SelectedCode);
+ EXPECT_EQ(SelectedCode->size(), 1u);
+ EXPECT_TRUE(isa<ObjCStringLiteral>((*SelectedCode)[0]));
+ },
+ SelectionFinderVisitor::Lang_OBJC);
+}
+
} // end anonymous namespace