-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
fix(eslint-plugin): [no-use-before-define] correctly handle typeof type references #2623
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
Conversation
Thanks for the PR, @Drakota! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. As a thank you, your profile/company logo will be added to our main README which receives thousands of unique visitors per day. |
Codecov Report
@@ Coverage Diff @@
## master #2623 +/- ##
=======================================
Coverage 92.82% 92.83%
=======================================
Files 293 294 +1
Lines 9619 9673 +54
Branches 2697 2714 +17
=======================================
+ Hits 8929 8980 +51
- Misses 326 327 +1
- Partials 364 366 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
|
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're most of the way there!
A few comments.
Thanks for working on this.
function isTypeReference(reference: TSESLint.Scope.Reference): boolean { | ||
return ( | ||
reference.isTypeReference || | ||
reference.identifier.parent?.parent?.type === AST_NODE_TYPES.TSTypeQuery |
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.
almost! but this will only match one case.
We need to match all of these cases, and more:
typeof a
typeof a.b
typeof a.b.c
Instead an easier way to do this would be with a loop.
Based on the defined types for TSTypeQuery
, we know that the exprName
will either be an Identifier
or a TSQualifiedName
.
typescript-eslint/packages/types/src/ts-estree.ts
Lines 1669 to 1672 in d7dc108
export interface TSTypeQuery extends BaseNode { | |
type: AST_NODE_TYPES.TSTypeQuery; | |
exprName: EntityName; | |
} |
Based on the defined types for TSQualifiedName
, we know the left will always be an Identifier
or a TSQualifiedName
.
typescript-eslint/packages/types/src/ts-estree.ts
Lines 1572 to 1576 in d7dc108
export interface TSQualifiedName extends BaseNode { | |
type: AST_NODE_TYPES.TSQualifiedName; | |
left: EntityName; | |
right: Identifier; | |
} |
This means we can simply loop and look at the parents
The reason I gave you the above is it'll help you constrain the loop so it won't iterate forever
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.
Fixed!
packages/eslint-plugin/tests/rules/no-use-before-define.test.ts
Outdated
Show resolved
Hide resolved
if (node.type === AST_NODE_TYPES.TSTypeQuery) { | ||
return true; | ||
} else if (!node.parent) { | ||
return false; | ||
} | ||
|
||
return referenceContainsTypeQuery(node.parent); |
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.
Almost there!
We can constrain this a little more so we don't recursively traverse up the whole tree unnecessarily.
We know that the node must always be either be a TSQualifiedName
, Identifier
or TSTypeQuery
.
switch (node.type) {
case AST_NODE_TYPES.TSTypeQuery:
return true;
case AST_NODE_TYPES.TSQualifiedName:
case AST_NODE_TYPES.Identifier:
return referenceContainsTypeQuery(node.parent);
default:
// if we find a different node, there's no chance that we're in a TSTypeQuery
return false;
}
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 see! I wasn't sure of what you meant in your first comment.
I've changed 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.
LGTM - thanks for your contribution!
Thank you for guiding me through this @bradzacher, I appreciate it 🙂 |
Fixes #2572
The
no-use-before-define
rule wasn't taking into account type reference that comes from values prefixed by thetypeof
operator.Thank you @bradzacher for your help 🙂