Skip to content

Commit c1bf009

Browse files
committed
[clangd] Consider expression statements in ExtractVariable tweak
For instance: int func(); int main() { func(); // => auto placeholder = func(); }
1 parent 0936195 commit c1bf009

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class ExtractionContext {
4949
llvm::StringRef VarName) const;
5050
// Generate Replacement for declaring the selected Expr as a new variable
5151
tooling::Replacement insertDeclaration(llvm::StringRef VarName,
52-
SourceRange InitChars) const;
52+
SourceRange InitChars,
53+
bool AddSemicolon) const;
5354

5455
private:
5556
bool Extractable = false;
@@ -252,15 +253,18 @@ ExtractionContext::replaceWithVar(SourceRange Chars,
252253
// returns the Replacement for declaring a new variable storing the extraction
253254
tooling::Replacement
254255
ExtractionContext::insertDeclaration(llvm::StringRef VarName,
255-
SourceRange InitializerChars) const {
256+
SourceRange InitializerChars,
257+
bool AddSemicolon) const {
256258
llvm::StringRef ExtractionCode = toSourceCode(SM, InitializerChars);
257259
const SourceLocation InsertionLoc =
258260
toHalfOpenFileRange(SM, Ctx.getLangOpts(),
259261
InsertionPoint->getSourceRange())
260262
->getBegin();
261263
std::string ExtractedVarDecl =
262264
printType(VarType, ExprNode->getDeclContext(), VarName) + " = " +
263-
ExtractionCode.str() + "; ";
265+
ExtractionCode.str();
266+
if (AddSemicolon)
267+
ExtractedVarDecl += "; ";
264268
return tooling::Replacement(SM, InsertionLoc, 0, ExtractedVarDecl);
265269
}
266270

@@ -423,8 +427,6 @@ bool childExprIsStmt(const Stmt *Outer, const Expr *Inner) {
423427
if (!Outer || !Inner)
424428
return false;
425429
// Exclude the most common places where an expr can appear but be unused.
426-
if (llvm::isa<CompoundStmt>(Outer))
427-
return true;
428430
if (llvm::isa<SwitchCase>(Outer))
429431
return true;
430432
// Control flow statements use condition etc, but not the body.
@@ -516,6 +518,12 @@ bool eligibleForExtraction(const SelectionTree::Node *N) {
516518
return false;
517519
}
518520

521+
// If e.g. a capture clause was selected, the target node is the lambda
522+
// expression. We only want to offer the extraction if the entire lambda
523+
// expression was selected.
524+
if (llvm::isa<LambdaExpr>(E))
525+
return N->Selected == SelectionTree::Complete;
526+
519527
// The same logic as for assignments applies to initializations.
520528
// However, we do allow extracting the RHS of an init capture, as it is
521529
// a valid use case to move non-trivial expressions out of the capture clause.
@@ -599,10 +607,22 @@ Expected<Tweak::Effect> ExtractVariable::apply(const Selection &Inputs) {
599607
// FIXME: get variable name from user or suggest based on type
600608
std::string VarName = "placeholder";
601609
SourceRange Range = Target->getExtractionChars();
610+
611+
const SelectionTree::Node &OuterImplicit =
612+
Target->getExprNode()->outerImplicit();
613+
assert(OuterImplicit.Parent);
614+
bool IsStmtExpr = llvm::isa_and_nonnull<CompoundStmt>(
615+
OuterImplicit.Parent->ASTNode.get<Stmt>());
616+
602617
// insert new variable declaration
603-
if (auto Err = Result.add(Target->insertDeclaration(VarName, Range)))
618+
if (auto Err =
619+
Result.add(Target->insertDeclaration(VarName, Range, !IsStmtExpr)))
604620
return std::move(Err);
605-
// replace expression with variable name
621+
622+
// replace expression with variable name, unless it's a statement expression,
623+
// in which case we remove it.
624+
if (IsStmtExpr)
625+
VarName.clear();
606626
if (auto Err = Result.add(Target->replaceWithVar(Range, VarName)))
607627
return std::move(Err);
608628
return Effect::mainFileEdit(Inputs.AST->getSourceManager(),

clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ TEST_F(ExtractVariableTest, Test) {
152152
a = [[b]];
153153
a = [[xyz()]];
154154
// statement expression
155-
[[xyz()]];
155+
[[v()]];
156156
while (a)
157157
[[++a]];
158158
// label statement
@@ -493,6 +493,16 @@ TEST_F(ExtractVariableTest, Test) {
493493
a = a + 1;
494494
}
495495
})cpp"},
496+
{R"cpp(
497+
int func() { return 0; }
498+
int main() {
499+
[[func()]];
500+
})cpp",
501+
R"cpp(
502+
int func() { return 0; }
503+
int main() {
504+
auto placeholder = func();
505+
})cpp"},
496506
{R"cpp(
497507
template <typename T>
498508
auto call(T t) { return t(); }

0 commit comments

Comments
 (0)