Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit bb88c01

Browse filesBrowse files
authored
Fix wrong scope reference type for <script setup lang=ts> (#181)
* Fix wrong scope reference type for `<script setup lang=ts>` * update * update
1 parent 5c3558c commit bb88c01
Copy full SHA for bb88c01

File tree

Expand file treeCollapse file tree

10 files changed

+277
-64
lines changed
Filter options
Expand file treeCollapse file tree

10 files changed

+277
-64
lines changed

‎src/ast/nodes.ts

Copy file name to clipboardExpand all lines: src/ast/nodes.ts
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,10 @@ export interface Reference {
753753
id: ESLintIdentifier
754754
mode: "rw" | "r" | "w"
755755
variable: Variable | null
756+
757+
// For typescript-eslint
758+
isValueReference?: boolean
759+
isTypeReference?: boolean
756760
}
757761

758762
/**

‎src/script-setup/scope-analyzer.ts

Copy file name to clipboardExpand all lines: src/script-setup/scope-analyzer.ts
+16-3Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type * as escopeTypes from "eslint-scope"
22
import type { ParserOptions } from "../common/parser-options"
33
import type {
4+
Reference,
45
VAttribute,
56
VDirective,
67
VDocumentFragment,
@@ -169,7 +170,17 @@ function analyzeUsedInTemplateVariables(
169170
return false
170171
}
171172

172-
function markVariableAsUsed(name: string) {
173+
function markVariableAsUsed(nameOrRef: string | Reference) {
174+
let name: string
175+
let isValueReference: boolean | undefined
176+
let isTypeReference: boolean | undefined
177+
if (typeof nameOrRef === "string") {
178+
name = nameOrRef
179+
} else {
180+
name = nameOrRef.id.name
181+
isValueReference = nameOrRef.isValueReference
182+
isTypeReference = nameOrRef.isTypeReference
183+
}
173184
const variable = scriptVariables.get(name)
174185
if (!variable || variable.identifiers.length === 0) {
175186
return
@@ -188,7 +199,9 @@ function analyzeUsedInTemplateVariables(
188199
reference.isRead = () => true
189200
reference.isReadOnly = () => true
190201
reference.isReadWrite = () => false
191-
reference.isValueReference = true // For typescript-eslint
202+
// For typescript-eslint
203+
reference.isValueReference = isValueReference
204+
reference.isTypeReference = isTypeReference
192205

193206
variable.references.push(reference)
194207
reference.resolved = variable
@@ -198,7 +211,7 @@ function analyzeUsedInTemplateVariables(
198211
for (const reference of node.references.filter(
199212
(ref) => ref.variable == null,
200213
)) {
201-
markVariableAsUsed(reference.id.name)
214+
markVariableAsUsed(reference)
202215
}
203216
}
204217

‎src/script/index.ts

Copy file name to clipboardExpand all lines: src/script/index.ts
+33-20Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,15 @@ function parseExpressionBody(
340340
debug('[script] parse expression: "0(%s)"', code)
341341

342342
try {
343-
const ast = parseScriptFragment(
343+
const result = parseScriptFragment(
344344
`0(${code})`,
345345
locationCalculator.getSubCalculatorShift(-2),
346346
parserOptions,
347-
).ast
347+
)
348+
const { ast } = result
348349
const tokens = ast.tokens || []
349350
const comments = ast.comments || []
350-
const references = analyzeExternalReferences(ast, parserOptions)
351+
const references = analyzeExternalReferences(result, parserOptions)
351352
const statement = ast.body[0] as ESLintExpressionStatement
352353
const callExpression = statement.expression as ESLintCallExpression
353354
const expression = callExpression.arguments[0]
@@ -461,13 +462,14 @@ function parseFilter(
461462

462463
// Parse the arguments.
463464
if (argsCode != null) {
464-
const { ast } = parseScriptFragment(
465+
const result = parseScriptFragment(
465466
`0${argsCode}`,
466467
locationCalculator
467468
.getSubCalculatorAfter(paren)
468469
.getSubCalculatorShift(-1),
469470
parserOptions,
470471
)
472+
const { ast } = result
471473
const statement = ast.body[0] as ESLintExpressionStatement
472474
const callExpression = statement.expression
473475

@@ -501,7 +503,7 @@ function parseFilter(
501503
}
502504
tokens.push(...ast.tokens!)
503505
comments.push(...ast.comments!)
504-
references.push(...analyzeExternalReferences(ast, parserOptions))
506+
references.push(...analyzeExternalReferences(result, parserOptions))
505507
}
506508

507509
// Update range.
@@ -755,16 +757,20 @@ export function parseVForExpression(
755757
processed.iterator,
756758
)
757759

758-
const ast = parseScriptFragment(
760+
const result = parseScriptFragment(
759761
`for(let ${processed.aliasesWithBrackets}${processed.delimiter}${processed.iterator});`,
760762
locationCalculator.getSubCalculatorShift(
761763
processed.hasParens ? -8 : -9,
762764
),
763765
parserOptions,
764-
).ast
766+
)
767+
const { ast } = result
765768
const tokens = ast.tokens || []
766769
const comments = ast.comments || []
767-
const scope = analyzeVariablesAndExternalReferences(ast, parserOptions)
770+
const scope = analyzeVariablesAndExternalReferences(
771+
result,
772+
parserOptions,
773+
)
768774
const references = scope.references
769775
const variables = scope.variables
770776
const statement = ast.body[0] as
@@ -934,14 +940,15 @@ function parseVForAliasesForEcmaVersion5(
934940
locationCalculator: LocationCalculatorForHtml,
935941
parserOptions: ParserOptions,
936942
) {
937-
const ast = parseScriptFragment(
943+
const result = parseScriptFragment(
938944
`0(${code})`,
939945
locationCalculator.getSubCalculatorShift(-2),
940946
parserOptions,
941-
).ast
947+
)
948+
const { ast } = result
942949
const tokens = ast.tokens || []
943950
const comments = ast.comments || []
944-
const variables = analyzeExternalReferences(ast, parserOptions).map(
951+
const variables = analyzeExternalReferences(result, parserOptions).map(
945952
transformVariable,
946953
)
947954

@@ -984,14 +991,15 @@ function parseVForIteratorForEcmaVersion5(
984991
locationCalculator: LocationCalculatorForHtml,
985992
parserOptions: ParserOptions,
986993
) {
987-
const ast = parseScriptFragment(
994+
const result = parseScriptFragment(
988995
`0(${code})`,
989996
locationCalculator.getSubCalculatorShift(-2),
990997
parserOptions,
991-
).ast
998+
)
999+
const { ast } = result
9921000
const tokens = ast.tokens || []
9931001
const comments = ast.comments || []
994-
const references = analyzeExternalReferences(ast, parserOptions)
1002+
const references = analyzeExternalReferences(result, parserOptions)
9951003

9961004
const statement = ast.body[0] as ESLintExpressionStatement
9971005
const callExpression = statement.expression as ESLintCallExpression
@@ -1049,12 +1057,13 @@ function parseVOnExpressionBody(
10491057
}
10501058

10511059
try {
1052-
const ast = parseScriptFragment(
1060+
const result = parseScriptFragment(
10531061
`void function($event){${code}}`,
10541062
locationCalculator.getSubCalculatorShift(-22),
10551063
parserOptions,
1056-
).ast
1057-
const references = analyzeExternalReferences(ast, parserOptions)
1064+
)
1065+
const { ast } = result
1066+
const references = analyzeExternalReferences(result, parserOptions)
10581067
const outermostStatement = ast.body[0] as ESLintExpressionStatement
10591068
const functionDecl = (
10601069
outermostStatement.expression as ESLintUnaryExpression
@@ -1126,11 +1135,12 @@ export function parseSlotScopeExpression(
11261135
}
11271136

11281137
try {
1129-
const ast = parseScriptFragment(
1138+
const result = parseScriptFragment(
11301139
`void function(${code}) {}`,
11311140
locationCalculator.getSubCalculatorShift(-14),
11321141
parserOptions,
1133-
).ast
1142+
)
1143+
const { ast } = result
11341144
const statement = ast.body[0] as ESLintExpressionStatement
11351145
const rawExpression = statement.expression as ESLintUnaryExpression
11361146
const functionDecl = rawExpression.argument as ESLintFunctionExpression
@@ -1148,7 +1158,10 @@ export function parseSlotScopeExpression(
11481158

11491159
const tokens = ast.tokens || []
11501160
const comments = ast.comments || []
1151-
const scope = analyzeVariablesAndExternalReferences(ast, parserOptions)
1161+
const scope = analyzeVariablesAndExternalReferences(
1162+
result,
1163+
parserOptions,
1164+
)
11521165
const references = scope.references
11531166
const variables = scope.variables
11541167
const firstParam = first(params)!

‎src/script/scope-analyzer.ts

Copy file name to clipboardExpand all lines: src/script/scope-analyzer.ts
+20-10Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import { getFallbackKeys } from "../ast"
1515
import { getEslintScope } from "../common/eslint-scope"
1616
import { getEcmaVersionIfUseEspree } from "../common/espree"
1717

18+
type ParserResult = {
19+
ast: ESLintProgram
20+
scopeManager?: escopeTypes.ScopeManager
21+
}
22+
1823
/**
1924
* Check whether the given reference is unique in the belonging array.
2025
* @param reference The current reference to check.
@@ -54,6 +59,8 @@ function transformReference(reference: escopeTypes.Reference): Reference {
5459
? "w"
5560
: /* otherwise */ "rw",
5661
variable: null,
62+
isValueReference: reference.isValueReference,
63+
isTypeReference: reference.isTypeReference,
5764
}
5865
Object.defineProperty(ret, "variable", { enumerable: false })
5966

@@ -106,40 +113,43 @@ export function analyzeScope(
106113
}
107114

108115
/**
109-
*
110-
* @param ast
116+
* Analyze the scope of the given AST.
117+
* @param {ParserResult} parserResult The parser result to analyze.
111118
* @param parserOptions
112119
*/
113120
function analyze(
114-
ast: ESLintProgram,
121+
parserResult: ParserResult,
115122
parserOptions: ParserOptions,
116123
): escopeTypes.Scope {
117-
return analyzeScope(ast, parserOptions).globalScope
124+
const scopeManager =
125+
parserResult.scopeManager ||
126+
analyzeScope(parserResult.ast, parserOptions)
127+
return scopeManager.globalScope
118128
}
119129

120130
/**
121131
* Analyze the external references of the given AST.
122-
* @param {ASTNode} ast The root node to analyze.
132+
* @param {ParserResult} parserResult The parser result to analyze.
123133
* @returns {Reference[]} The reference objects of external references.
124134
*/
125135
export function analyzeExternalReferences(
126-
ast: ESLintProgram,
136+
parserResult: ParserResult,
127137
parserOptions: ParserOptions,
128138
): Reference[] {
129-
const scope = analyze(ast, parserOptions)
139+
const scope = analyze(parserResult, parserOptions)
130140
return scope.through.filter(isUnique).map(transformReference)
131141
}
132142

133143
/**
134144
* Analyze the external references of the given AST.
135-
* @param {ASTNode} ast The root node to analyze.
145+
* @param {ParserResult} parserResult The parser result to analyze.
136146
* @returns {Reference[]} The reference objects of external references.
137147
*/
138148
export function analyzeVariablesAndExternalReferences(
139-
ast: ESLintProgram,
149+
parserResult: ParserResult,
140150
parserOptions: ParserOptions,
141151
): { variables: Variable[]; references: Reference[] } {
142-
const scope = analyze(ast, parserOptions)
152+
const scope = analyze(parserResult, parserOptions)
143153
return {
144154
variables: getForScope(scope)
145155
.variables.filter(hasDefinition)

‎test/fixtures/ast/parser-option-multiple-parsers-1/ast.json

Copy file name to clipboardExpand all lines: test/fixtures/ast/parser-option-multiple-parsers-1/ast.json
+52-2Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,9 @@
656656
}
657657
}
658658
},
659-
"mode": "r"
659+
"mode": "r",
660+
"isValueReference": true,
661+
"isTypeReference": false
660662
},
661663
{
662664
"id": {
@@ -677,7 +679,55 @@
677679
}
678680
}
679681
},
680-
"mode": "r"
682+
"mode": "r",
683+
"isValueReference": true,
684+
"isTypeReference": false
685+
},
686+
{
687+
"id": {
688+
"type": "Identifier",
689+
"name": "b",
690+
"range": [
691+
17,
692+
18
693+
],
694+
"loc": {
695+
"start": {
696+
"line": 2,
697+
"column": 6
698+
},
699+
"end": {
700+
"line": 2,
701+
"column": 7
702+
}
703+
}
704+
},
705+
"mode": "r",
706+
"isValueReference": false,
707+
"isTypeReference": true
708+
},
709+
{
710+
"id": {
711+
"type": "Identifier",
712+
"name": "c",
713+
"range": [
714+
19,
715+
20
716+
],
717+
"loc": {
718+
"start": {
719+
"line": 2,
720+
"column": 8
721+
},
722+
"end": {
723+
"line": 2,
724+
"column": 9
725+
}
726+
}
727+
},
728+
"mode": "r",
729+
"isValueReference": false,
730+
"isTypeReference": true
681731
}
682732
]
683733
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.