-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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 |
andrewbranch
left a comment
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 offeredbut 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
isFunctionBlockto 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
isBindingPatternto 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 destructuringI 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
| 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
| //// 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
andrewbranch
left a comment
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 🌟
sandersn
left a comment
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 |
sandersn
left a comment
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