-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Feat/exclude completions of variable initializers #42087
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/exclude completions of variable initializers #42087
Conversation
… feat/exclude-completions-of-declared-variable
@andrewbranch Please look at this PR here.I am doing the same thing as you thought. I changed the existing test cases (because they had previously considered undeclared variables) and added a new test cases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, but I want to wait until more of the team is back after the holidays to add an additional review.
src/services/completions.ts
Outdated
} | ||
|
||
const variableDeclaration = findAncestor(property, (node) => { | ||
if (isFunctionLikeDeclaration(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to check if you’re actually in the body of the function, since this fails to filter out e.g. parameter defaults:
const fn = (p = /* 'fn' appears here */) => {}
That said, leaving in some bad completions that we already have is not a big problem IMO, so this is a minor nitpick.
A similar comment applies to isVariableDeclaration(node)
: what you’re interested in is whether we walked up from the initializer of a variable declaration, but you might have a false positive on a case like this:
const { a, b = /**/ } = { ... }
We’re not interested in getting the variable declaration if we started at the default binding for b
. But, it ends up having no effect on the outcome, since there will be no symbol where symbol.valueDeclaration === variableDeclaration
. But if it’s easy to skip that property access and equality check, we should do it, since it runs for every completion item. It could maybe shave off a couple milliseconds if the list is long.
This also brings up another point worth noting, that this logic won’t work for destructuring:
const { a, b } = { /** }; // 'a' and 'b' are offered
but I don’t think it’s worth doing anything about this. I really don’t want to have to loop through every binding element declaration for every symbol—I’m happy that currently the check is only one equality comparison per symbol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
You may want to check if you’re actually in the body of the function, since this fails to filter out e.g. parameter defaults:
Yes. You are right, maybe we should use
isFunctionBlock
to check. -
We’re not interested in getting the variable declaration if we started at the default binding for b. But, it ends up having no effect on the outcome, since there will be no symbol where symbol.valueDeclaration === variableDeclaration. But if it’s easy to skip that property access and equality check, we should do it, since it runs for every completion item. It could maybe shave off a couple milliseconds if the list is long.
I think we can use the
isBindingPattern
to filter out this two situations
const { a, b = /**/ } = { ... }
const [ a, b = /**/ ] = [ ... ]
-
This also brings up another point worth noting, that this logic won’t work for destructuring
I have the same idea with you. I think the time loss may be too much
For the 1 and 2, I have updated the code and added some test cases. Please help check it @andrewbranch
Supersedes #42056 |
src/services/completions.ts
Outdated
@@ -1543,7 +1543,7 @@ namespace ts.Completions { | |||
|
|||
function getVariableDeclaration(property: Node): VariableDeclaration | undefined { | |||
const variableDeclaration = findAncestor(property, (node) => { | |||
if (isFunctionLikeDeclaration(node)) { | |||
if (isFunctionBlock(node) || isBindingPattern(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn’t work for arrow function expressions without braces, e.g. () => expression/**/
. It seems like there should be a util for this but I can’t find an existing one: isFunctionBlock(node) || isArrowFunction(node.parent) && node.parent.expression === node
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. But I found no node.parent.expression. maybe node.parent.body?
isFunctionBlock(node) || (isArrowFunction(node.parent) && node.parent.body === node)
I has updated the code and add a new test case of arrow function expressions without braces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, body
is what I meant 👍
d9ab307
to
7b7cc24
Compare
@@ -2,4 +2,4 @@ | |||
|
|||
//// var x = this as/*1*/ | |||
|
|||
verify.completions({marker: "1", exact: completion.globalsPlus(["x"]) }) | |||
verify.completions({marker: "1", exact: completion.globals }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a very strange test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test has existed before, after this modification, there should be no 'x'. Let me optimize it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not saying there’s anything wrong here, just observing that it was weird for someone to write this test this way in the first place, a long time ago. I think the changes you made to these make sense 👍
b66e039
to
578a1ce
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me 🌟
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor formatting requests -- the check and its tests look correct to me.
thanks for you suggestions. done @sandersn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor nit with a cast
src/services/completions.ts
Outdated
? "quit" | ||
: isVariableDeclaration(node)); | ||
|
||
return variableDeclaration as VariableDeclaration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be as VariableDeclaration | undefined
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. You are right. Done
Fixes #41731