diff --git a/src/ast/nodes.ts b/src/ast/nodes.ts
index 86e67990..104255fe 100644
--- a/src/ast/nodes.ts
+++ b/src/ast/nodes.ts
@@ -753,6 +753,10 @@ export interface Reference {
id: ESLintIdentifier
mode: "rw" | "r" | "w"
variable: Variable | null
+
+ // For typescript-eslint
+ isValueReference?: boolean
+ isTypeReference?: boolean
}
/**
diff --git a/src/script-setup/scope-analyzer.ts b/src/script-setup/scope-analyzer.ts
index 0d77fd22..e4f892a5 100644
--- a/src/script-setup/scope-analyzer.ts
+++ b/src/script-setup/scope-analyzer.ts
@@ -1,6 +1,7 @@
import type * as escopeTypes from "eslint-scope"
import type { ParserOptions } from "../common/parser-options"
import type {
+ Reference,
VAttribute,
VDirective,
VDocumentFragment,
@@ -169,7 +170,17 @@ function analyzeUsedInTemplateVariables(
return false
}
- function markVariableAsUsed(name: string) {
+ function markVariableAsUsed(nameOrRef: string | Reference) {
+ let name: string
+ let isValueReference: boolean | undefined
+ let isTypeReference: boolean | undefined
+ if (typeof nameOrRef === "string") {
+ name = nameOrRef
+ } else {
+ name = nameOrRef.id.name
+ isValueReference = nameOrRef.isValueReference
+ isTypeReference = nameOrRef.isTypeReference
+ }
const variable = scriptVariables.get(name)
if (!variable || variable.identifiers.length === 0) {
return
@@ -188,7 +199,9 @@ function analyzeUsedInTemplateVariables(
reference.isRead = () => true
reference.isReadOnly = () => true
reference.isReadWrite = () => false
- reference.isValueReference = true // For typescript-eslint
+ // For typescript-eslint
+ reference.isValueReference = isValueReference
+ reference.isTypeReference = isTypeReference
variable.references.push(reference)
reference.resolved = variable
@@ -198,7 +211,7 @@ function analyzeUsedInTemplateVariables(
for (const reference of node.references.filter(
(ref) => ref.variable == null,
)) {
- markVariableAsUsed(reference.id.name)
+ markVariableAsUsed(reference)
}
}
diff --git a/src/script/index.ts b/src/script/index.ts
index a2e9d14e..62cd8708 100644
--- a/src/script/index.ts
+++ b/src/script/index.ts
@@ -340,14 +340,15 @@ function parseExpressionBody(
debug('[script] parse expression: "0(%s)"', code)
try {
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`0(${code})`,
locationCalculator.getSubCalculatorShift(-2),
parserOptions,
- ).ast
+ )
+ const { ast } = result
const tokens = ast.tokens || []
const comments = ast.comments || []
- const references = analyzeExternalReferences(ast, parserOptions)
+ const references = analyzeExternalReferences(result, parserOptions)
const statement = ast.body[0] as ESLintExpressionStatement
const callExpression = statement.expression as ESLintCallExpression
const expression = callExpression.arguments[0]
@@ -461,13 +462,14 @@ function parseFilter(
// Parse the arguments.
if (argsCode != null) {
- const { ast } = parseScriptFragment(
+ const result = parseScriptFragment(
`0${argsCode}`,
locationCalculator
.getSubCalculatorAfter(paren)
.getSubCalculatorShift(-1),
parserOptions,
)
+ const { ast } = result
const statement = ast.body[0] as ESLintExpressionStatement
const callExpression = statement.expression
@@ -501,7 +503,7 @@ function parseFilter(
}
tokens.push(...ast.tokens!)
comments.push(...ast.comments!)
- references.push(...analyzeExternalReferences(ast, parserOptions))
+ references.push(...analyzeExternalReferences(result, parserOptions))
}
// Update range.
@@ -755,16 +757,20 @@ export function parseVForExpression(
processed.iterator,
)
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`for(let ${processed.aliasesWithBrackets}${processed.delimiter}${processed.iterator});`,
locationCalculator.getSubCalculatorShift(
processed.hasParens ? -8 : -9,
),
parserOptions,
- ).ast
+ )
+ const { ast } = result
const tokens = ast.tokens || []
const comments = ast.comments || []
- const scope = analyzeVariablesAndExternalReferences(ast, parserOptions)
+ const scope = analyzeVariablesAndExternalReferences(
+ result,
+ parserOptions,
+ )
const references = scope.references
const variables = scope.variables
const statement = ast.body[0] as
@@ -934,14 +940,15 @@ function parseVForAliasesForEcmaVersion5(
locationCalculator: LocationCalculatorForHtml,
parserOptions: ParserOptions,
) {
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`0(${code})`,
locationCalculator.getSubCalculatorShift(-2),
parserOptions,
- ).ast
+ )
+ const { ast } = result
const tokens = ast.tokens || []
const comments = ast.comments || []
- const variables = analyzeExternalReferences(ast, parserOptions).map(
+ const variables = analyzeExternalReferences(result, parserOptions).map(
transformVariable,
)
@@ -984,14 +991,15 @@ function parseVForIteratorForEcmaVersion5(
locationCalculator: LocationCalculatorForHtml,
parserOptions: ParserOptions,
) {
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`0(${code})`,
locationCalculator.getSubCalculatorShift(-2),
parserOptions,
- ).ast
+ )
+ const { ast } = result
const tokens = ast.tokens || []
const comments = ast.comments || []
- const references = analyzeExternalReferences(ast, parserOptions)
+ const references = analyzeExternalReferences(result, parserOptions)
const statement = ast.body[0] as ESLintExpressionStatement
const callExpression = statement.expression as ESLintCallExpression
@@ -1049,12 +1057,13 @@ function parseVOnExpressionBody(
}
try {
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`void function($event){${code}}`,
locationCalculator.getSubCalculatorShift(-22),
parserOptions,
- ).ast
- const references = analyzeExternalReferences(ast, parserOptions)
+ )
+ const { ast } = result
+ const references = analyzeExternalReferences(result, parserOptions)
const outermostStatement = ast.body[0] as ESLintExpressionStatement
const functionDecl = (
outermostStatement.expression as ESLintUnaryExpression
@@ -1126,11 +1135,12 @@ export function parseSlotScopeExpression(
}
try {
- const ast = parseScriptFragment(
+ const result = parseScriptFragment(
`void function(${code}) {}`,
locationCalculator.getSubCalculatorShift(-14),
parserOptions,
- ).ast
+ )
+ const { ast } = result
const statement = ast.body[0] as ESLintExpressionStatement
const rawExpression = statement.expression as ESLintUnaryExpression
const functionDecl = rawExpression.argument as ESLintFunctionExpression
@@ -1148,7 +1158,10 @@ export function parseSlotScopeExpression(
const tokens = ast.tokens || []
const comments = ast.comments || []
- const scope = analyzeVariablesAndExternalReferences(ast, parserOptions)
+ const scope = analyzeVariablesAndExternalReferences(
+ result,
+ parserOptions,
+ )
const references = scope.references
const variables = scope.variables
const firstParam = first(params)!
diff --git a/src/script/scope-analyzer.ts b/src/script/scope-analyzer.ts
index 369dbdb3..38de19f1 100644
--- a/src/script/scope-analyzer.ts
+++ b/src/script/scope-analyzer.ts
@@ -15,6 +15,11 @@ import { getFallbackKeys } from "../ast"
import { getEslintScope } from "../common/eslint-scope"
import { getEcmaVersionIfUseEspree } from "../common/espree"
+type ParserResult = {
+ ast: ESLintProgram
+ scopeManager?: escopeTypes.ScopeManager
+}
+
/**
* Check whether the given reference is unique in the belonging array.
* @param reference The current reference to check.
@@ -54,6 +59,8 @@ function transformReference(reference: escopeTypes.Reference): Reference {
? "w"
: /* otherwise */ "rw",
variable: null,
+ isValueReference: reference.isValueReference,
+ isTypeReference: reference.isTypeReference,
}
Object.defineProperty(ret, "variable", { enumerable: false })
@@ -106,40 +113,43 @@ export function analyzeScope(
}
/**
- *
- * @param ast
+ * Analyze the scope of the given AST.
+ * @param {ParserResult} parserResult The parser result to analyze.
* @param parserOptions
*/
function analyze(
- ast: ESLintProgram,
+ parserResult: ParserResult,
parserOptions: ParserOptions,
): escopeTypes.Scope {
- return analyzeScope(ast, parserOptions).globalScope
+ const scopeManager =
+ parserResult.scopeManager ||
+ analyzeScope(parserResult.ast, parserOptions)
+ return scopeManager.globalScope
}
/**
* Analyze the external references of the given AST.
- * @param {ASTNode} ast The root node to analyze.
+ * @param {ParserResult} parserResult The parser result to analyze.
* @returns {Reference[]} The reference objects of external references.
*/
export function analyzeExternalReferences(
- ast: ESLintProgram,
+ parserResult: ParserResult,
parserOptions: ParserOptions,
): Reference[] {
- const scope = analyze(ast, parserOptions)
+ const scope = analyze(parserResult, parserOptions)
return scope.through.filter(isUnique).map(transformReference)
}
/**
* Analyze the external references of the given AST.
- * @param {ASTNode} ast The root node to analyze.
+ * @param {ParserResult} parserResult The parser result to analyze.
* @returns {Reference[]} The reference objects of external references.
*/
export function analyzeVariablesAndExternalReferences(
- ast: ESLintProgram,
+ parserResult: ParserResult,
parserOptions: ParserOptions,
): { variables: Variable[]; references: Reference[] } {
- const scope = analyze(ast, parserOptions)
+ const scope = analyze(parserResult, parserOptions)
return {
variables: getForScope(scope)
.variables.filter(hasDefinition)
diff --git a/test/fixtures/ast/parser-option-multiple-parsers-1/ast.json b/test/fixtures/ast/parser-option-multiple-parsers-1/ast.json
index 97d900ed..e4419dca 100644
--- a/test/fixtures/ast/parser-option-multiple-parsers-1/ast.json
+++ b/test/fixtures/ast/parser-option-multiple-parsers-1/ast.json
@@ -656,7 +656,9 @@
}
}
},
- "mode": "r"
+ "mode": "r",
+ "isValueReference": true,
+ "isTypeReference": false
},
{
"id": {
@@ -677,7 +679,55 @@
}
}
},
- "mode": "r"
+ "mode": "r",
+ "isValueReference": true,
+ "isTypeReference": false
+ },
+ {
+ "id": {
+ "type": "Identifier",
+ "name": "b",
+ "range": [
+ 17,
+ 18
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 6
+ },
+ "end": {
+ "line": 2,
+ "column": 7
+ }
+ }
+ },
+ "mode": "r",
+ "isValueReference": false,
+ "isTypeReference": true
+ },
+ {
+ "id": {
+ "type": "Identifier",
+ "name": "c",
+ "range": [
+ 19,
+ 20
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 8
+ },
+ "end": {
+ "line": 2,
+ "column": 9
+ }
+ }
+ },
+ "mode": "r",
+ "isValueReference": false,
+ "isTypeReference": true
}
]
},
diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json
index b7deda38..8ad44185 100644
--- a/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json
+++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json
@@ -275,7 +275,9 @@
}
}
},
- "mode": "r"
+ "mode": "r",
+ "isValueReference": true,
+ "isTypeReference": false
},
{
"id": {
@@ -296,7 +298,55 @@
}
}
},
- "mode": "r"
+ "mode": "r",
+ "isValueReference": true,
+ "isTypeReference": false
+ },
+ {
+ "id": {
+ "type": "Identifier",
+ "name": "b",
+ "range": [
+ 17,
+ 18
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 6
+ },
+ "end": {
+ "line": 2,
+ "column": 7
+ }
+ }
+ },
+ "mode": "r",
+ "isValueReference": false,
+ "isTypeReference": true
+ },
+ {
+ "id": {
+ "type": "Identifier",
+ "name": "c",
+ "range": [
+ 19,
+ 20
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 8
+ },
+ "end": {
+ "line": 2,
+ "column": 9
+ }
+ }
+ },
+ "mode": "r",
+ "isValueReference": false,
+ "isTypeReference": true
}
]
},
diff --git a/test/fixtures/ast/ts-script-setup-with-use-global-var/ast.json b/test/fixtures/ast/ts-script-setup-with-use-global-var/ast.json
index b86e69af..6d83d037 100644
--- a/test/fixtures/ast/ts-script-setup-with-use-global-var/ast.json
+++ b/test/fixtures/ast/ts-script-setup-with-use-global-var/ast.json
@@ -357,7 +357,9 @@
}
}
},
- "mode": "r"
+ "mode": "r",
+ "isValueReference": true,
+ "isTypeReference": false
}
]
},
diff --git a/test/fixtures/ast/ts-script-setup-with-use-global-var/scope.json b/test/fixtures/ast/ts-script-setup-with-use-global-var/scope.json
index 80bdb3dd..d82fa33c 100644
--- a/test/fixtures/ast/ts-script-setup-with-use-global-var/scope.json
+++ b/test/fixtures/ast/ts-script-setup-with-use-global-var/scope.json
@@ -1,6 +1,90 @@
{
"type": "global",
"variables": [
+ {
+ "name": "ClassMemberDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "DecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassMethodDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassGetterDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassSetterDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassAccessorDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassAccessorDecoratorTarget",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassAccessorDecoratorResult",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassFieldDecoratorContext",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ClassDecorator",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "PropertyDecorator",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "MethodDecorator",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "ParameterDecorator",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
{
"name": "Symbol",
"identifiers": [],
@@ -301,30 +385,6 @@
"defs": [],
"references": []
},
- {
- "name": "ClassDecorator",
- "identifiers": [],
- "defs": [],
- "references": []
- },
- {
- "name": "PropertyDecorator",
- "identifiers": [],
- "defs": [],
- "references": []
- },
- {
- "name": "MethodDecorator",
- "identifiers": [],
- "defs": [],
- "references": []
- },
- {
- "name": "ParameterDecorator",
- "identifiers": [],
- "defs": [],
- "references": []
- },
{
"name": "PromiseConstructorLike",
"identifiers": [],
diff --git a/test/fixtures/integrations/script-setup-with-typescript-eslint/consistent-type-imports/valid-type-import.vue b/test/fixtures/integrations/script-setup-with-typescript-eslint/consistent-type-imports/valid-type-import.vue
new file mode 100644
index 00000000..c1c451fc
--- /dev/null
+++ b/test/fixtures/integrations/script-setup-with-typescript-eslint/consistent-type-imports/valid-type-import.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/typings/eslint-scope/index.d.ts b/typings/eslint-scope/index.d.ts
index c3ae32b5..6d14afcf 100644
--- a/typings/eslint-scope/index.d.ts
+++ b/typings/eslint-scope/index.d.ts
@@ -75,8 +75,8 @@ export class Reference {
public isWriteOnly(): boolean
// For typescript-eslint
- public isTypeReference: boolean
- public isValueReference: boolean
+ public isTypeReference?: boolean
+ public isValueReference?: boolean
}
export declare const analyze: (