-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
feat: support TypeScript syntax in no-use-before-define
#19566
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
Changes from 3 commits
7edd79a
d7f6c64
d842554
73b3575
dda9f22
64659f8
b70fcc1
d02b75e
185c537
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,9 @@ function parseOptions(options) { | |
| classes: true, | ||
| variables: true, | ||
| allowNamedExports: false, | ||
| enums: true, | ||
| typedefs: true, | ||
| ignoreTypeReferences: true, | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -208,6 +211,54 @@ function isEvaluatedDuringInitialization(reference) { | |
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * check whether the reference contains a type query. | ||
| * @param {ASTNode} node Identifier node to check. | ||
| * @returns {boolean} true if reference contains type query. | ||
| */ | ||
| function referenceContainsTypeQuery(node) { | ||
| switch (node.type) { | ||
| case "TSTypeQuery": | ||
| return true; | ||
|
|
||
| case "TSQualifiedName": | ||
| case "Identifier": | ||
| return referenceContainsTypeQuery(node.parent); | ||
|
|
||
| default: | ||
| // if we find a different node, there's no chance that we're in a TSTypeQuery | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Decorators are transpiled such that the decorator is placed after the class declaration | ||
| * So it is considered safe | ||
| * @param {Variable} variable The variable to check. | ||
| * @param {Reference} reference The reference to check. | ||
| * @returns {boolean} `true` if the reference is in a class decorator. | ||
| */ | ||
| function isClassRefInClassDecorator(variable, reference) { | ||
| if ( | ||
| variable.defs[0].type !== "ClassName" || | ||
| variable.defs[0].node?.decorators?.length === 0 || | ||
snitin315 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| !Array.isArray(variable.defs[0].node?.decorators) | ||
| ) { | ||
| return false; | ||
| } | ||
|
|
||
| for (const deco of variable.defs[0].node.decorators) { | ||
| if ( | ||
| reference.identifier.range[0] >= deco.range[0] && | ||
| reference.identifier.range[1] <= deco.range[1] | ||
| ) { | ||
| return true; | ||
| } | ||
snitin315 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Rule Definition | ||
| //------------------------------------------------------------------------------ | ||
|
|
@@ -237,6 +288,9 @@ module.exports = { | |
| classes: { type: "boolean" }, | ||
| variables: { type: "boolean" }, | ||
| allowNamedExports: { type: "boolean" }, | ||
| enums: { type: "boolean" }, | ||
| typedefs: { type: "boolean" }, | ||
| ignoreTypeReferences: { type: "boolean" }, | ||
|
Comment on lines
+294
to
+296
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also update the types for this rule?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
| }, | ||
| additionalProperties: false, | ||
| }, | ||
|
|
@@ -250,6 +304,9 @@ module.exports = { | |
| functions: true, | ||
| variables: true, | ||
| allowNamedExports: false, | ||
| enums: true, | ||
| typedefs: true, | ||
| ignoreTypeReferences: true, | ||
| }, | ||
| ], | ||
|
|
||
|
|
@@ -310,6 +367,41 @@ module.exports = { | |
| return false; | ||
| } | ||
|
|
||
| if (!options.enums && definitionType === "TSEnumName") { | ||
| return false; | ||
| } | ||
|
|
||
| if (!options.typedefs && definitionType === "Type") { | ||
| return false; | ||
| } | ||
|
Comment on lines
+377
to
+379
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Testing] Removing this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems when /*eslint no-use-before-define: ["error", { "ignoreTypeReferences": false, "typedefs": false, }]*/
var x: Foo = {};
interface Foo {}please let me know if i am missing anything here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That looks good to me. I think there should also be testing for type Before = typeof after;
const after = {};type Before = After;
interface After {} |
||
|
|
||
| if ( | ||
| options.ignoreTypeReferences && | ||
| (referenceContainsTypeQuery(identifier) || | ||
| identifier.parent.type === "TSTypeReference") | ||
| ) { | ||
| return false; | ||
| } | ||
|
|
||
| // skip nested namespace aliases as variable references | ||
| if (identifier.parent.type === "TSQualifiedName") { | ||
| let currentNode = identifier.parent; | ||
|
|
||
| while (currentNode.type === "TSQualifiedName") { | ||
| currentNode = currentNode.left; | ||
| } | ||
|
|
||
| if (currentNode === identifier) { | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Testing] Switching this to |
||
| } | ||
|
|
||
| if (isClassRefInClassDecorator(variable, reference)) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -326,7 +418,8 @@ module.exports = { | |
| if ( | ||
| reference.identifier.range[1] < | ||
| definitionIdentifier.range[1] || | ||
| isEvaluatedDuringInitialization(reference) | ||
| (isEvaluatedDuringInitialization(reference) && | ||
| reference.identifier.parent.type !== "TSTypeReference") | ||
| ) { | ||
| context.report({ | ||
| node: reference.identifier, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.