[PATCH] D63773: [clangd] dummy variable extraction on a function scope
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 4 05:01:42 PDT 2019
sammccall added inline comments.
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:42
+ // Generate Replacement for replacing selected expression with given VarName
+ tooling::Replacement replaceWithVar(std::string VarName) const;
+ // Generate Replacement for declaring the selected Expr as a new variable
----------------
nit: StringRef almost always for params you don't mutate
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:46
+ // returns true if the Expr can be extracted
+ inline bool isExtractable() const;
+
----------------
define trivial (and even simple) methods inline
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:65
+};
+/// Extracts an expression to the variable dummy
+/// Before:
----------------
nit: can you move the tweak to the end, to avoid alternating between the inner logic implementation and the outer interface?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:88
+// this is to avoid the function name being extracted in a function call.
+// e.g. int a = [[f]]();
+bool isAFunctionRef(const clang::Expr *Expr) {
----------------
I'd suggest naming this something more after the intent than after the structure, as we may want to refine it over time, e.g. `isTooTrivialToExtract` or `isEligibleToExtract`
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:90
+bool isAFunctionRef(const clang::Expr *Expr) {
+ const clang::DeclRefExpr *DeclRef = dyn_cast_or_null<DeclRefExpr>(Expr);
+ if (DeclRef && isa<FunctionDecl>(DeclRef->getDecl()))
----------------
Extracting just a declrefexpr (and replacing it with another declrefexpr) doesn't seem useful. Any reason to only do this for functions, rather than all declrefexprs?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:90
+bool isAFunctionRef(const clang::Expr *Expr) {
+ const clang::DeclRefExpr *DeclRef = dyn_cast_or_null<DeclRefExpr>(Expr);
+ if (DeclRef && isa<FunctionDecl>(DeclRef->getDecl()))
----------------
sammccall wrote:
> Extracting just a declrefexpr (and replacing it with another declrefexpr) doesn't seem useful. Any reason to only do this for functions, rather than all declrefexprs?
a syntactically similar case is MemberExpr where isImplicitAccess() is true. (This is referring to a method of the current class, without qualification)
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:91
+ const clang::DeclRefExpr *DeclRef = dyn_cast_or_null<DeclRefExpr>(Expr);
+ if (DeclRef && isa<FunctionDecl>(DeclRef->getDecl()))
+ return true;
----------------
you may want to check whether this does the right thing for a function template
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:120
+ if ((Expr = Node->ASTNode.get<clang::Expr>())) {
+ Expr->dump();
+ ReferencedDecls = computeReferencedDecls(Expr);
----------------
remove debug dumping
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:122
+ ReferencedDecls = computeReferencedDecls(Expr);
+ Extractable =
+ !isAFunctionRef(Expr) && (InsertionPoint = computeInsertionPoint());
----------------
Can we be a bit more explicit about the control flow and boolean initialization here?
e.g. `if (isAFunctionRef(Expr)) return; if (InsertionPoint = computeInsertionPoint()) Extractable = true;`
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:135
+// variable out of scope
+bool ExtractionContext::canInsertBefore(const clang::Stmt *Scope) const {
+ if (!Scope)
----------------
The name doesn't really match the behavior here - there are lots of other reasons we couldn't insert before a point.
this sounds more like `ExtractionContext::exprIsValidOutside` or something?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:137
+ if (!Scope)
+ return true;
+ SourceLocation ScopeBegin = Scope->getBeginLoc();
----------------
this behavior is not at all obvious at the callsite. I'd suggest making the caller check for null, and taking a reference.
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:158
+const clang::Stmt *ExtractionContext::computeInsertionPoint() const {
+ bool WaitForSwitch = false;
+ for (const SelectionTree::Node *CurNode = getExprNode(); CurNode->Parent;
----------------
The scope of this patch is growing in ways that don't seem to be related to the review.
Can you revert the switch-related changes and move them to another patch?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:165
+ break;
+ if (const clang::Stmt *Ancestor = CurNode->Parent->ASTNode.get<Stmt>()) {
+ if (WaitForSwitch) {
----------------
this is the Parent, not an Ancestor, I think?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:173
+ if (isa<CompoundStmt>(Ancestor)) {
+ // Return if the CurInsertionPoint is not inside a macro. Else we
+ // continue traversing up.
----------------
this describes what the code is doing, but that's fairly obvious from the code. It would be useful to say why instead.
e.g. "We only allow insertion inside a CompoundStmt. It must be written in the file, not a macro."
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:178
+ return CurInsertionPoint;
+ } else if (isa<SwitchCase>(Ancestor))
+ WaitForSwitch = true;
----------------
nit: please use braces consistently within an else-if chain
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:181
+ // don't extract from lambda captures/default arguments
+ else if (isa<LambdaExpr>(Ancestor))
+ break;
----------------
I think this is also new in this revision.
Can we move it to a followup patch? I'm not sure exactly what you're trying to do, but suspect there's a better way/place for it.
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:183
+ break;
+ }
+ // don't extract from function/method default arguments.
----------------
you're still traversing upwards through arbitrary AST nodes with a blacklist - as discussed previously this doesn't seem safe
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:219
+
+// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a = 1
+// FIXME: Expressions involving macro expansions
----------------
this FIXME probably belongs on the `isEligibleToExtract` or similar function
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:220
+// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a = 1
+// FIXME: Expressions involving macro expansions
+bool ExtractVariable::prepare(const Selection &Inputs) {
----------------
it's not clear what the bug or fix is for this
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D63773/new/
https://reviews.llvm.org/D63773
More information about the cfe-commits
mailing list