diff --git a/.changeset/quiet-toys-burn.md b/.changeset/quiet-toys-burn.md new file mode 100644 index 000000000..6c7c31109 --- /dev/null +++ b/.changeset/quiet-toys-burn.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': minor +--- + +feat: support for typescript-eslint v8 to `svelte/indent` rule diff --git a/package.json b/package.json index f1927cd85..fe4cc5fd7 100644 --- a/package.json +++ b/package.json @@ -15,34 +15,34 @@ }, "devDependencies": { "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "^2.27.9", - "@changesets/get-release-plan": "^4.0.4", - "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0", + "@changesets/cli": "^2.27.10", + "@changesets/get-release-plan": "^4.0.5", + "@eslint-community/eslint-plugin-eslint-comments": "^4.4.1", "@ota-meshi/eslint-plugin": "^0.17.5", "@types/eslint": "^9.6.1", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", "env-cmd": "^10.1.0", "eslint": "~9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-formatter-friendly": "^7.0.0", - "eslint-plugin-eslint-plugin": "^6.2.0", - "eslint-plugin-jsdoc": "^50.4.1", + "eslint-plugin-eslint-plugin": "^6.3.2", + "eslint-plugin-jsdoc": "^50.6.0", "eslint-plugin-json-schema-validator": "^5.1.3", - "eslint-plugin-jsonc": "^2.16.0", + "eslint-plugin-jsonc": "^2.18.2", "eslint-plugin-markdown": "^5.1.0", "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-n": "^17.11.1", + "eslint-plugin-n": "^17.14.0", "eslint-plugin-node-dependencies": "^0.12.0", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-regexp": "^2.6.0", - "eslint-plugin-yml": "^1.14.0", - "npm-run-all2": "^7.0.0", - "prettier": "^3.3.3", - "prettier-plugin-svelte": "^3.2.7", + "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-yml": "^1.15.0", + "npm-run-all2": "^7.0.1", + "prettier": "^3.4.1", + "prettier-plugin-svelte": "^3.3.2", "rimraf": "^6.0.1", - "typescript": "~5.7.0", - "typescript-eslint": "^7.18.0" + "typescript": "~5.7.2", + "typescript-eslint": "^8.16.0" }, "publishConfig": { "access": "public" diff --git a/packages/eslint-plugin-svelte/package.json b/packages/eslint-plugin-svelte/package.json index 039f32665..47215b194 100644 --- a/packages/eslint-plugin-svelte/package.json +++ b/packages/eslint-plugin-svelte/package.json @@ -56,52 +56,52 @@ } }, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@jridgewell/sourcemap-codec": "^1.4.15", - "eslint-compat-utils": "^0.6.0", + "@eslint-community/eslint-utils": "^4.4.1", + "@jridgewell/sourcemap-codec": "^1.5.0", + "eslint-compat-utils": "^0.6.3", "esutils": "^2.0.3", "known-css-properties": "^0.35.0", - "postcss": "^8.4.38", + "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^7.0.0", - "semver": "^7.6.2", + "semver": "^7.6.3", "svelte-eslint-parser": "^1.0.0-0" }, "devDependencies": { - "@babel/core": "^7.25.8", - "@babel/eslint-parser": "^7.25.8", - "@babel/plugin-proposal-function-bind": "^7.25.8", - "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0", + "@babel/core": "^7.26.0", + "@babel/eslint-parser": "^7.25.9", + "@babel/plugin-proposal-function-bind": "^7.25.9", + "@eslint-community/eslint-plugin-eslint-comments": "^4.4.1", "@types/babel__core": "^7.20.5", "@types/eslint-utils": "^3.0.5", "@types/esutils": "^2.0.2", "@types/json-schema": "^7.0.15", - "@types/less": "^3.0.6", - "@types/mocha": "^10.0.9", - "@types/node": "^22.0.0", + "@types/less": "^3.0.7", + "@types/mocha": "^10.0.10", + "@types/node": "^22.10.0", "@types/postcss-safe-parser": "^5.0.4", "@types/semver": "^7.5.8", "@types/stylus": "^0.48.43", - "acorn": "^8.13.0", + "acorn": "^8.14.0", "assert": "^2.1.0", "esbuild": "^0.24.0", "esbuild-register": "^3.6.0", - "eslint-scope": "^8.1.0", + "eslint-scope": "^8.2.0", "eslint-typegen": "^0.3.2", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", - "less": "^4.2.0", - "mocha": "^10.7.3", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "less": "^4.2.1", + "mocha": "^10.8.2", "nyc": "^17.1.0", - "postcss-nested": "^7.0.0", - "sass": "^1.79.5", + "postcss-nested": "^7.0.2", + "sass": "^1.81.0", "source-map-js": "^1.2.1", "stylus": "^0.64.0", - "svelte": "^5.0.0", - "svelte-i18n": "^4.0.0", + "svelte": "^5.2.9", + "svelte-i18n": "^4.0.1", "type-coverage": "^2.29.7", - "yaml": "^2.6.0" + "yaml": "^2.6.1" }, "publishConfig": { "access": "public" diff --git a/packages/eslint-plugin-svelte/src/rules/indent-helpers/es.ts b/packages/eslint-plugin-svelte/src/rules/indent-helpers/es.ts index a0d684521..3e30ed77a 100644 --- a/packages/eslint-plugin-svelte/src/rules/indent-helpers/es.ts +++ b/packages/eslint-plugin-svelte/src/rules/indent-helpers/es.ts @@ -195,7 +195,10 @@ export function defineVisitor(context: IndentContext): NodeListener { visitor.BreakStatement(node); }, CallExpression(node: TSESTree.CallExpression) { - const typeArguments = node.typeArguments ?? node.typeParameters; + const typeArguments = + node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters; const firstToken = sourceCode.getFirstToken(node); const leftParenToken = sourceCode.getTokenAfter(typeArguments || node.callee, { filter: isOpeningParenToken, @@ -706,7 +709,10 @@ export function defineVisitor(context: IndentContext): NodeListener { visitor.MethodDefinition(node); }, NewExpression(node: TSESTree.NewExpression) { - const typeArguments = node.typeArguments ?? node.typeParameters; + const typeArguments = + node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters; const newToken = sourceCode.getFirstToken(node); const calleeTokens = getFirstAndLastTokens(sourceCode, node.callee); offsets.setOffsetToken(calleeTokens.firstToken, 1, newToken); diff --git a/packages/eslint-plugin-svelte/src/rules/indent-helpers/ts.ts b/packages/eslint-plugin-svelte/src/rules/indent-helpers/ts.ts index 16cbc8231..c75d031ee 100644 --- a/packages/eslint-plugin-svelte/src/rules/indent-helpers/ts.ts +++ b/packages/eslint-plugin-svelte/src/rules/indent-helpers/ts.ts @@ -62,7 +62,10 @@ export function defineVisitor(context: IndentContext): NodeListener { // or // const ErrorMap = Map // ^^^^^^^^^^^^^^^^^^ - const typeArguments = node.typeArguments ?? node.typeParameters; + const typeArguments = + node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters; if (typeArguments) { const firstToken = sourceCode.getFirstToken(node); offsets.setOffsetToken(sourceCode.getFirstToken(typeArguments), 1, firstToken); @@ -254,20 +257,34 @@ export function defineVisitor(context: IndentContext): NodeListener { // {[key in foo]: bar} const leftBraceToken = sourceCode.getFirstToken(node); - const leftBracketToken = sourceCode.getTokenBefore(node.typeParameter)!; - const rightBracketToken = sourceCode.getTokenAfter(node.nameType || node.typeParameter)!; + const leftBracketToken = sourceCode.getTokenBefore(node.key || node.typeParameter)!; + const rightBracketToken = sourceCode.getTokenAfter( + node.nameType || node.constraint || node.typeParameter + )!; offsets.setOffsetToken( [...sourceCode.getTokensBetween(leftBraceToken, leftBracketToken), leftBracketToken], 1, leftBraceToken ); offsets.setOffsetElementList( - [node.typeParameter, node.nameType], + [node.key, node.constraint, node.typeParameter, node.nameType], leftBracketToken, rightBracketToken, 1 ); + if (node.key && node.constraint) { + const firstToken = sourceCode.getFirstToken(node.key); + offsets.setOffsetToken( + [ + ...sourceCode.getTokensBetween(firstToken, node.constraint), + sourceCode.getFirstToken(node.constraint) + ], + 1, + firstToken + ); + } + const rightBraceToken = sourceCode.getLastToken(node); if (node.typeAnnotation) { const typeAnnotationToken = sourceCode.getFirstToken(node.typeAnnotation); @@ -402,7 +419,10 @@ export function defineVisitor(context: IndentContext): NodeListener { TSClassImplements(node: TSESTree.TSClassImplements | TSESTree.TSInterfaceHeritage) { // class C implements T {} // ^ - const typeArguments = node.typeArguments ?? node.typeParameters; + const typeArguments = + node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters; if (typeArguments) { offsets.setOffsetToken( sourceCode.getFirstToken(typeArguments), @@ -427,6 +447,14 @@ export function defineVisitor(context: IndentContext): NodeListener { const leftBraceToken = sourceCode.getTokenAfter(idTokens.lastToken)!; const rightBraceToken = sourceCode.getLastToken(node); offsets.setOffsetToken(leftBraceToken, 0, firstToken); + if (node.members) + offsets.setOffsetElementList(node.members, leftBraceToken, rightBraceToken, 1); + }, + TSEnumBody(node: TSESTree.TSEnumBody) { + // enum E {...} + // ^^^^^ + const leftBraceToken = sourceCode.getFirstToken(node); + const rightBraceToken = sourceCode.getLastToken(node); offsets.setOffsetElementList(node.members, leftBraceToken, rightBraceToken, 1); }, TSModuleDeclaration(node: TSESTree.TSModuleDeclaration) { @@ -677,7 +705,10 @@ export function defineVisitor(context: IndentContext): NodeListener { }, TSImportType(node: TSESTree.TSImportType) { // import('foo').B - const typeArguments = node.typeArguments ?? node.typeParameters; + const typeArguments = + node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters; const firstToken = sourceCode.getFirstToken(node); const leftParenToken = sourceCode.getTokenAfter(firstToken, { filter: isOpeningParenToken, @@ -1057,7 +1088,10 @@ export function defineVisitor(context: IndentContext): NodeListener { sourceCode.getFirstToken(node.id || node) ); } - const superTypeArguments = node.superTypeArguments ?? node.superTypeParameters; + const superTypeArguments = + node.superTypeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).superTypeParameters; if (superTypeArguments != null && node.superClass != null) { offsets.setOffsetToken( sourceCode.getFirstToken(superTypeArguments), diff --git a/packages/eslint-plugin-svelte/src/rules/require-event-dispatcher-types.ts b/packages/eslint-plugin-svelte/src/rules/require-event-dispatcher-types.ts index 28c1f51cd..50567410d 100644 --- a/packages/eslint-plugin-svelte/src/rules/require-event-dispatcher-types.ts +++ b/packages/eslint-plugin-svelte/src/rules/require-event-dispatcher-types.ts @@ -42,7 +42,11 @@ export default createRule('require-event-dispatcher-types', { } })) { const node = n as TSESTree.CallExpression; - if ((node.typeArguments ?? node.typeParameters) === undefined) { + if ( + (node.typeArguments ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Support old typescript-eslint + (node as any).typeParameters) === undefined + ) { context.report({ node, messageId: 'missingTypeParameter' }); } } diff --git a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/babel.ts b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/babel.ts index 3cc4c9310..93a6d168d 100644 --- a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/babel.ts +++ b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/babel.ts @@ -43,7 +43,7 @@ export function transform( output: output.code!, mappings: output.map!.mappings }; - } catch (_e) { + } catch { return null; } } diff --git a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/less.ts b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/less.ts index b489dfdd1..b846a92bd 100644 --- a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/less.ts +++ b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/less.ts @@ -50,7 +50,7 @@ export function transform( output: output.css, mappings: JSON.parse(output.map).mappings }; - } catch (_e) { + } catch { return null; } } diff --git a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/postcss.ts b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/postcss.ts index 4c3d699ab..c47fe3e92 100644 --- a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/postcss.ts +++ b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/postcss.ts @@ -49,7 +49,7 @@ export function transform( output: result.content, mappings: result.map.toJSON().mappings }; - } catch (_e) { + } catch { // console.log(e) return null; } diff --git a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/sass.ts b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/sass.ts index 2c1377e91..a6504f423 100644 --- a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/sass.ts +++ b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/sass.ts @@ -39,7 +39,7 @@ export function transform( output: output.css, mappings: output.sourceMap!.mappings }; - } catch (_e) { + } catch { return null; } } diff --git a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/stylus.ts b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/stylus.ts index 14a8a0240..0a92e5b0e 100644 --- a/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/stylus.ts +++ b/packages/eslint-plugin-svelte/src/shared/svelte-compile-warns/transform/stylus.ts @@ -45,7 +45,7 @@ export function transform( output, mappings: (style as unknown as { sourcemap: RawSourceMap }).sourcemap.mappings }; - } catch (_e) { + } catch { return null; } } diff --git a/packages/eslint-plugin-svelte/src/types-for-node.ts b/packages/eslint-plugin-svelte/src/types-for-node.ts index 866ea6dab..a1bf991a5 100644 --- a/packages/eslint-plugin-svelte/src/types-for-node.ts +++ b/packages/eslint-plugin-svelte/src/types-for-node.ts @@ -135,6 +135,7 @@ export type ASTNodeListener = { TSEmptyBodyFunctionExpression?: ( node: TSESTree.TSEmptyBodyFunctionExpression & ASTNodeWithParent ) => void; + TSEnumBody?: (node: TSESTree.TSEnumBody & ASTNodeWithParent) => void; TSEnumDeclaration?: (node: TSESTree.TSEnumDeclaration & ASTNodeWithParent) => void; TSEnumMember?: (node: TSESTree.TSEnumMember & ASTNodeWithParent) => void; TSExportAssignment?: (node: TSESTree.TSExportAssignment & ASTNodeWithParent) => void; @@ -143,9 +144,6 @@ export type ASTNodeListener = { node: TSESTree.TSExternalModuleReference & ASTNodeWithParent ) => void; TSFunctionType?: (node: TSESTree.TSFunctionType & ASTNodeWithParent) => void; - TSInstantiationExpression?: ( - node: TSESTree.TSInstantiationExpression & ASTNodeWithParent - ) => void; TSImportEqualsDeclaration?: ( node: TSESTree.TSImportEqualsDeclaration & ASTNodeWithParent ) => void; @@ -153,6 +151,9 @@ export type ASTNodeListener = { TSIndexedAccessType?: (node: TSESTree.TSIndexedAccessType & ASTNodeWithParent) => void; TSIndexSignature?: (node: TSESTree.TSIndexSignature & ASTNodeWithParent) => void; TSInferType?: (node: TSESTree.TSInferType & ASTNodeWithParent) => void; + TSInstantiationExpression?: ( + node: TSESTree.TSInstantiationExpression & ASTNodeWithParent + ) => void; TSInterfaceBody?: (node: TSESTree.TSInterfaceBody & ASTNodeWithParent) => void; TSInterfaceDeclaration?: (node: TSESTree.TSInterfaceDeclaration & ASTNodeWithParent) => void; TSInterfaceHeritage?: (node: TSESTree.TSInterfaceHeritage & ASTNodeWithParent) => void; @@ -354,6 +355,7 @@ export type TSNodeListener = { TSEmptyBodyFunctionExpression?: ( node: TSESTree.TSEmptyBodyFunctionExpression & ASTNodeWithParent ) => void; + TSEnumBody?: (node: TSESTree.TSEnumBody & ASTNodeWithParent) => void; TSEnumDeclaration?: (node: TSESTree.TSEnumDeclaration & ASTNodeWithParent) => void; TSEnumMember?: (node: TSESTree.TSEnumMember & ASTNodeWithParent) => void; TSExportAssignment?: (node: TSESTree.TSExportAssignment & ASTNodeWithParent) => void; @@ -362,9 +364,6 @@ export type TSNodeListener = { node: TSESTree.TSExternalModuleReference & ASTNodeWithParent ) => void; TSFunctionType?: (node: TSESTree.TSFunctionType & ASTNodeWithParent) => void; - TSInstantiationExpression?: ( - node: TSESTree.TSInstantiationExpression & ASTNodeWithParent - ) => void; TSImportEqualsDeclaration?: ( node: TSESTree.TSImportEqualsDeclaration & ASTNodeWithParent ) => void; @@ -372,6 +371,9 @@ export type TSNodeListener = { TSIndexedAccessType?: (node: TSESTree.TSIndexedAccessType & ASTNodeWithParent) => void; TSIndexSignature?: (node: TSESTree.TSIndexSignature & ASTNodeWithParent) => void; TSInferType?: (node: TSESTree.TSInferType & ASTNodeWithParent) => void; + TSInstantiationExpression?: ( + node: TSESTree.TSInstantiationExpression & ASTNodeWithParent + ) => void; TSInterfaceBody?: (node: TSESTree.TSInterfaceBody & ASTNodeWithParent) => void; TSInterfaceDeclaration?: (node: TSESTree.TSInterfaceDeclaration & ASTNodeWithParent) => void; TSInterfaceHeritage?: (node: TSESTree.TSInterfaceHeritage & ASTNodeWithParent) => void; diff --git a/packages/eslint-plugin-svelte/src/utils/get-package-json.ts b/packages/eslint-plugin-svelte/src/utils/get-package-json.ts index e764d2589..9017256d2 100644 --- a/packages/eslint-plugin-svelte/src/utils/get-package-json.ts +++ b/packages/eslint-plugin-svelte/src/utils/get-package-json.ts @@ -35,7 +35,7 @@ function readPackageJson(dir: string): PackageJson | null { data.filePath = filePath; return data; } - } catch (_err) { + } catch { // do nothing. } diff --git a/packages/eslint-plugin-svelte/src/utils/svelte-kit.ts b/packages/eslint-plugin-svelte/src/utils/svelte-kit.ts index 04a1b390b..93f0236ae 100644 --- a/packages/eslint-plugin-svelte/src/utils/svelte-kit.ts +++ b/packages/eslint-plugin-svelte/src/utils/svelte-kit.ts @@ -55,7 +55,7 @@ function hasSvelteKit(filePath: string): boolean { return Boolean( packageJson.dependencies?.['@sveltejs/kit'] ?? packageJson.devDependencies?.['@sveltejs/kit'] ); - } catch (_e) { + } catch { return false; } } diff --git a/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/no-unnecessary-condition.ts b/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/no-unnecessary-condition.ts index e15bc7b3f..3ebabcea4 100644 --- a/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/no-unnecessary-condition.ts +++ b/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/no-unnecessary-condition.ts @@ -11,7 +11,8 @@ const tester = new RuleTester({ ts: '@typescript-eslint/parser', js: 'espree' }, - project: RULES_PROJECT + project: RULES_PROJECT, + disallowAutomaticSingleRunInference: true } } }); diff --git a/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/original-tests/no-unnecessary-condition.ts b/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/original-tests/no-unnecessary-condition.ts index 624ee2456..2d92bcb05 100644 --- a/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/original-tests/no-unnecessary-condition.ts +++ b/packages/eslint-plugin-svelte/tests/src/rules/@typescript-eslint/original-tests/no-unnecessary-condition.ts @@ -18,7 +18,8 @@ const ruleTester = new RuleTester({ parser: require('@typescript-eslint/parser'), parserOptions: { tsconfigRootDir: rootPath, - project: './tsconfig.json' + project: './tsconfig.json', + disallowAutomaticSingleRunInference: true } } }); diff --git a/packages/eslint-plugin-svelte/tools/new-rule.ts b/packages/eslint-plugin-svelte/tools/new-rule.ts index a76cc322e..16c5ae3ad 100644 --- a/packages/eslint-plugin-svelte/tools/new-rule.ts +++ b/packages/eslint-plugin-svelte/tools/new-rule.ts @@ -141,7 +141,7 @@ This rule reports ???. cp.execSync(`code "${ruleFile}"`); cp.execSync(`code "${testFile}"`); cp.execSync(`code "${docFile}"`); - } catch (_) { + } catch { logger.error('Unable to find code command. Will not open files with VSCode.'); } })(process.argv.slice(2));