Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(eslint-plugin): [no-use-before-define] correctly handle typeof type references #2623

Merged
merged 3 commits into from Oct 11, 2020

Conversation

Drakota
Copy link
Contributor

@Drakota Drakota commented Oct 2, 2020

Fixes #2572

The no-use-before-define rule wasn't taking into account type reference that comes from values prefixed by the typeof operator.

Thank you @bradzacher for your help 馃檪

@typescript-eslint
Copy link
Contributor

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
Copy link

codecov bot commented Oct 2, 2020

Codecov Report

Merging #2623 into master will increase coverage by 0.00%.
The diff coverage is 80.00%.

@@           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     
Flag Coverage 螖
#unittest 92.83% <80.00%> (+<0.01%) 猬嗭笍

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage 螖
...es/eslint-plugin/src/rules/no-use-before-define.ts 92.50% <80.00%> (-1.87%) 猬囷笍
...es/eslint-plugin/src/rules/no-duplicate-imports.ts 97.77% <0.00%> (酶)

@bradzacher bradzacher added the bug Something isn't working label Oct 2, 2020
Copy link
Member

@bradzacher bradzacher left a 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
Copy link
Member

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.

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.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@bradzacher bradzacher added the awaiting response Issues waiting for a reply from the OP or another party label Oct 2, 2020
Comment on lines 99 to 105
if (node.type === AST_NODE_TYPES.TSTypeQuery) {
return true;
} else if (!node.parent) {
return false;
}

return referenceContainsTypeQuery(node.parent);
Copy link
Member

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;
}

Copy link
Contributor Author

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.

@bradzacher bradzacher removed the awaiting response Issues waiting for a reply from the OP or another party label Oct 11, 2020
Copy link
Member

@bradzacher bradzacher left a 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!

@bradzacher bradzacher changed the title fix(eslint-plugin): Added typeof value type reference check to no-use-before-define rule fix(eslint-plugin): [no-use-before-define] correctly handle typeof type references Oct 11, 2020
@bradzacher bradzacher merged commit 8e44c78 into typescript-eslint:master Oct 11, 2020
@Drakota Drakota deleted the fix/2572 branch October 12, 2020 02:32
@Drakota
Copy link
Contributor Author

Drakota commented Oct 12, 2020

Thank you for guiding me through this @bradzacher, I appreciate it 馃檪

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[no-use-before-define] False positive when using the typeof keyword
2 participants