From 8fef4ca3631eb03c1f113de244b33c4c684169ab Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Wed, 5 Mar 2025 22:58:24 +0900 Subject: [PATCH 01/14] Fix wrong scope for generic attribute (#254) * Fix wrong scope for generic attribute * update --- src/script/generic.ts | 9 +- .../define-model05-with-modifiers/ast.json | 4 +- test/fixtures/ast/multiple-scripts-5/ast.json | 3 +- test/fixtures/ast/multiple-scripts-6/ast.json | 3 +- test/fixtures/ast/multiple-scripts-7/ast.json | 3 +- test/fixtures/ast/multiple-scripts-8/ast.json | 3 +- .../multiple-scripts-with-export01/ast.json | 3 +- .../multiple-scripts-with-export02/ast.json | 12 +- .../multiple-scripts-with-export04/ast.json | 12 +- test/fixtures/ast/multiple-scripts/ast.json | 3 +- .../ast/script-setup-example13/ast.json | 8 +- .../ast/script-setup-example14/ast.json | 3 +- .../ast/script-setup-with-export/ast.json | 3 +- .../ast/slot-scope-destructuring/ast.json | 8 +- .../ast.json | 4 +- .../ast.json | 4 +- .../ast.json | 12 +- .../ast/v-slot-default-shorthand/ast.json | 4 +- test/fixtures/ast/v-slot-default/ast.json | 4 +- .../ast/v-slot-named-shorthand/ast.json | 4 +- test/fixtures/ast/v-slot-named/ast.json | 4 +- test/fixtures/ast/vue3.3-generic-3/scope.json | 155 ++++-------------- 22 files changed, 95 insertions(+), 173 deletions(-) diff --git a/src/script/generic.ts b/src/script/generic.ts index baf96955..5509062d 100644 --- a/src/script/generic.ts +++ b/src/script/generic.ts @@ -94,7 +94,8 @@ export function extractGeneric(element: VElement): GenericProcessInfo | null { typeDefScope: Scope, isRemoveTarget: (nodeOrToken: HasLocation) => boolean, ) { - for (const variable of typeDefScope.variables) { + // eslint-disable-next-line unicorn/no-useless-spread -- The original array is mutated + for (const variable of [...typeDefScope.variables]) { let def = variable.defs.find((d) => isRemoveTarget(d.name as HasLocation), ) @@ -105,13 +106,15 @@ export function extractGeneric(element: VElement): GenericProcessInfo | null { ) } } - for (const reference of typeDefScope.references) { + // eslint-disable-next-line unicorn/no-useless-spread -- The original array is mutated + for (const reference of [...typeDefScope.references]) { if (isRemoveTarget(reference.identifier as HasLocation)) { removeReference(reference, typeDefScope) } } - for (const scope of scopeManager.scopes) { + // eslint-disable-next-line unicorn/no-useless-spread -- The original array is mutated + for (const scope of [...scopeManager.scopes]) { if (isRemoveTarget(scope.block as HasLocation)) { removeScope(scopeManager, scope) } diff --git a/test/fixtures/ast/define-model05-with-modifiers/ast.json b/test/fixtures/ast/define-model05-with-modifiers/ast.json index fc25e5f3..55f8d42e 100644 --- a/test/fixtures/ast/define-model05-with-modifiers/ast.json +++ b/test/fixtures/ast/define-model05-with-modifiers/ast.json @@ -214,7 +214,6 @@ ], "name": "set" }, - "kind": "init", "value": { "type": "FunctionExpression", "start": 71, @@ -522,7 +521,8 @@ } ] } - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/multiple-scripts-5/ast.json b/test/fixtures/ast/multiple-scripts-5/ast.json index 6b026649..fd0cbb7d 100644 --- a/test/fixtures/ast/multiple-scripts-5/ast.json +++ b/test/fixtures/ast/multiple-scripts-5/ast.json @@ -118,7 +118,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "ImportDeclaration", diff --git a/test/fixtures/ast/multiple-scripts-6/ast.json b/test/fixtures/ast/multiple-scripts-6/ast.json index 06ab461d..4d97bdcb 100644 --- a/test/fixtures/ast/multiple-scripts-6/ast.json +++ b/test/fixtures/ast/multiple-scripts-6/ast.json @@ -260,7 +260,8 @@ "kind": "const" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] } ], "sourceType": "module", diff --git a/test/fixtures/ast/multiple-scripts-7/ast.json b/test/fixtures/ast/multiple-scripts-7/ast.json index eb6d9eae..ca60f41a 100644 --- a/test/fixtures/ast/multiple-scripts-7/ast.json +++ b/test/fixtures/ast/multiple-scripts-7/ast.json @@ -118,7 +118,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "ImportDeclaration", diff --git a/test/fixtures/ast/multiple-scripts-8/ast.json b/test/fixtures/ast/multiple-scripts-8/ast.json index 2fc13bc3..2055eb94 100644 --- a/test/fixtures/ast/multiple-scripts-8/ast.json +++ b/test/fixtures/ast/multiple-scripts-8/ast.json @@ -118,7 +118,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "VariableDeclaration", diff --git a/test/fixtures/ast/multiple-scripts-with-export01/ast.json b/test/fixtures/ast/multiple-scripts-with-export01/ast.json index 2b9018f4..9b0ae9fb 100644 --- a/test/fixtures/ast/multiple-scripts-with-export01/ast.json +++ b/test/fixtures/ast/multiple-scripts-with-export01/ast.json @@ -200,7 +200,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] } ], "sourceType": "module", diff --git a/test/fixtures/ast/multiple-scripts-with-export02/ast.json b/test/fixtures/ast/multiple-scripts-with-export02/ast.json index 0d545d97..cf673aae 100644 --- a/test/fixtures/ast/multiple-scripts-with-export02/ast.json +++ b/test/fixtures/ast/multiple-scripts-with-export02/ast.json @@ -364,7 +364,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "ImportDeclaration", @@ -914,7 +915,8 @@ } } ], - "source": null + "source": null, + "attributes": [] }, { "type": "ExportNamedDeclaration", @@ -1055,7 +1057,8 @@ } } ], - "source": null + "source": null, + "attributes": [] }, { "type": "ExportNamedDeclaration", @@ -1077,7 +1080,8 @@ ], "declaration": null, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "VariableDeclaration", diff --git a/test/fixtures/ast/multiple-scripts-with-export04/ast.json b/test/fixtures/ast/multiple-scripts-with-export04/ast.json index c7b5583d..cfbba14f 100644 --- a/test/fixtures/ast/multiple-scripts-with-export04/ast.json +++ b/test/fixtures/ast/multiple-scripts-with-export04/ast.json @@ -118,7 +118,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "ExportNamedDeclaration", @@ -221,7 +222,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "ImportDeclaration", @@ -467,7 +469,8 @@ } } ], - "source": null + "source": null, + "attributes": [] }, { "type": "ExportNamedDeclaration", @@ -570,7 +573,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] } ], "sourceType": "module", diff --git a/test/fixtures/ast/multiple-scripts/ast.json b/test/fixtures/ast/multiple-scripts/ast.json index bdaec0c7..0867d769 100644 --- a/test/fixtures/ast/multiple-scripts/ast.json +++ b/test/fixtures/ast/multiple-scripts/ast.json @@ -178,7 +178,8 @@ "kind": "const" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "VariableDeclaration", diff --git a/test/fixtures/ast/script-setup-example13/ast.json b/test/fixtures/ast/script-setup-example13/ast.json index 6a67da3b..8e2d4fe6 100644 --- a/test/fixtures/ast/script-setup-example13/ast.json +++ b/test/fixtures/ast/script-setup-example13/ast.json @@ -340,7 +340,6 @@ ], "name": "a" }, - "kind": "init", "value": { "type": "Identifier", "start": 62, @@ -360,7 +359,8 @@ 63 ], "name": "a" - } + }, + "kind": "init" }, { "type": "Property", @@ -403,7 +403,6 @@ ], "name": "b" }, - "kind": "init", "value": { "type": "Identifier", "start": 67, @@ -423,7 +422,8 @@ 68 ], "name": "b" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/script-setup-example14/ast.json b/test/fixtures/ast/script-setup-example14/ast.json index 03765608..288e20da 100644 --- a/test/fixtures/ast/script-setup-example14/ast.json +++ b/test/fixtures/ast/script-setup-example14/ast.json @@ -178,7 +178,8 @@ "kind": "const" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] }, { "type": "VariableDeclaration", diff --git a/test/fixtures/ast/script-setup-with-export/ast.json b/test/fixtures/ast/script-setup-with-export/ast.json index 932e9dd3..f97586b0 100644 --- a/test/fixtures/ast/script-setup-with-export/ast.json +++ b/test/fixtures/ast/script-setup-with-export/ast.json @@ -118,7 +118,8 @@ "kind": "let" }, "specifiers": [], - "source": null + "source": null, + "attributes": [] } ], "sourceType": "module", diff --git a/test/fixtures/ast/slot-scope-destructuring/ast.json b/test/fixtures/ast/slot-scope-destructuring/ast.json index bc1794e2..9ef5942d 100644 --- a/test/fixtures/ast/slot-scope-destructuring/ast.json +++ b/test/fixtures/ast/slot-scope-destructuring/ast.json @@ -319,7 +319,6 @@ ], "name": "a" }, - "kind": "init", "value": { "type": "Identifier", "start": 58, @@ -339,7 +338,8 @@ 59 ], "name": "a" - } + }, + "kind": "init" }, { "type": "Property", @@ -382,7 +382,6 @@ ], "name": "b" }, - "kind": "init", "value": { "type": "Identifier", "start": 61, @@ -402,7 +401,8 @@ 62 ], "name": "b" - } + }, + "kind": "init" }, { "type": "RestElement", diff --git a/test/fixtures/ast/v-bind-same-name-shorthand02-options/ast.json b/test/fixtures/ast/v-bind-same-name-shorthand02-options/ast.json index 84add60c..55f56637 100644 --- a/test/fixtures/ast/v-bind-same-name-shorthand02-options/ast.json +++ b/test/fixtures/ast/v-bind-same-name-shorthand02-options/ast.json @@ -95,7 +95,6 @@ ], "name": "data" }, - "kind": "init", "value": { "type": "FunctionExpression", "start": 33, @@ -244,7 +243,8 @@ } ] } - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-bind-same-name-shorthand04-with-v-for/ast.json b/test/fixtures/ast/v-bind-same-name-shorthand04-with-v-for/ast.json index 7a0ab7e5..05fdd689 100644 --- a/test/fixtures/ast/v-bind-same-name-shorthand04-with-v-for/ast.json +++ b/test/fixtures/ast/v-bind-same-name-shorthand04-with-v-for/ast.json @@ -95,7 +95,6 @@ ], "name": "data" }, - "kind": "init", "value": { "type": "FunctionExpression", "start": 33, @@ -286,7 +285,8 @@ } ] } - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-for-directives-with-destructuring/ast.json b/test/fixtures/ast/v-for-directives-with-destructuring/ast.json index ddf0f4c2..b6ede250 100644 --- a/test/fixtures/ast/v-for-directives-with-destructuring/ast.json +++ b/test/fixtures/ast/v-for-directives-with-destructuring/ast.json @@ -262,7 +262,6 @@ ], "name": "key" }, - "kind": "init", "value": { "type": "Identifier", "start": 28, @@ -282,7 +281,8 @@ 31 ], "name": "key" - } + }, + "kind": "init" }, { "type": "Property", @@ -325,7 +325,6 @@ ], "name": "name" }, - "kind": "init", "value": { "type": "Identifier", "start": 32, @@ -345,7 +344,8 @@ 36 ], "name": "name" - } + }, + "kind": "init" } ] } @@ -1460,7 +1460,6 @@ ], "name": "name" }, - "kind": "init", "value": { "type": "Identifier", "start": 163, @@ -1480,7 +1479,8 @@ 167 ], "name": "name" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-slot-default-shorthand/ast.json b/test/fixtures/ast/v-slot-default-shorthand/ast.json index 1298f1e8..fc107094 100644 --- a/test/fixtures/ast/v-slot-default-shorthand/ast.json +++ b/test/fixtures/ast/v-slot-default-shorthand/ast.json @@ -280,7 +280,6 @@ ], "name": "foo" }, - "kind": "init", "value": { "type": "Identifier", "start": 43, @@ -300,7 +299,8 @@ 46 ], "name": "foo" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-slot-default/ast.json b/test/fixtures/ast/v-slot-default/ast.json index 835b83b8..38fcf4da 100644 --- a/test/fixtures/ast/v-slot-default/ast.json +++ b/test/fixtures/ast/v-slot-default/ast.json @@ -262,7 +262,6 @@ ], "name": "foo" }, - "kind": "init", "value": { "type": "Identifier", "start": 41, @@ -282,7 +281,8 @@ 44 ], "name": "foo" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-slot-named-shorthand/ast.json b/test/fixtures/ast/v-slot-named-shorthand/ast.json index a6a99b82..f7004d68 100644 --- a/test/fixtures/ast/v-slot-named-shorthand/ast.json +++ b/test/fixtures/ast/v-slot-named-shorthand/ast.json @@ -337,7 +337,6 @@ ], "name": "foo" }, - "kind": "init", "value": { "type": "Identifier", "start": 61, @@ -357,7 +356,8 @@ 64 ], "name": "foo" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/v-slot-named/ast.json b/test/fixtures/ast/v-slot-named/ast.json index dcc9961d..1c337d08 100644 --- a/test/fixtures/ast/v-slot-named/ast.json +++ b/test/fixtures/ast/v-slot-named/ast.json @@ -337,7 +337,6 @@ ], "name": "foo" }, - "kind": "init", "value": { "type": "Identifier", "start": 67, @@ -357,7 +356,8 @@ 70 ], "name": "foo" - } + }, + "kind": "init" } ] } diff --git a/test/fixtures/ast/vue3.3-generic-3/scope.json b/test/fixtures/ast/vue3.3-generic-3/scope.json index fb10e250..01a2cda1 100644 --- a/test/fixtures/ast/vue3.3-generic-3/scope.json +++ b/test/fixtures/ast/vue3.3-generic-3/scope.json @@ -1160,28 +1160,35 @@ "references": [] }, { - "name": "T", + "name": "defineProps", "identifiers": [], "defs": [], "references": [ { "identifier": { "type": "Identifier", - "name": "T", + "name": "defineProps", "loc": { "end": { - "column": 11, - "line": 8 + "line": 5, + "column": 21 }, "start": { - "column": 10, - "line": 8 + "line": 5, + "column": 10 } } }, "from": "module", "init": null - }, + } + ] + }, + { + "name": "T", + "identifiers": [], + "defs": [], + "references": [ { "identifier": { "type": "Identifier", @@ -1203,22 +1210,22 @@ ] }, { - "name": "defineProps", + "name": "U", "identifiers": [], "defs": [], "references": [ { "identifier": { "type": "Identifier", - "name": "defineProps", + "name": "U", "loc": { "end": { "line": 5, - "column": 21 + "column": 36 }, "start": { "line": 5, - "column": 10 + "column": 35 } } }, @@ -1306,78 +1313,6 @@ } ] }, - { - "name": "U", - "identifiers": [ - { - "type": "Identifier", - "name": "U", - "loc": { - "end": { - "column": 6, - "line": 8 - }, - "start": { - "column": 5, - "line": 8 - } - } - } - ], - "defs": [ - { - "type": "Type", - "node": { - "type": "TSTypeAliasDeclaration", - "loc": { - "end": { - "column": 1, - "line": 9 - }, - "start": { - "column": 0, - "line": 8 - } - } - }, - "name": "U" - } - ], - "references": [ - { - "identifier": { - "type": "Identifier", - "name": "U", - "loc": { - "end": { - "line": 5, - "column": 36 - }, - "start": { - "line": 5, - "column": 35 - } - } - }, - "from": "module", - "resolved": { - "type": "Identifier", - "name": "U", - "loc": { - "end": { - "column": 6, - "line": 8 - }, - "start": { - "column": 5, - "line": 8 - } - } - }, - "init": null - } - ] - }, { "name": "p", "identifiers": [ @@ -1621,24 +1556,6 @@ } ], "references": [ - { - "identifier": { - "type": "Identifier", - "name": "T", - "loc": { - "end": { - "column": 11, - "line": 8 - }, - "start": { - "column": 10, - "line": 8 - } - } - }, - "from": "module", - "init": null - }, { "identifier": { "type": "Identifier", @@ -1723,20 +1640,6 @@ } }, "from": "module", - "resolved": { - "type": "Identifier", - "name": "U", - "loc": { - "end": { - "column": 6, - "line": 8 - }, - "start": { - "column": 5, - "line": 8 - } - } - }, "init": null }, { @@ -1860,15 +1763,15 @@ { "identifier": { "type": "Identifier", - "name": "T", + "name": "defineProps", "loc": { "end": { - "column": 11, - "line": 8 + "line": 5, + "column": 21 }, "start": { - "column": 10, - "line": 8 + "line": 5, + "column": 10 } } }, @@ -1878,15 +1781,15 @@ { "identifier": { "type": "Identifier", - "name": "defineProps", + "name": "T", "loc": { "end": { "line": 5, - "column": 21 + "column": 28 }, "start": { "line": 5, - "column": 10 + "column": 27 } } }, @@ -1896,15 +1799,15 @@ { "identifier": { "type": "Identifier", - "name": "T", + "name": "U", "loc": { "end": { "line": 5, - "column": 28 + "column": 36 }, "start": { "line": 5, - "column": 27 + "column": 35 } } }, From 9574d91be036d050f058485a8a73fd2eea17b5fe Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Wed, 5 Mar 2025 22:59:05 +0900 Subject: [PATCH 02/14] 10.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c449c660..500d3790 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-eslint-parser", - "version": "10.1.0", + "version": "10.1.1", "description": "The ESLint custom parser for `.vue` files.", "main": "index.js", "files": [ From 5712b7f6d2b5a0fbccd949ec540caa36667b7b70 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Mon, 31 Mar 2025 17:06:34 -0700 Subject: [PATCH 03/14] Update README.md (#259) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b4d1a580..f3273b1e 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,7 @@ See [implementing-custom-template-tokenizers.md](./docs/implementing-custom-temp - `defineDocumentVisitor(documentVisitor, options)` ... returns ESLint visitor to traverses the document. - [ast.md](./docs/ast.md) is `` const result = parseForESLint(code, { sourceType: "module" }) - const comments = result.ast.comments + const comments = result.ast.comments! // Should have 2 comments assert.strictEqual(comments.length, 2) @@ -937,7 +945,7 @@ export default {} }) }) -function buildPlugins(rule) { +function buildPlugins(rule: Rule.RuleModule) { return { test: { rules: { diff --git a/test/integrations.js b/test/integrations.test.ts similarity index 67% rename from test/integrations.js rename to test/integrations.test.ts index 88e9c501..651e6616 100644 --- a/test/integrations.js +++ b/test/integrations.test.ts @@ -2,16 +2,18 @@ // Requirements //------------------------------------------------------------------------------ -const assert = require("assert") -const path = require("path") -const fs = require("fs-extra") -const cp = require("child_process") -const eslintCompat = require("./lib/eslint-compat") +import { assert, beforeAll, describe, it } from "vitest" +import path from "node:path" +import fs from "node:fs" +import cp from "child_process" +import eslintCompat from "./lib/eslint-compat" +import ESLintRaw from "eslint" //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ +// eslint-disable-next-line no-undef const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") //------------------------------------------------------------------------------ @@ -19,15 +21,19 @@ const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") //------------------------------------------------------------------------------ describe("Integration tests", () => { + beforeAll(async () => { + await import("ts-node/register") + }) for (const target of fs.readdirSync(FIXTURE_DIR)) { it(target, async () => { - let ESLint = eslintCompat(require("eslint")).ESLint + let ESLint = eslintCompat(ESLintRaw).ESLint if (fs.existsSync(path.join(FIXTURE_DIR, target, "package.json"))) { const originalCwd = process.cwd() try { process.chdir(path.join(FIXTURE_DIR, target)) cp.execSync("npm i", { stdio: "inherit" }) ESLint = eslintCompat( + // eslint-disable-next-line @typescript-eslint/no-require-imports require( path.join( FIXTURE_DIR, @@ -46,7 +52,7 @@ describe("Integration tests", () => { }) const report = await cli.lintFiles(["**/*.vue"]) - const outputPath = path.join(FIXTURE_DIR, target, `output.json`) + const outputPath = path.join(FIXTURE_DIR, target, "output.json") const expected = JSON.parse(fs.readFileSync(outputPath, "utf8")) try { assert.deepStrictEqual( @@ -59,7 +65,7 @@ describe("Integration tests", () => { const actualPath = path.join( FIXTURE_DIR, target, - `_actual.json`, + "_actual.json", ) fs.writeFileSync( actualPath, @@ -69,25 +75,24 @@ describe("Integration tests", () => { throw e } - function normalizeReport(report, option = {}) { - return report + function normalizeReport( + result: ESLintRaw.ESLint.LintResult[], + option: { withoutMessage?: boolean } = {}, + ) { + return result .filter((res) => res.messages.length) - .map((res) => { - return { - filePath: res.filePath - .replace(cwd, "") - .replace(/\\/gu, "/"), - messages: res.messages.map((msg) => { - return { - ruleId: msg.ruleId, - line: msg.line, - ...(option.withoutMessage - ? {} - : { message: msg.message }), - } - }), - } - }) + .map((res) => ({ + filePath: res.filePath + .replace(cwd, "") + .replace(/\\/gu, "/"), + messages: res.messages.map((msg) => ({ + ruleId: msg.ruleId, + line: msg.line, + ...(option.withoutMessage + ? {} + : { message: msg.message }), + })), + })) .sort((a, b) => a.filePath < b.filePath ? -1 diff --git a/test/lib/eslint-compat.js b/test/lib/eslint-compat.ts similarity index 60% rename from test/lib/eslint-compat.js rename to test/lib/eslint-compat.ts index 9077ec55..ae96362f 100644 --- a/test/lib/eslint-compat.js +++ b/test/lib/eslint-compat.ts @@ -1,11 +1,10 @@ -"use strict" +import type { ESLint, Linter, RuleTester } from "eslint" -/** - * @typedef {import('eslint')} eslint - */ - -/** @param {eslint} eslint */ -module.exports = function compat(eslint) { +export default function compat(eslint: any): { + ESLint: typeof ESLint + RuleTester: typeof RuleTester + Linter: typeof Linter +} { return { ESLint: eslint.ESLint || getESLintClassForV6(eslint), RuleTester: eslint.RuleTester, @@ -13,15 +12,17 @@ module.exports = function compat(eslint) { } } -/** @returns {typeof eslint.ESLint} */ -function getESLintClassForV6(eslint) { +function getESLintClassForV6(eslint: any): typeof ESLint { class ESLintForV6 { + public engine + + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility static get version() { return eslint.CLIEngine.version } - /** @param {eslint.ESLint.Options} options */ - constructor(options) { + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + constructor(options: any) { const { overrideConfig: { plugins, @@ -33,14 +34,13 @@ function getESLintClassForV6(eslint) { plugins: [], globals: {}, rules: {}, - }, + } as any, overrideConfigFile, fix, reportUnusedDisableDirectives, plugins: pluginsMap, ...otherOptions } = options || {} - /** @type {eslint.CLIEngine.Options} */ const newOptions = { fix: Boolean(fix), reportUnusedDisableDirectives: reportUnusedDisableDirectives @@ -64,7 +64,7 @@ function getESLintClassForV6(eslint) { } return o }, - /** @type {NonNullable} */ {}, + {} as Record, ) : undefined, ...overrideConfig, @@ -76,41 +76,37 @@ function getESLintClassForV6(eslint) { } } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - async lintText(...params) { - const result = this.engine.executeOnText( + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + async lintText( + ...params: Parameters + ): ReturnType { + const result = await this.engine.executeOnText( params[0], - params[1].filePath, + params[1]!.filePath, ) return result.results } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - async lintFiles(...params) { - const result = this.engine.executeOnFiles( + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + async lintFiles( + ...params: Parameters + ): ReturnType { + const result = await this.engine.executeOnFiles( Array.isArray(params[0]) ? params[0] : [params[0]], ) return result.results } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - static async outputFixes(...params) { - return eslint.CLIEngine.outputFixes({ + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + static async outputFixes( + ...params: Parameters + ): ReturnType { + // eslint-disable-next-line no-return-await + return await eslint.CLIEngine.outputFixes({ results: params[0], }) } } - /** @type {typeof eslint.ESLint} */ - const eslintClass = /** @type {any} */ ESLintForV6 - return eslintClass + return ESLintForV6 as any } diff --git a/test/parser-options-project.js b/test/parser-options-project.test.ts similarity index 93% rename from test/parser-options-project.js rename to test/parser-options-project.test.ts index 1fc3b12a..257f4ded 100644 --- a/test/parser-options-project.js +++ b/test/parser-options-project.test.ts @@ -1,8 +1,7 @@ -"use strict" - -const assert = require("assert") -const { parseForESLint } = require("../src") -const espree = require("espree") +import { describe, it, assert } from "vitest" +import { parseForESLint } from "../src" +import * as espree from "espree" +import type { Linter } from "eslint" describe("use `project: undefined` when parsing template script-let", () => { it("should be the project option is defined only once in Simple SFC.", () => { @@ -39,7 +38,7 @@ describe("use `project: undefined` when parsing template script-let", () => { ast: espree.parse(code, options), } }, - }, + } satisfies Linter.Parser, }, ) assert.strictEqual(projectCount, 1) @@ -83,7 +82,7 @@ describe("use `project: undefined` when parsing template script-let", () => { ast: espree.parse(code, options), } }, - }, + } satisfies Linter.Parser, }, ) assert.strictEqual(projectCount, 1) @@ -126,7 +125,7 @@ describe("use `project: undefined` when parsing template script-let", () => { ast: espree.parse(code, options), } }, - }, + } satisfies Linter.Parser, }, ) assert.strictEqual(projectCount, 1) diff --git a/test/parser-options.js b/test/parser-options.test.ts similarity index 86% rename from test/parser-options.js rename to test/parser-options.test.ts index 3c7e4e1b..37aa60a9 100644 --- a/test/parser-options.js +++ b/test/parser-options.test.ts @@ -2,18 +2,17 @@ * @author Toru Nagashima * See LICENSE file in root directory for full license. */ -"use strict" -const assert = require("assert") -const { parseForESLint } = require("../src") -const eslint = require("eslint") -const Linter = eslint.Linter +import { describe, it, assert } from "vitest" +import { parseForESLint } from "../src" +import type { ESLint } from "eslint" +import { Linter } from "eslint" describe("parserOptions", () => { describe("parser", () => { const linter = new Linter({ configType: "flat" }) - const parser = { parseForESLint } - const plugin = { + const parser: Linter.Parser = { parseForESLint } + const plugin: ESLint.Plugin = { rules: { "template-test": { create(context) { @@ -33,7 +32,7 @@ describe("parserOptions", () => { it("false then skip parsing '` - const config = { + const config: Linter.Config = { files: ["*.vue"], plugins: { vue: plugin, @@ -57,7 +56,7 @@ describe("parserOptions", () => { it("Fail in ` - const config = { + const config: Linter.Config = { files: ["*.vue"], plugins: { vue: plugin, diff --git a/test/test-utils.js b/test/test-utils.ts similarity index 68% rename from test/test-utils.js rename to test/test-utils.ts index 8ea0b760..f5305181 100644 --- a/test/test-utils.js +++ b/test/test-utils.ts @@ -1,14 +1,22 @@ -const escope = require("eslint-scope") - -module.exports = { replacer, getAllTokens, scopeToJSON, analyze } +import type { Identifier, Node } from "estree" +import type { + Scope, + ScopeManager, + Variable, + VariableDefinition, +} from "eslint-scope" +import type { ESLintProgram, Token } from "../src/ast" +import type { ParserOptions } from "../src/common/parser-options" +import * as escope from "eslint-scope" +import { getFallbackKeys } from "../src/ast" /** * Remove `parent` properties from the given AST. - * @param {string} key The key. - * @param {any} value The value of the key. - * @returns {any} The value of the key to output. + * @param key The key. + * @param value The value of the key. + * @returns The value of the key to output. */ -function replacer(key, value) { +export function replacer(key: string, value: any): any { if (key === "parent") { return undefined } @@ -25,10 +33,10 @@ function replacer(key, value) { /** * Get all tokens of the given AST. - * @param {ASTNode} ast The root node of AST. - * @returns {Token[]} Tokens. + * @param ast The root node of AST. + * @returns Tokens. */ -function getAllTokens(ast) { +export function getAllTokens(ast: ESLintProgram): Token[] { const tokenArrays = [ast.tokens, ast.comments] if (ast.templateBody != null) { tokenArrays.push(ast.templateBody.tokens, ast.templateBody.comments) @@ -36,10 +44,10 @@ function getAllTokens(ast) { return Array.prototype.concat.apply([], tokenArrays) } -function scopeToJSON(scopeManager) { +export function scopeToJSON(scopeManager: ScopeManager) { return JSON.stringify(normalizeScope(scopeManager.globalScope), replacer, 4) - function normalizeScope(scope) { + function normalizeScope(scope: Scope): any { return { type: scope.type, variables: scope.variables.map(normalizeVar), @@ -49,7 +57,7 @@ function scopeToJSON(scopeManager) { } } - function normalizeVar(v) { + function normalizeVar(v: Variable) { return { name: v.name, identifiers: v.identifiers.map(normalizeId), @@ -58,7 +66,7 @@ function scopeToJSON(scopeManager) { } } - function normalizeReference(reference) { + function normalizeReference(reference: any) { return { identifier: normalizeId(reference.identifier), from: reference.from.type, @@ -75,7 +83,7 @@ function scopeToJSON(scopeManager) { } } - function normalizeDef(def) { + function normalizeDef(def: VariableDefinition) { return { type: def.type, node: normalizeDefNode(def.node), @@ -83,7 +91,7 @@ function scopeToJSON(scopeManager) { } } - function normalizeId(identifier) { + function normalizeId(identifier: Identifier | null) { return ( identifier && { type: identifier.type, @@ -93,7 +101,7 @@ function scopeToJSON(scopeManager) { ) } - function normalizeDefNode(node) { + function normalizeDefNode(node: Node) { return { type: node.type, loc: node.loc, @@ -104,7 +112,10 @@ function scopeToJSON(scopeManager) { /** * Analyze scope */ -function analyze(ast, parserOptions) { +export function analyze( + ast: ESLintProgram, + parserOptions: ParserOptions, +): ScopeManager { const ecmaVersion = parserOptions.ecmaVersion ?? 2022 const ecmaFeatures = parserOptions.ecmaFeatures ?? {} const sourceType = parserOptions.sourceType ?? "script" @@ -118,23 +129,4 @@ function analyze(ast, parserOptions) { }) return result - - function getFallbackKeys(node) { - return Object.keys(node).filter(fallbackKeysFilter, node) - } - - function fallbackKeysFilter(key) { - const value = null - return ( - key !== "comments" && - key !== "leadingComments" && - key !== "loc" && - key !== "parent" && - key !== "range" && - key !== "tokens" && - key !== "trailingComments" && - typeof value === "object" && - (typeof value.type === "string" || Array.isArray(value)) - ) - } } diff --git a/test/tokens.js b/test/tokens.test.ts similarity index 70% rename from test/tokens.js rename to test/tokens.test.ts index de370298..b7133625 100644 --- a/test/tokens.js +++ b/test/tokens.test.ts @@ -3,14 +3,20 @@ * @copyright 2017 Toru Nagashima. All rights reserved. * See LICENSE file in root directory for full license. */ -"use strict" //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ -const assert = require("assert") -const parse = require("../src").parseForESLint +import type { + ESLintProgram, + Token, + VElement, + VExpressionContainer, +} from "../src/ast" +import type TokenStore from "../src/external/token-store" +import { assert, beforeAll, describe, it } from "vitest" +import { parseForESLint as parse } from "../src" //------------------------------------------------------------------------------ // Helpers @@ -26,10 +32,10 @@ const PARSER_OPTIONS = { /** * Get the value of the given node. - * @param {ASTNode} token The node to get value. - * @returns {string} The value of the node. + * @param token The node to get value. + * @returns The value of the node. */ -function toValue(token) { +function toValue(token: Token): string { if (token.type === "HTMLAssociation") { return "=" } @@ -48,18 +54,18 @@ describe("services.getTemplateBodyTokenStore", () => {
{{ message /*comment3*/ }}
` - let ast = null - let tokens = null + let ast: ESLintProgram | null = null + let tokens: TokenStore | null = null - before(() => { + beforeAll(() => { const result = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }) ast = result.ast - tokens = result.services.getTemplateBodyTokenStore() + tokens = result.services!.getTemplateBodyTokenStore() }) describe("ast.templateBody", () => { it("should return all tokens (except comments) in the template.", () => { - const actual = tokens.getTokens(ast.templateBody).map(toValue) + const actual = tokens!.getTokens(ast!.templateBody!).map(toValue) assert.deepStrictEqual(actual, [ "template", @@ -94,8 +100,8 @@ describe("services.getTemplateBodyTokenStore", () => { }) it("should return all tokens (include comments) in the template if you give {includeComments: true} option.", () => { - const actual = tokens - .getTokens(ast.templateBody, { includeComments: true }) + const actual = tokens! + .getTokens(ast!.templateBody!, { includeComments: true }) .map(toValue) assert.deepStrictEqual(actual, [ @@ -137,8 +143,8 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[0] (VText)", () => { it("should return a text token.", () => { - const node = ast.templateBody.children[0] - const actual = tokens.getTokens(node).map(toValue) + const node = ast!.templateBody!.children[0] + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["\n "]) }) @@ -146,8 +152,8 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2] (VElement)", () => { it("should return all tokens in the element.", () => { - const node = ast.templateBody.children[2] - const actual = tokens.getTokens(node).map(toValue) + const node = ast!.templateBody!.children[2] + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, [ "div", @@ -177,8 +183,8 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag (VStartTag)", () => { it("should return all tokens in the tag.", () => { - const node = ast.templateBody.children[2].startTag - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, [ "div", @@ -203,8 +209,9 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[0] (VAttribute)", () => { it("should return all tokens in the attribute.", () => { - const node = ast.templateBody.children[2].startTag.attributes[0] - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + .attributes[0] + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["a", "=", "b"]) }) @@ -212,8 +219,9 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[0].key (VIdentifier)", () => { it("should return the identifier token.", () => { - const node = ast.templateBody.children[2].startTag.attributes[0].key - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + .attributes[0].key + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["a"]) }) @@ -221,9 +229,9 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[0].value (VAttributeValue)", () => { it("should return the value token.", () => { - const node = - ast.templateBody.children[2].startTag.attributes[0].value - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + .attributes[0].value! + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["b"]) }) @@ -231,8 +239,9 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[1].key (VDirectiveKey)", () => { it("should return the identifier token.", () => { - const node = ast.templateBody.children[2].startTag.attributes[1].key - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + .attributes[1].key + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["v-show"]) }) @@ -240,9 +249,9 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[1].value (VExpressionContainer)", () => { it("should return all tokens in the value.", () => { - const node = - ast.templateBody.children[2].startTag.attributes[1].value - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).startTag + .attributes[1].value! + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, [ '"', @@ -260,10 +269,11 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].startTag.attributes[1].value.expression (BinaryExpression)", () => { it("should return all tokens in the expression.", () => { - const node = - ast.templateBody.children[2].startTag.attributes[1].value - .expression - const actual = tokens.getTokens(node).map(toValue) + const node = ( + (ast!.templateBody!.children[2] as VElement).startTag + .attributes[1].value as VExpressionContainer + ).expression! + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, [ "c", @@ -279,8 +289,8 @@ describe("services.getTemplateBodyTokenStore", () => { describe("ast.templateBody.children[2].endTag (VEndTag)", () => { it("should return all tokens in the tag.", () => { - const node = ast.templateBody.children[2].endTag - const actual = tokens.getTokens(node).map(toValue) + const node = (ast!.templateBody!.children[2] as VElement).endTag! + const actual = tokens!.getTokens(node).map(toValue) assert.deepStrictEqual(actual, ["div", ">"]) }) @@ -289,15 +299,13 @@ describe("services.getTemplateBodyTokenStore", () => { describe("TokenStore#get{Range,Loc}()", () => { it("should return loc and range.", () => { const { - templateBody: { - children: [node], - tokens: [token], - }, - } = ast - assert.equal(typeof tokens.getRange(node)[0], "number") - assert.equal(typeof tokens.getRange(token)[1], "number") - assert.equal(typeof tokens.getLoc(node).start.line, "number") - assert.equal(typeof tokens.getLoc(node).end.column, "number") + children: [node], + tokens: [token], + } = ast!.templateBody! + assert.equal(typeof tokens!.getRange(node)[0], "number") + assert.equal(typeof tokens!.getRange(token)[1], "number") + assert.equal(typeof tokens!.getLoc(node).start.line, "number") + assert.equal(typeof tokens!.getLoc(node).end.column, "number") }) }) }) diff --git a/test/variables-references.js b/test/variables-references.test.ts similarity index 53% rename from test/variables-references.js rename to test/variables-references.test.ts index 4e6a590b..e0a9e765 100644 --- a/test/variables-references.js +++ b/test/variables-references.test.ts @@ -3,14 +3,26 @@ * @copyright 2017 Toru Nagashima. All rights reserved. * See LICENSE file in root directory for full license. */ -"use strict" //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ -const assert = require("assert") -const parse = require("../src").parseForESLint +import type { + ESLintBinaryExpression, + ESLintCallExpression, + ESLintExpressionStatement, + ESLintProgram, + Reference, + Variable, + VDirective, + VElement, + VExpressionContainer, + VForExpression, + VOnExpression, +} from "../src/ast" +import { describe, it, assert, beforeAll } from "vitest" +import { parseForESLint as parse } from "../src" //------------------------------------------------------------------------------ // Helpers @@ -31,65 +43,82 @@ const PARSER_OPTIONS = { describe("[references] expression containers", () => { describe("in directives", () => { const code = '' - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should have references", () => { - const directive = - ast.templateBody.children[0].startTag.attributes[0] + const element = ast.templateBody!.children[0] as VElement + const directive = element.startTag.attributes[0] as VDirective assert(directive.key.type === "VDirectiveKey") - assert(directive.value.references != null) + assert(directive.value!.references != null) assert( - directive.value.references[0].id === - directive.value.expression.left, + directive.value!.references[0].id === + (directive.value!.expression as ESLintBinaryExpression) + .left, ) assert( - directive.value.references[1].id === - directive.value.expression.right, + directive.value!.references[1].id === + (directive.value!.expression as ESLintBinaryExpression) + .right, ) }) }) describe("in text", () => { const code = "" - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should have references", () => { - const container = ast.templateBody.children[0] + const container = ast.templateBody! + .children[0] as VExpressionContainer assert(container.type === "VExpressionContainer") assert(container.references != null) - assert(container.references[0].id === container.expression.left) - assert(container.references[1].id === container.expression.right) + assert( + container.references[0].id === + (container.expression as ESLintBinaryExpression).left, + ) + assert( + container.references[1].id === + (container.expression as ESLintBinaryExpression).right, + ) }) }) describe("in v-on directive", () => { const code = '' - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should not include $event references.", () => { - const directive = - ast.templateBody.children[0].startTag.attributes[0] + const element = ast.templateBody!.children[0] as VElement + const directive = element.startTag.attributes[0] as VDirective assert(directive.key.type === "VDirectiveKey") assert(directive.key.name.name === "on") - assert(directive.value.references.length === 1) + assert(directive.value!.references.length === 1) assert( - directive.value.references[0].id === - directive.value.expression.body[0].expression.callee, + directive.value!.references[0].id === + ( + ( + (directive.value!.expression as VOnExpression) + .body[0] as ESLintExpressionStatement + ).expression as ESLintCallExpression + ).callee, ) }) }) @@ -98,68 +127,61 @@ describe("[references] expression containers", () => { describe("[variables] elements", () => { describe("which have v-for directive", () => { const code = '' - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should have references", () => { - const element = ast.templateBody.children[0] - const directive = element.startTag.attributes[0] + const element = ast.templateBody!.children[0] as VElement + const directive = element.startTag.attributes[0] as VDirective + const vForExpression = directive.value!.expression as VForExpression assert(element.type === "VElement") assert(element.variables.length === 1) - assert( - element.variables[0].id === directive.value.expression.left[0], - ) - assert(directive.value.references.length === 1) - assert( - directive.value.references[0].id === - directive.value.expression.right, - ) + assert(element.variables[0].id === vForExpression.left[0]) + assert(directive.value!.references.length === 1) + assert(directive.value!.references[0].id === vForExpression.right) }) }) describe("which have v-for directive (with index)", () => { const code = '' - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should have references", () => { - const element = ast.templateBody.children[0] - const directive = element.startTag.attributes[0] + const element = ast.templateBody!.children[0] as VElement + const directive = element.startTag.attributes[0] as VDirective + const vForExpression = directive.value!.expression as VForExpression assert(element.type === "VElement") assert(element.variables.length === 2) - assert( - element.variables[0].id === directive.value.expression.left[0], - ) - assert( - element.variables[1].id === directive.value.expression.left[1], - ) - assert(directive.value.references.length === 1) - assert( - directive.value.references[0].id === - directive.value.expression.right, - ) + assert(element.variables[0].id === vForExpression.left[0]) + assert(element.variables[1].id === vForExpression.left[1]) + assert(directive.value!.references.length === 1) + assert(directive.value!.references[0].id === vForExpression.right) }) }) describe("which have scope attribute", () => { const code = '' - let ast = null + // @ts-expect-error init in beforeAll + let ast: ESLintProgram = null - before(() => { + beforeAll(() => { ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast }) it("should have variables", () => { - const element = ast.templateBody.children[0] - const attribute = element.startTag.attributes[0] + const element = ast.templateBody!.children[0] as VElement + const attribute = element.startTag.attributes[0] as VDirective assert(element.type === "VElement") assert(element.variables.length === 1) @@ -167,10 +189,10 @@ describe("[variables] elements", () => { assert(element.variables[0].id.range[0] === 27) assert(element.variables[0].id.range[1] === 28) assert(element.variables[0].kind === "scope") - assert(attribute.value.type === "VExpressionContainer") - assert(attribute.value.expression.type === "VSlotScopeExpression") - assert(attribute.value.expression.params[0].type === "Identifier") - assert(attribute.value.expression.params[0].name === "a") + assert(attribute.value!.type === "VExpressionContainer") + assert(attribute.value!.expression!.type === "VSlotScopeExpression") + assert(attribute.value!.expression.params[0].type === "Identifier") + assert(attribute.value!.expression.params[0].name === "a") }) }) }) @@ -178,25 +200,38 @@ describe("[variables] elements", () => { describe("Variables of v-for and references", () => { const code = '' - let variables = null - let vForReferences = null - let vBindKeyReferences = null - let mustacheReferences1 = null - let mustacheReferences2 = null - let mustacheReferences3 = null - - before(() => { + // @ts-expect-error init in beforeAll + let variables: Variable[] = null + // @ts-expect-error init in beforeAll + let vForReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let vBindKeyReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences1: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences2: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences3: Reference[] = null + + beforeAll(() => { const ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast - variables = ast.templateBody.children[0].variables - vForReferences = - ast.templateBody.children[0].startTag.attributes[0].value.references - vBindKeyReferences = - ast.templateBody.children[0].startTag.attributes[1].value.references - mustacheReferences1 = - ast.templateBody.children[0].children[0].references - mustacheReferences2 = - ast.templateBody.children[0].children[1].children[0].references - mustacheReferences3 = ast.templateBody.children[1].references + const firstChild = ast.templateBody!.children[0] as VElement + const secondChild = ast.templateBody! + .children[1] as VExpressionContainer + variables = firstChild.variables + vForReferences = ( + firstChild.startTag.attributes[0].value as VExpressionContainer + ).references + vBindKeyReferences = ( + firstChild.startTag.attributes[1].value as VExpressionContainer + ).references + mustacheReferences1 = (firstChild.children[0] as VExpressionContainer) + .references + mustacheReferences2 = ( + (firstChild.children[1] as VElement) + .children[0] as VExpressionContainer + ).references + mustacheReferences3 = secondChild.references }) it("should have relationship each other", () => { @@ -221,14 +256,14 @@ describe("Variables of v-for and references", () => { it("`Variable#references` should be non-enumerable", () => { for (const variable of variables) { assert( - Object.getOwnPropertyDescriptor(variable, "references") + Object.getOwnPropertyDescriptor(variable, "references")! .enumerable === false, ) } }) it("`Reference#variable` should be non-enumerable", () => { - for (const reference of [].concat( + for (const reference of ([] as Reference[]).concat( vForReferences, vBindKeyReferences, mustacheReferences1, @@ -236,7 +271,7 @@ describe("Variables of v-for and references", () => { mustacheReferences3, )) { assert( - Object.getOwnPropertyDescriptor(reference, "variable") + Object.getOwnPropertyDescriptor(reference, "variable")! .enumerable === false, ) } @@ -246,22 +281,33 @@ describe("Variables of v-for and references", () => { describe("Variables of template-scope and references", () => { const code = '' - let variables = null - let vBindKeyReferences = null - let mustacheReferences1 = null - let mustacheReferences2 = null - let mustacheReferences3 = null - - before(() => { + // @ts-expect-error init in beforeAll + let variables: Variable[] = null + // @ts-expect-error init in beforeAll + let vBindKeyReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences1: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences2: Reference[] = null + // @ts-expect-error init in beforeAll + let mustacheReferences3: Reference[] = null + + beforeAll(() => { const ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast - variables = ast.templateBody.children[0].variables - vBindKeyReferences = - ast.templateBody.children[0].startTag.attributes[1].value.references - mustacheReferences1 = - ast.templateBody.children[0].children[0].references - mustacheReferences2 = - ast.templateBody.children[0].children[1].children[0].references - mustacheReferences3 = ast.templateBody.children[1].references + const element = ast.templateBody!.children[0] as VElement + const secondElement = ast.templateBody! + .children[1] as VExpressionContainer + + variables = element.variables + vBindKeyReferences = (element.startTag.attributes[1] as VDirective) + .value!.references + mustacheReferences1 = (element.children[0] as VExpressionContainer) + .references + mustacheReferences2 = ( + (element.children[1] as VElement) + .children[0] as VExpressionContainer + ).references + mustacheReferences3 = secondElement.references }) it("should have relationship each other", () => { @@ -284,21 +330,21 @@ describe("Variables of template-scope and references", () => { it("`Variable#references` should be non-enumerable", () => { for (const variable of variables) { assert( - Object.getOwnPropertyDescriptor(variable, "references") + Object.getOwnPropertyDescriptor(variable, "references")! .enumerable === false, ) } }) it("`Reference#variable` should be non-enumerable", () => { - for (const reference of [].concat( + for (const reference of ([] as Reference[]).concat( vBindKeyReferences, mustacheReferences1, mustacheReferences2, mustacheReferences3, )) { assert( - Object.getOwnPropertyDescriptor(reference, "variable") + Object.getOwnPropertyDescriptor(reference, "variable")! .enumerable === false, ) } @@ -307,18 +353,24 @@ describe("Variables of template-scope and references", () => { describe("Variables of v-for and references of dynamic arguments", () => { const code = '' - let variables = null - let vForReferences = null - let vBindKeyReferences = null - - before(() => { + // @ts-expect-error init in beforeAll + let variables: Variable[] = null + // @ts-expect-error init in beforeAll + let vForReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let vBindKeyReferences: Reference[] = null + + beforeAll(() => { const ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast - variables = ast.templateBody.children[0].variables - vForReferences = - ast.templateBody.children[0].startTag.attributes[0].value.references - vBindKeyReferences = - ast.templateBody.children[0].startTag.attributes[1].key.argument - .references + const element = ast.templateBody!.children[0] as VElement + + variables = element.variables + vForReferences = (element.startTag.attributes[0] as VDirective).value! + .references + vBindKeyReferences = ( + (element.startTag.attributes[1] as VDirective).key + .argument as VExpressionContainer + ).references }) it("should have relationship each other", () => { @@ -334,17 +386,22 @@ describe("Variables of v-for and references of dynamic arguments", () => { describe("Variables of v-for and references of v-bind same-name shorthand", () => { const code = '' - let variables = null - let vForReferences = null - let vBindReferences = null - - before(() => { + // @ts-expect-error init in beforeAll + let variables: Variable[] = null + // @ts-expect-error init in beforeAll + let vForReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let vBindReferences: Reference[] = null + + beforeAll(() => { const ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast - variables = ast.templateBody.children[0].variables - vForReferences = - ast.templateBody.children[0].startTag.attributes[0].value.references - vBindReferences = - ast.templateBody.children[0].startTag.attributes[1].value.references + const element = ast.templateBody!.children[0] as VElement + + variables = element.variables + vForReferences = (element.startTag.attributes[0] as VDirective).value! + .references + vBindReferences = (element.startTag.attributes[1] as VDirective).value! + .references }) it("should have relationship each other", () => { @@ -360,17 +417,22 @@ describe("Variables of v-for and references of v-bind same-name shorthand", () = describe("Variables of v-for and references of v-bind same-name shorthand with kebab-case", () => { const code = '' - let variables = null - let vForReferences = null - let vBindReferences = null - - before(() => { + // @ts-expect-error init in beforeAll + let variables: Variable[] = null + // @ts-expect-error init in beforeAll + let vForReferences: Reference[] = null + // @ts-expect-error init in beforeAll + let vBindReferences: Reference[] = null + + beforeAll(() => { const ast = parse(code, { filePath: "test.vue", ...PARSER_OPTIONS }).ast - variables = ast.templateBody.children[0].variables - vForReferences = - ast.templateBody.children[0].startTag.attributes[0].value.references - vBindReferences = - ast.templateBody.children[0].startTag.attributes[1].value.references + const element = ast.templateBody!.children[0] as VElement + + variables = element.variables + vForReferences = (element.startTag.attributes[0] as VDirective).value! + .references + vBindReferences = (element.startTag.attributes[1] as VDirective).value! + .references }) it("should have relationship each other", () => { diff --git a/tsconfig.json b/tsconfig.json index c5dc0e4c..677d8fec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,5 +37,6 @@ "skipLibCheck": true }, - "include": ["src/**/*.ts"] + "include": ["src/**/*.ts"], + "references": [{ "path": "./tsconfig.test.json" }] } diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..a5e080f7 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "paths": { + "*": ["typings/*"] + }, + "module": "esnext", + "moduleResolution": "Bundler" + }, + "include": ["test/**/*.ts", "vitest.config.ts"] +} diff --git a/typings/eslint-scope/index.d.ts b/typings/eslint-scope/index.d.ts index 6d14afcf..1469f501 100644 --- a/typings/eslint-scope/index.d.ts +++ b/typings/eslint-scope/index.d.ts @@ -14,7 +14,7 @@ export interface AnalysisOptions { impliedStrict?: boolean fallback?: string | Function sourceType?: "script" | "module" - ecmaVersion?: number + ecmaVersion?: number | "latest" childVisitorKeys?: VisitorKeys } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..f0cdca4d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "vitest/config" + +export default defineConfig({ + test: { + reporters: "dot", + include: ["test/**/*.test.ts"], + testTimeout: 60000, + coverage: { + include: ["src"], + }, + }, +}) From 4e48327385fd26f39884c81fb21f3f12c36260ad Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Wed, 9 Jul 2025 07:36:53 +0800 Subject: [PATCH 14/14] test: align with `nyc` coverage configuration (#270) --- .nycrc | 19 ------------------- vitest.config.ts | 4 +++- 2 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 .nycrc diff --git a/.nycrc b/.nycrc deleted file mode 100644 index a31275f2..00000000 --- a/.nycrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "src/external/**/*.ts" - ], - "extension": [ - ".ts" - ], - "require": [ - "ts-node/register" - ], - "reporter": [ - "lcov", - "text-summary" - ], - "sourceMap": true -} diff --git a/vitest.config.ts b/vitest.config.ts index f0cdca4d..9df42d5d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,7 +6,9 @@ export default defineConfig({ include: ["test/**/*.test.ts"], testTimeout: 60000, coverage: { - include: ["src"], + include: ["src/**/*.ts"], + exclude: ["src/external/**/*.ts"], + reporter: ["html", "lcov", "text-summary"], }, }, })