[refactor][selection] canonicalize selected string literal to objc

string literal when possible

llvm-svn: 317224
This commit is contained in:
Alex Lorenz 2017-11-02 18:05:48 +00:00
parent 6d2590baec
commit 547e5ad0af
2 changed files with 54 additions and 1 deletions

View File

@ -249,9 +249,30 @@ struct SelectedNodeWithParents {
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.
///
@ -330,7 +351,7 @@ CodeRangeASTSelection::create(SourceRange SelectionRange,
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);
}

View File

@ -972,4 +972,36 @@ TEST(ASTSelectionFinder, SimpleCodeRangeASTSelectionInObjCMethod) {
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