1 //===--- ExtractVariable.cpp ------------------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "Selection.h"
12 #include "SourceCode.h"
13 #include "refactor/Tweak.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/AST/ExprCXX.h"
19 #include "clang/AST/LambdaCapture.h"
20 #include "clang/AST/OperationKinds.h"
21 #include "clang/AST/RecursiveASTVisitor.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/StmtCXX.h"
24 #include "clang/Basic/LangOptions.h"
25 #include "clang/Basic/SourceLocation.h"
26 #include "clang/Basic/SourceManager.h"
27 #include "clang/Tooling/Core/Replacement.h"
28 #include "llvm/ADT/SmallVector.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/Error.h"
32 #include "llvm/Support/raw_ostream.h"
37 // information regarding the Expr that is being extracted
38 class ExtractionContext
{
40 ExtractionContext(const SelectionTree::Node
*Node
, const SourceManager
&SM
,
41 const ASTContext
&Ctx
);
42 const clang::Expr
*getExpr() const { return Expr
; }
43 const SelectionTree::Node
*getExprNode() const { return ExprNode
; }
44 bool isExtractable() const { return Extractable
; }
45 // The half-open range for the expression to be extracted.
46 SourceRange
getExtractionChars() const;
47 // Generate Replacement for replacing selected expression with given VarName
48 tooling::Replacement
replaceWithVar(SourceRange Chars
,
49 llvm::StringRef VarName
) const;
50 // Generate Replacement for declaring the selected Expr as a new variable
51 tooling::Replacement
insertDeclaration(llvm::StringRef VarName
,
52 SourceRange InitChars
,
53 bool AddSemicolon
) const;
56 bool Extractable
= false;
57 const clang::Expr
*Expr
;
59 const SelectionTree::Node
*ExprNode
;
60 // Stmt before which we will extract
61 const clang::Stmt
*InsertionPoint
= nullptr;
62 const SourceManager
&SM
;
63 const ASTContext
&Ctx
;
64 // Decls referenced in the Expr
65 std::vector
<clang::Decl
*> ReferencedDecls
;
66 // returns true if the Expr doesn't reference any variable declared in scope
67 bool exprIsValidOutside(const clang::Stmt
*Scope
) const;
68 // computes the Stmt before which we will extract out Expr
69 const clang::Stmt
*computeInsertionPoint() const;
72 // Returns all the Decls referenced inside the given Expr
73 static std::vector
<clang::Decl
*>
74 computeReferencedDecls(const clang::Expr
*Expr
) {
75 // RAV subclass to find all DeclRefs in a given Stmt
76 class FindDeclRefsVisitor
77 : public clang::RecursiveASTVisitor
<FindDeclRefsVisitor
> {
79 std::vector
<Decl
*> ReferencedDecls
;
80 bool VisitDeclRefExpr(DeclRefExpr
*DeclRef
) { // NOLINT
81 // Stop the call operator of lambdas from being marked as a referenced
82 // DeclRefExpr in immediately invoked lambdas.
83 if (const auto *const Method
=
84 llvm::dyn_cast
<CXXMethodDecl
>(DeclRef
->getDecl());
85 Method
!= nullptr && Method
->getParent()->isLambda()) {
88 ReferencedDecls
.push_back(DeclRef
->getDecl());
92 // Local variables declared inside of the selected lambda cannot go out of
93 // scope. The DeclRefExprs that are important are the variables captured,
94 // the DeclRefExprs inside the initializers of init-capture variables,
95 // variables mentioned in trailing return types, constraints and explicit
96 // defaulted template parameters.
97 bool TraverseLambdaExpr(LambdaExpr
*LExpr
) {
98 for (const auto &[Capture
, Initializer
] :
99 llvm::zip(LExpr
->captures(), LExpr
->capture_inits())) {
100 TraverseLambdaCapture(LExpr
, &Capture
, Initializer
);
103 if (clang::Expr
*const RequiresClause
=
104 LExpr
->getTrailingRequiresClause()) {
105 TraverseStmt(RequiresClause
);
108 for (auto *const TemplateParam
: LExpr
->getExplicitTemplateParameters())
109 TraverseDecl(TemplateParam
);
111 if (auto *const CallOperator
= LExpr
->getCallOperator()) {
112 TraverseType(CallOperator
->getDeclaredReturnType());
114 for (auto *const Param
: CallOperator
->parameters()) {
115 TraverseParmVarDecl(Param
);
118 for (auto *const Attr
: CallOperator
->attrs()) {
127 FindDeclRefsVisitor Visitor
;
128 Visitor
.TraverseStmt(const_cast<Stmt
*>(cast
<Stmt
>(Expr
)));
129 return Visitor
.ReferencedDecls
;
132 static QualType
computeVariableType(const Expr
*Expr
, const ASTContext
&Ctx
) {
133 if (Ctx
.getLangOpts().CPlusPlus11
)
134 return Ctx
.getAutoDeductType();
136 if (Expr
->hasPlaceholderType(BuiltinType::PseudoObject
)) {
137 if (const auto *PR
= dyn_cast
<ObjCPropertyRefExpr
>(Expr
)) {
138 if (PR
->isMessagingSetter()) {
139 // Don't support extracting a compound reference like `self.prop += 1`
140 // since the meaning changes after extraction since we'll no longer call
141 // the setter. Non compound access like `self.prop = 1` is invalid since
142 // it returns nil (setter method must have a void return type).
144 } else if (PR
->isMessagingGetter()) {
145 if (PR
->isExplicitProperty())
146 return PR
->getExplicitProperty()->getType();
148 return PR
->getImplicitPropertyGetter()->getReturnType();
154 return Expr
->getType();
157 ExtractionContext::ExtractionContext(const SelectionTree::Node
*Node
,
158 const SourceManager
&SM
,
159 const ASTContext
&Ctx
)
160 : ExprNode(Node
), SM(SM
), Ctx(Ctx
) {
161 Expr
= Node
->ASTNode
.get
<clang::Expr
>();
162 ReferencedDecls
= computeReferencedDecls(Expr
);
163 InsertionPoint
= computeInsertionPoint();
166 VarType
= computeVariableType(Expr
, Ctx
);
167 if (VarType
.isNull())
170 // Strip the outer nullability since it's not common for local variables.
171 AttributedType::stripOuterNullability(VarType
);
174 // checks whether extracting before InsertionPoint will take a
175 // variable reference out of scope
176 bool ExtractionContext::exprIsValidOutside(const clang::Stmt
*Scope
) const {
177 SourceLocation ScopeBegin
= Scope
->getBeginLoc();
178 SourceLocation ScopeEnd
= Scope
->getEndLoc();
179 for (const Decl
*ReferencedDecl
: ReferencedDecls
) {
180 if (ReferencedDecl
->getBeginLoc().isValid() &&
181 SM
.isPointWithin(ReferencedDecl
->getBeginLoc(), ScopeBegin
, ScopeEnd
) &&
182 SM
.isPointWithin(ReferencedDecl
->getEndLoc(), ScopeBegin
, ScopeEnd
))
188 // Return the Stmt before which we need to insert the extraction.
189 // To find the Stmt, we go up the AST Tree and if the Parent of the current
190 // Stmt is a CompoundStmt, we can extract inside this CompoundStmt just before
191 // the current Stmt. We ALWAYS insert before a Stmt whose parent is a
194 // FIXME: Extraction from label, switch and case statements
195 // FIXME: Doens't work for FoldExpr
196 // FIXME: Ensure extraction from loops doesn't change semantics.
197 const clang::Stmt
*ExtractionContext::computeInsertionPoint() const {
198 // returns true if we can extract before InsertionPoint
199 auto CanExtractOutside
=
200 [](const SelectionTree::Node
*InsertionPoint
) -> bool {
201 if (const clang::Stmt
*Stmt
= InsertionPoint
->ASTNode
.get
<clang::Stmt
>()) {
202 if (isa
<clang::Expr
>(Stmt
)) {
203 // Do not allow extraction from the initializer of a defaulted parameter
204 // to a local variable (e.g. a function-local lambda).
205 if (InsertionPoint
->Parent
->ASTNode
.get
<ParmVarDecl
>() != nullptr) {
212 // We don't yet allow extraction from switch/case stmt as we would need to
213 // jump over the switch stmt even if there is a CompoundStmt inside the
214 // switch. And there are other Stmts which we don't care about (e.g.
215 // continue and break) as there can never be anything to extract from
217 return isa
<AttributedStmt
>(Stmt
) || isa
<CompoundStmt
>(Stmt
) ||
218 isa
<CXXForRangeStmt
>(Stmt
) || isa
<DeclStmt
>(Stmt
) ||
219 isa
<DoStmt
>(Stmt
) || isa
<ForStmt
>(Stmt
) || isa
<IfStmt
>(Stmt
) ||
220 isa
<ReturnStmt
>(Stmt
) || isa
<WhileStmt
>(Stmt
);
222 if (InsertionPoint
->ASTNode
.get
<VarDecl
>())
226 for (const SelectionTree::Node
*CurNode
= getExprNode();
227 CurNode
->Parent
&& CanExtractOutside(CurNode
);
228 CurNode
= CurNode
->Parent
) {
229 const clang::Stmt
*CurInsertionPoint
= CurNode
->ASTNode
.get
<Stmt
>();
230 // give up if extraction will take a variable out of scope
231 if (CurInsertionPoint
&& !exprIsValidOutside(CurInsertionPoint
))
233 if (const clang::Stmt
*CurParent
= CurNode
->Parent
->ASTNode
.get
<Stmt
>()) {
234 if (isa
<CompoundStmt
>(CurParent
)) {
235 // Ensure we don't write inside a macro.
236 if (CurParent
->getBeginLoc().isMacroID())
238 return CurInsertionPoint
;
245 // returns the replacement for substituting the extraction with VarName
247 ExtractionContext::replaceWithVar(SourceRange Chars
,
248 llvm::StringRef VarName
) const {
249 unsigned ExtractionLength
=
250 SM
.getFileOffset(Chars
.getEnd()) - SM
.getFileOffset(Chars
.getBegin());
251 return tooling::Replacement(SM
, Chars
.getBegin(), ExtractionLength
, VarName
);
253 // returns the Replacement for declaring a new variable storing the extraction
255 ExtractionContext::insertDeclaration(llvm::StringRef VarName
,
256 SourceRange InitializerChars
,
257 bool AddSemicolon
) const {
258 llvm::StringRef ExtractionCode
= toSourceCode(SM
, InitializerChars
);
259 const SourceLocation InsertionLoc
=
260 toHalfOpenFileRange(SM
, Ctx
.getLangOpts(),
261 InsertionPoint
->getSourceRange())
263 std::string ExtractedVarDecl
=
264 printType(VarType
, ExprNode
->getDeclContext(), VarName
) + " = " +
265 ExtractionCode
.str();
267 ExtractedVarDecl
+= "; ";
268 return tooling::Replacement(SM
, InsertionLoc
, 0, ExtractedVarDecl
);
271 // Helpers for handling "binary subexpressions" like a + [[b + c]] + d.
273 // These are special, because the formal AST doesn't match what users expect:
274 // - the AST is ((a + b) + c) + d, so the ancestor expression is `a + b + c`.
275 // - but extracting `b + c` is reasonable, as + is (mathematically) associative.
277 // So we try to support these cases with some restrictions:
278 // - the operator must be associative
279 // - no mixing of operators is allowed
280 // - we don't look inside macro expansions in the subexpressions
281 // - we only adjust the extracted range, so references in the unselected parts
282 // of the AST expression (e.g. `a`) are still considered referenced for
283 // the purposes of calculating the insertion point.
284 // FIXME: it would be nice to exclude these references, by micromanaging
285 // the computeReferencedDecls() calls around the binary operator tree.
287 // Information extracted about a binary operator encounted in a SelectionTree.
288 // It can represent either an overloaded or built-in operator.
289 struct ParsedBinaryOperator
{
290 BinaryOperatorKind Kind
;
291 SourceLocation ExprLoc
;
292 llvm::SmallVector
<const SelectionTree::Node
*> SelectedOperands
;
294 // If N is a binary operator, populate this and return true.
295 bool parse(const SelectionTree::Node
&N
) {
296 SelectedOperands
.clear();
298 if (const BinaryOperator
*Op
=
299 llvm::dyn_cast_or_null
<BinaryOperator
>(N
.ASTNode
.get
<Expr
>())) {
300 Kind
= Op
->getOpcode();
301 ExprLoc
= Op
->getExprLoc();
302 SelectedOperands
= N
.Children
;
305 if (const CXXOperatorCallExpr
*Op
=
306 llvm::dyn_cast_or_null
<CXXOperatorCallExpr
>(
307 N
.ASTNode
.get
<Expr
>())) {
308 if (!Op
->isInfixBinaryOp())
311 Kind
= BinaryOperator::getOverloadedOpcode(Op
->getOperator());
312 ExprLoc
= Op
->getExprLoc();
313 // Not all children are args, there's also the callee (operator).
314 for (const auto *Child
: N
.Children
) {
315 const Expr
*E
= Child
->ASTNode
.get
<Expr
>();
316 assert(E
&& "callee and args should be Exprs!");
317 if (E
== Op
->getArg(0) || E
== Op
->getArg(1))
318 SelectedOperands
.push_back(Child
);
325 bool associative() const {
326 // Must also be left-associative, or update getBinaryOperatorRange()!
341 bool crossesMacroBoundary(const SourceManager
&SM
) {
342 FileID F
= SM
.getFileID(ExprLoc
);
343 for (const SelectionTree::Node
*Child
: SelectedOperands
)
344 if (SM
.getFileID(Child
->ASTNode
.get
<Expr
>()->getExprLoc()) != F
)
350 // If have an associative operator at the top level, then we must find
351 // the start point (rightmost in LHS) and end point (leftmost in RHS).
352 // We can only descend into subtrees where the operator matches.
354 // e.g. for a + [[b + c]] + d
362 const SourceRange
getBinaryOperatorRange(const SelectionTree::Node
&N
,
363 const SourceManager
&SM
,
364 const LangOptions
&LangOpts
) {
365 // If N is not a suitable binary operator, bail out.
366 ParsedBinaryOperator Op
;
367 if (!Op
.parse(N
.ignoreImplicit()) || !Op
.associative() ||
368 Op
.crossesMacroBoundary(SM
) || Op
.SelectedOperands
.size() != 2)
369 return SourceRange();
370 BinaryOperatorKind OuterOp
= Op
.Kind
;
372 // Because the tree we're interested in contains only one operator type, and
373 // all eligible operators are left-associative, the shape of the tree is
374 // very restricted: it's a linked list along the left edges.
375 // This simplifies our implementation.
376 const SelectionTree::Node
*Start
= Op
.SelectedOperands
.front(); // LHS
377 const SelectionTree::Node
*End
= Op
.SelectedOperands
.back(); // RHS
378 // End is already correct: it can't be an OuterOp (as it's left-associative).
379 // Start needs to be pushed down int the subtree to the right spot.
380 while (Op
.parse(Start
->ignoreImplicit()) && Op
.Kind
== OuterOp
&&
381 !Op
.crossesMacroBoundary(SM
)) {
382 assert(!Op
.SelectedOperands
.empty() && "got only operator on one side!");
383 if (Op
.SelectedOperands
.size() == 1) { // Only Op.RHS selected
384 Start
= Op
.SelectedOperands
.back();
387 // Op.LHS is (at least partially) selected, so descend into it.
388 Start
= Op
.SelectedOperands
.front();
392 toHalfOpenFileRange(SM
, LangOpts
, Start
->ASTNode
.getSourceRange())
394 toHalfOpenFileRange(SM
, LangOpts
, End
->ASTNode
.getSourceRange())
398 SourceRange
ExtractionContext::getExtractionChars() const {
399 // Special case: we're extracting an associative binary subexpression.
400 SourceRange BinaryOperatorRange
=
401 getBinaryOperatorRange(*ExprNode
, SM
, Ctx
.getLangOpts());
402 if (BinaryOperatorRange
.isValid())
403 return BinaryOperatorRange
;
405 // Usual case: we're extracting the whole expression.
406 return *toHalfOpenFileRange(SM
, Ctx
.getLangOpts(), Expr
->getSourceRange());
409 // Find the CallExpr whose callee is the (possibly wrapped) DeclRef
410 const SelectionTree::Node
*getCallExpr(const SelectionTree::Node
*DeclRef
) {
411 const SelectionTree::Node
&MaybeCallee
= DeclRef
->outerImplicit();
412 const SelectionTree::Node
*MaybeCall
= MaybeCallee
.Parent
;
416 llvm::dyn_cast_or_null
<CallExpr
>(MaybeCall
->ASTNode
.get
<Expr
>());
419 if (CE
->getCallee() != MaybeCallee
.ASTNode
.get
<Expr
>())
424 // Returns true if Inner (which is a direct child of Outer) is appearing as
425 // a statement rather than an expression whose value can be used.
426 bool childExprIsDisallowedStmt(const Stmt
*Outer
, const Expr
*Inner
) {
427 if (!Outer
|| !Inner
)
429 // Exclude the most common places where an expr can appear but be unused.
430 if (llvm::isa
<SwitchCase
>(Outer
))
432 // Control flow statements use condition etc, but not the body.
433 if (const auto *WS
= llvm::dyn_cast
<WhileStmt
>(Outer
))
434 return Inner
== WS
->getBody();
435 if (const auto *DS
= llvm::dyn_cast
<DoStmt
>(Outer
))
436 return Inner
== DS
->getBody();
437 if (const auto *FS
= llvm::dyn_cast
<ForStmt
>(Outer
))
438 return Inner
== FS
->getBody();
439 if (const auto *FS
= llvm::dyn_cast
<CXXForRangeStmt
>(Outer
))
440 return Inner
== FS
->getBody();
441 if (const auto *IS
= llvm::dyn_cast
<IfStmt
>(Outer
))
442 return Inner
== IS
->getThen() || Inner
== IS
->getElse();
443 // Assume all other cases may be actual expressions.
444 // This includes the important case of subexpressions (where Outer is Expr).
448 // check if N can and should be extracted (e.g. is not void-typed).
449 bool eligibleForExtraction(const SelectionTree::Node
*N
) {
450 const Expr
*E
= N
->ASTNode
.get
<Expr
>();
454 // Void expressions can't be assigned to variables.
455 const Type
*ExprType
= E
->getType().getTypePtrOrNull();
456 if (!ExprType
|| ExprType
->isVoidType())
459 // A plain reference to a name (e.g. variable) isn't worth extracting.
460 // FIXME: really? What if it's e.g. `std::is_same<void, void>::value`?
461 if (llvm::isa
<DeclRefExpr
>(E
))
464 // Similarly disallow extraction for member exprs with an implicit `this`.
465 if (const auto *ME
= dyn_cast
<MemberExpr
>(E
))
466 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(ME
->getBase()->IgnoreImpCasts()))
467 if (TE
->isImplicit())
470 // Extracting Exprs like a = 1 gives placeholder = a = 1 which isn't useful.
471 // FIXME: we could still hoist the assignment, and leave the variable there?
472 ParsedBinaryOperator BinOp
;
473 bool IsBinOp
= BinOp
.parse(*N
);
474 if (IsBinOp
&& BinaryOperator::isAssignmentOp(BinOp
.Kind
))
477 const SelectionTree::Node
&OuterImplicit
= N
->outerImplicit();
478 const auto *Parent
= OuterImplicit
.Parent
;
481 // Filter non-applicable expression statements.
482 if (childExprIsDisallowedStmt(Parent
->ASTNode
.get
<Stmt
>(),
483 OuterImplicit
.ASTNode
.get
<Expr
>()))
486 std::function
<bool(const SelectionTree::Node
*)> IsFullySelected
=
487 [&](const SelectionTree::Node
*N
) {
488 if (N
->ASTNode
.getSourceRange().isValid() &&
489 N
->Selected
!= SelectionTree::Complete
)
491 for (const auto *Child
: N
->Children
) {
492 if (!IsFullySelected(Child
))
497 auto ExprIsFullySelectedTargetNode
= [&](const Expr
*E
) {
498 if (E
!= OuterImplicit
.ASTNode
.get
<Expr
>())
501 // The above condition is the only relevant one except for binary operators.
502 // Without the following code, we would fail to offer extraction for e.g.:
503 // int x = 1 + 2 + [[3 + 4 + 5]];
504 // See the documentation of ParsedBinaryOperator for further details.
507 return IsFullySelected(N
);
510 // Disable extraction of full RHS on assignment operations, e.g:
512 // This would just result in duplicating the code.
513 if (const auto *BO
= Parent
->ASTNode
.get
<BinaryOperator
>()) {
514 if (BO
->isAssignmentOp() && ExprIsFullySelectedTargetNode(BO
->getRHS()))
518 // If e.g. a capture clause was selected, the target node is the lambda
519 // expression. We only want to offer the extraction if the entire lambda
520 // expression was selected.
521 if (llvm::isa
<LambdaExpr
>(E
))
522 return N
->Selected
== SelectionTree::Complete
;
524 // The same logic as for assignments applies to initializations.
525 // However, we do allow extracting the RHS of an init capture, as it is
526 // a valid use case to move non-trivial expressions out of the capture clause.
527 // FIXME: In that case, the extracted variable should be captured directly,
528 // rather than an explicit copy.
529 if (const auto *Decl
= Parent
->ASTNode
.get
<VarDecl
>()) {
530 if (!Decl
->isInitCapture() &&
531 ExprIsFullySelectedTargetNode(Decl
->getInit())) {
539 // Find the Expr node that we're going to extract.
540 // We don't want to trigger for assignment expressions and variable/field
541 // DeclRefs. For function/member function, we want to extract the entire
543 const SelectionTree::Node
*computeExtractedExpr(const SelectionTree::Node
*N
) {
546 const SelectionTree::Node
*TargetNode
= N
;
547 const clang::Expr
*SelectedExpr
= N
->ASTNode
.get
<clang::Expr
>();
550 // For function and member function DeclRefs, extract the whole call.
551 if (llvm::isa
<DeclRefExpr
>(SelectedExpr
) ||
552 llvm::isa
<MemberExpr
>(SelectedExpr
))
553 if (const SelectionTree::Node
*Call
= getCallExpr(N
))
555 // Extracting Exprs like a = 1 gives placeholder = a = 1 which isn't useful.
556 if (const BinaryOperator
*BinOpExpr
=
557 dyn_cast_or_null
<BinaryOperator
>(SelectedExpr
)) {
558 if (BinOpExpr
->getOpcode() == BinaryOperatorKind::BO_Assign
)
561 if (!TargetNode
|| !eligibleForExtraction(TargetNode
))
566 /// Extracts an expression to the variable placeholder
568 /// int x = 5 + 4 * 3;
571 /// auto placeholder = 5 + 4;
572 /// int x = placeholder * 3;
573 class ExtractVariable
: public Tweak
{
575 const char *id() const final
;
576 bool prepare(const Selection
&Inputs
) override
;
577 Expected
<Effect
> apply(const Selection
&Inputs
) override
;
578 std::string
title() const override
{
579 return "Extract subexpression to variable";
581 llvm::StringLiteral
kind() const override
{
582 return CodeAction::REFACTOR_KIND
;
586 // the expression to extract
587 std::unique_ptr
<ExtractionContext
> Target
;
589 REGISTER_TWEAK(ExtractVariable
)
590 bool ExtractVariable::prepare(const Selection
&Inputs
) {
591 // we don't trigger on empty selections for now
592 if (Inputs
.SelectionBegin
== Inputs
.SelectionEnd
)
594 const ASTContext
&Ctx
= Inputs
.AST
->getASTContext();
595 const SourceManager
&SM
= Inputs
.AST
->getSourceManager();
596 if (const SelectionTree::Node
*N
=
597 computeExtractedExpr(Inputs
.ASTSelection
.commonAncestor()))
598 Target
= std::make_unique
<ExtractionContext
>(N
, SM
, Ctx
);
599 return Target
&& Target
->isExtractable();
602 Expected
<Tweak::Effect
> ExtractVariable::apply(const Selection
&Inputs
) {
603 tooling::Replacements Result
;
604 // FIXME: get variable name from user or suggest based on type
605 std::string VarName
= "placeholder";
606 SourceRange Range
= Target
->getExtractionChars();
608 const SelectionTree::Node
&OuterImplicit
=
609 Target
->getExprNode()->outerImplicit();
610 assert(OuterImplicit
.Parent
);
611 bool IsExprStmt
= llvm::isa_and_nonnull
<CompoundStmt
>(
612 OuterImplicit
.Parent
->ASTNode
.get
<Stmt
>());
614 // insert new variable declaration. add a semicolon if and only if
615 // we are not dealing with an expression statement, which already has
616 // a semicolon that stays where it is, as it's not part of the range.
618 Result
.add(Target
->insertDeclaration(VarName
, Range
, !IsExprStmt
)))
619 return std::move(Err
);
621 // replace expression with variable name, unless it's an expression statement,
622 // in which case we remove it.
625 if (auto Err
= Result
.add(Target
->replaceWithVar(Range
, VarName
)))
626 return std::move(Err
);
627 return Effect::mainFileEdit(Inputs
.AST
->getSourceManager(),
632 } // namespace clangd