1
1
import type { ScopeManager , Scope } from "eslint-scope" ;
2
2
import type * as ESTree from "estree" ;
3
3
import type { TSESTree } from "@typescript-eslint/types" ;
4
+ import type { Scope as TSScope } from "@typescript-eslint/scope-manager" ;
4
5
import type { Context , ScriptsSourceCode } from "." ;
5
6
import type {
6
7
Comment ,
@@ -20,19 +21,19 @@ import {
20
21
removeReference ,
21
22
removeScope ,
22
23
} from "../scope" ;
23
- import { traverseNodes } from "../traverse" ;
24
+ import { getKeys , traverseNodes , getNodes } from "../traverse" ;
24
25
import { UniqueIdGenerator } from "./unique" ;
25
26
26
27
type TSAsExpression = {
27
28
type : "TSAsExpression" ;
28
29
expression : ESTree . Expression ;
29
- typeAnnotation : TSParenthesizedType | ESTree . Node ;
30
+ typeAnnotation : TSParenthesizedType | TSESTree . TypeNode ;
30
31
} ;
31
32
32
33
// TS ESLint v4 Node
33
34
type TSParenthesizedType = {
34
35
type : "TSParenthesizedType" ;
35
- typeAnnotation : ESTree . Node ;
36
+ typeAnnotation : TSESTree . TypeNode ;
36
37
} ;
37
38
38
39
export type ScriptLetCallback < E extends ESTree . Node > = (
@@ -167,30 +168,10 @@ export class ScriptLetContext {
167
168
}
168
169
169
170
if ( isTS ) {
170
- const blockNode =
171
- tsAs ! . typeAnnotation . type === "TSParenthesizedType"
172
- ? tsAs ! . typeAnnotation . typeAnnotation
173
- : tsAs ! . typeAnnotation ;
174
- const targetScopes = [ result . getScope ( blockNode ) ] ;
175
- let targetBlockNode : TSESTree . Node | TSParenthesizedType =
176
- blockNode as any ;
177
- while (
178
- targetBlockNode . type === "TSConditionalType" ||
179
- targetBlockNode . type === "TSParenthesizedType"
180
- ) {
181
- if ( targetBlockNode . type === "TSParenthesizedType" ) {
182
- targetBlockNode = targetBlockNode . typeAnnotation as any ;
183
- continue ;
184
- }
185
- // TSConditionalType's `falseType` may not be a child scope.
186
- const falseType : TSESTree . TypeNode = targetBlockNode . falseType ;
187
- const falseTypeScope = result . getScope ( falseType as any ) ;
188
- if ( ! targetScopes . includes ( falseTypeScope ) ) {
189
- targetScopes . push ( falseTypeScope ) ;
190
- }
191
- targetBlockNode = falseType ;
192
- }
193
- for ( const scope of targetScopes ) {
171
+ for ( const scope of extractTypeNodeScopes (
172
+ tsAs ! . typeAnnotation ,
173
+ result
174
+ ) ) {
194
175
removeScope ( result . scopeManager , scope ) ;
195
176
}
196
177
this . remapNodes (
@@ -1039,3 +1020,44 @@ function getNodeToScope(
1039
1020
1040
1021
return nodeToScope ;
1041
1022
}
1023
+
1024
+ /** Extract the type scope of the given node. */
1025
+ function extractTypeNodeScopes (
1026
+ node : TSESTree . TypeNode | TSParenthesizedType ,
1027
+ result : ScriptLetCallbackOption
1028
+ ) : Iterable < Scope > {
1029
+ const scopes = new Set < Scope > ( ) ;
1030
+ for ( const scope of iterateTypeNodeScopes ( node ) ) {
1031
+ scopes . add ( scope ) ;
1032
+ }
1033
+
1034
+ return scopes ;
1035
+
1036
+ /** Iterate the type scope of the given node. */
1037
+ function * iterateTypeNodeScopes (
1038
+ node : TSESTree . TypeNode | TSParenthesizedType
1039
+ ) : Iterable < Scope > {
1040
+ if ( node . type === "TSParenthesizedType" ) {
1041
+ // Skip TSParenthesizedType.
1042
+ yield * iterateTypeNodeScopes ( node . typeAnnotation ) ;
1043
+ } else if ( node . type === "TSConditionalType" ) {
1044
+ yield result . getScope ( node as any ) ;
1045
+ // `falseType` of `TSConditionalType` is sibling scope.
1046
+ const falseType : TSESTree . TypeNode = node . falseType ;
1047
+ yield * iterateTypeNodeScopes ( falseType ) ;
1048
+ } else if (
1049
+ node . type === "TSFunctionType" ||
1050
+ node . type === "TSMappedType" ||
1051
+ node . type === "TSConstructorType"
1052
+ ) {
1053
+ yield result . getScope ( node as any ) ;
1054
+ } else {
1055
+ const typeNode : Exclude < TSESTree . TypeNode , TSScope [ "block" ] > = node ;
1056
+ for ( const key of getKeys ( typeNode , result . visitorKeys ) ) {
1057
+ for ( const child of getNodes ( typeNode , key ) ) {
1058
+ yield * iterateTypeNodeScopes ( child as TSESTree . TypeNode ) ;
1059
+ }
1060
+ }
1061
+ }
1062
+ }
1063
+ }
0 commit comments