From d52f3615625a19067c33b7b459d3b8facf050952 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Mon, 4 Aug 2025 21:49:25 +0900 Subject: [PATCH 01/12] feat: add ignoreUsingDeclarations option --- packages/eslint-plugin/src/rules/no-unused-vars.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index f2bfa26bb1a8..fa9dace6fd32 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -35,6 +35,7 @@ export type Options = [ destructuredArrayIgnorePattern?: string; ignoreClassWithStaticInitBlock?: boolean; ignoreRestSiblings?: boolean; + ignoreUsingDeclarations?: boolean; reportUsedIgnorePattern?: boolean; vars?: 'all' | 'local'; varsIgnorePattern?: string; @@ -49,6 +50,7 @@ interface TranslatedOptions { destructuredArrayIgnorePattern?: RegExp; ignoreClassWithStaticInitBlock: boolean; ignoreRestSiblings: boolean; + ignoreUsingDeclarations: boolean; reportUsedIgnorePattern: boolean; vars: 'all' | 'local'; varsIgnorePattern?: RegExp; @@ -127,6 +129,11 @@ export default createRule({ description: 'Whether to ignore sibling properties in `...` destructurings.', }, + ignoreUsingDeclarations: { + type: 'boolean', + description: + 'Whether to ignore using or await using declarations.', + }, reportUsedIgnorePattern: { type: 'boolean', description: @@ -162,6 +169,7 @@ export default createRule({ caughtErrors: 'all', ignoreClassWithStaticInitBlock: false, ignoreRestSiblings: false, + ignoreUsingDeclarations: false, reportUsedIgnorePattern: false, vars: 'all', }; @@ -173,6 +181,9 @@ export default createRule({ options.args = firstOption.args ?? options.args; options.ignoreRestSiblings = firstOption.ignoreRestSiblings ?? options.ignoreRestSiblings; + options.ignoreUsingDeclarations = + firstOption.ignoreUsingDeclarations ?? + options.ignoreUsingDeclarations; options.caughtErrors = firstOption.caughtErrors ?? options.caughtErrors; options.ignoreClassWithStaticInitBlock = firstOption.ignoreClassWithStaticInitBlock ?? From ef56280851d97aa22963868ea2fd074845dccfe0 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Mon, 4 Aug 2025 23:23:50 +0900 Subject: [PATCH 02/12] test: add test case for using and await using --- .../no-unused-vars/no-unused-vars.test.ts | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 5f40bbcdc3cc..650a82c75dd0 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -1715,6 +1715,40 @@ export {}; ], filename: 'foo.d.ts', }, + { + code: ` +using foo = bar; + `, + errors: [ + { + data: { + action: 'defined', + varName: 'foo', + additional: '', + }, + line: 2, + messageId: 'unusedVar', + }, + ], + filename: 'foo.d.ts', + }, + { + code: ` +await using foo = bar; + `, + errors: [ + { + data: { + action: 'defined', + varName: 'foo', + additional: '', + }, + line: 2, + messageId: 'unusedVar', + }, + ], + filename: 'foo.d.ts', + }, ], valid: [ @@ -3018,5 +3052,19 @@ declare class Bar {} `, filename: 'foo.d.ts', }, + { + code: ` +using foo = bar; + `, + options: [{ ignoreUsingDeclarations: true }], + filename: 'foo.d.ts', + }, + { + code: ` +await using foo = bar; + `, + options: [{ ignoreUsingDeclarations: true }], + filename: 'foo.d.ts', + }, ], }); From ab2184194ab323f0f6f859da48399640d3ff21f0 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Tue, 5 Aug 2025 00:01:19 +0900 Subject: [PATCH 03/12] feat: implement report using and await using with option --- packages/eslint-plugin/src/rules/no-unused-vars.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index fa9dace6fd32..fb63c9eb2d41 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -557,6 +557,12 @@ export default createRule({ }); } continue; + } else if ( + def.type === TSESLint.Scope.DefinitionType.Variable && + options.ignoreUsingDeclarations && + (def.parent.kind === 'await using' || def.parent.kind === 'using') + ) { + continue; } if (hasRestSpreadSibling(variable)) { From 4216cc99c7c8d7ab3bfea04045e460f68637a1aa Mon Sep 17 00:00:00 2001 From: nayounsang Date: Tue, 5 Aug 2025 15:09:24 +0900 Subject: [PATCH 04/12] test: fix test cases --- .../rules/no-unused-vars/no-unused-vars.test.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 650a82c75dd0..1d73032be13c 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -1722,15 +1722,14 @@ using foo = bar; errors: [ { data: { - action: 'defined', - varName: 'foo', + action: 'assigned a value', additional: '', + varName: 'foo', }, line: 2, messageId: 'unusedVar', }, ], - filename: 'foo.d.ts', }, { code: ` @@ -1739,15 +1738,14 @@ await using foo = bar; errors: [ { data: { - action: 'defined', - varName: 'foo', + action: 'assigned a value', additional: '', + varName: 'foo', }, line: 2, messageId: 'unusedVar', }, ], - filename: 'foo.d.ts', }, ], @@ -3057,14 +3055,12 @@ declare class Bar {} using foo = bar; `, options: [{ ignoreUsingDeclarations: true }], - filename: 'foo.d.ts', }, { code: ` await using foo = bar; `, options: [{ ignoreUsingDeclarations: true }], - filename: 'foo.d.ts', }, ], }); From 01b73c26e51da78e1fcfbc5c254433a169fab6e0 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Tue, 5 Aug 2025 15:09:48 +0900 Subject: [PATCH 05/12] chore: generate snapshots --- .../snapshots/2-TSESTree-Tokens.shot | 14 ++++++++-- .../snapshots/2-TSESTree-Tokens.shot | 14 ++++++++-- .../snapshots/6-AST-Alignment-Tokens.shot | 26 +++++++++---------- .../fixtures-with-differences-tokens.shot | 1 - .../schema-snapshots/no-unused-vars.shot | 6 +++++ .../lib/__snapshots__/convert.test.ts.snap | 2 +- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot index 1d0b129b61d1..52c93eab8644 100644 --- a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot +++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot @@ -81,11 +81,21 @@ }, Punctuator { type: "Punctuator", - value: " List fixtures with Token differences`] "element/AccessorProperty/fixtures/modifier-private/fixture.ts", "element/AccessorProperty/fixtures/modifier-protected/fixture.ts", "element/AccessorProperty/fixtures/modifier-public/fixture.ts", - "jsx/JSXAttribute/fixtures/element-non-self-closing/fixture.tsx", "jsx/JSXNamespacedName/fixtures/component-dashed/fixture.tsx", "jsx/JSXNamespacedName/fixtures/component/fixture.tsx", "legacy-fixtures/basics/fixtures/abstract-class-with-abstract-readonly-property/fixture.ts", diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot index 0d9872aa6a11..e4919667312a 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot @@ -41,6 +41,10 @@ "description": "Whether to ignore sibling properties in `...` destructurings.", "type": "boolean" }, + "ignoreUsingDeclarations": { + "description": "Whether to ignore using or await using declarations.", + "type": "boolean" + }, "reportUsedIgnorePattern": { "description": "Whether to report variables that match any of the valid ignore pattern options if they have been used.", "type": "boolean" @@ -89,6 +93,8 @@ type Options = [ ignoreClassWithStaticInitBlock?: boolean; /** Whether to ignore sibling properties in `...` destructurings. */ ignoreRestSiblings?: boolean; + /** Whether to ignore using or await using declarations. */ + ignoreUsingDeclarations?: boolean; /** Whether to report variables that match any of the valid ignore pattern options if they have been used. */ reportUsedIgnorePattern?: boolean; /** Whether to check all variables or only locally-declared variables. */ diff --git a/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap index e1699f2c49ec..88b6ecabdead 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap @@ -274,7 +274,7 @@ exports[`convert > deeplyCopy > should convert node correctly 1`] = ` "imports": undefined, "isDeclarationFile": false, "jsDocParsingMode": 0, - "kind": 308, + "kind": 307, "languageVariant": 1, "languageVersion": 99, "libReferenceDirectives": [], From cbc5316721fc77284961967407215ff9d287b458 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Wed, 6 Aug 2025 16:13:35 +0900 Subject: [PATCH 06/12] chore: revert snapshots and commit only necessary snapshot --- .../tests/schema-snapshots/no-unused-vars.shot | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot index e4919667312a..0d9872aa6a11 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot @@ -41,10 +41,6 @@ "description": "Whether to ignore sibling properties in `...` destructurings.", "type": "boolean" }, - "ignoreUsingDeclarations": { - "description": "Whether to ignore using or await using declarations.", - "type": "boolean" - }, "reportUsedIgnorePattern": { "description": "Whether to report variables that match any of the valid ignore pattern options if they have been used.", "type": "boolean" @@ -93,8 +89,6 @@ type Options = [ ignoreClassWithStaticInitBlock?: boolean; /** Whether to ignore sibling properties in `...` destructurings. */ ignoreRestSiblings?: boolean; - /** Whether to ignore using or await using declarations. */ - ignoreUsingDeclarations?: boolean; /** Whether to report variables that match any of the valid ignore pattern options if they have been used. */ reportUsedIgnorePattern?: boolean; /** Whether to check all variables or only locally-declared variables. */ From 9a6b869daabe4a487a46fe5860afb930c9586f96 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Wed, 6 Aug 2025 16:27:19 +0900 Subject: [PATCH 07/12] Revert "chore: generate snapshots" This reverts commit 01b73c26e51da78e1fcfbc5c254433a169fab6e0. --- .../snapshots/2-TSESTree-Tokens.shot | 14 ++-------- .../snapshots/2-TSESTree-Tokens.shot | 14 ++-------- .../snapshots/6-AST-Alignment-Tokens.shot | 26 ++++++++++--------- .../fixtures-with-differences-tokens.shot | 1 + .../lib/__snapshots__/convert.test.ts.snap | 2 +- 5 files changed, 20 insertions(+), 37 deletions(-) diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot index 52c93eab8644..1d0b129b61d1 100644 --- a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot +++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot @@ -81,21 +81,11 @@ }, Punctuator { type: "Punctuator", - value: "<", + value: " List fixtures with Token differences`] "element/AccessorProperty/fixtures/modifier-private/fixture.ts", "element/AccessorProperty/fixtures/modifier-protected/fixture.ts", "element/AccessorProperty/fixtures/modifier-public/fixture.ts", + "jsx/JSXAttribute/fixtures/element-non-self-closing/fixture.tsx", "jsx/JSXNamespacedName/fixtures/component-dashed/fixture.tsx", "jsx/JSXNamespacedName/fixtures/component/fixture.tsx", "legacy-fixtures/basics/fixtures/abstract-class-with-abstract-readonly-property/fixture.ts", diff --git a/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap index 88b6ecabdead..e1699f2c49ec 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/convert.test.ts.snap @@ -274,7 +274,7 @@ exports[`convert > deeplyCopy > should convert node correctly 1`] = ` "imports": undefined, "isDeclarationFile": false, "jsDocParsingMode": 0, - "kind": 307, + "kind": 308, "languageVariant": 1, "languageVersion": 99, "libReferenceDirectives": [], From 5a853f564b854d9555b4a53c31e20ada5d33d0fc Mon Sep 17 00:00:00 2001 From: nayounsang Date: Wed, 6 Aug 2025 16:31:09 +0900 Subject: [PATCH 08/12] chore: commit only necessary snapshot --- .../tests/schema-snapshots/no-unused-vars.shot | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot index 0d9872aa6a11..e4919667312a 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot @@ -41,6 +41,10 @@ "description": "Whether to ignore sibling properties in `...` destructurings.", "type": "boolean" }, + "ignoreUsingDeclarations": { + "description": "Whether to ignore using or await using declarations.", + "type": "boolean" + }, "reportUsedIgnorePattern": { "description": "Whether to report variables that match any of the valid ignore pattern options if they have been used.", "type": "boolean" @@ -89,6 +93,8 @@ type Options = [ ignoreClassWithStaticInitBlock?: boolean; /** Whether to ignore sibling properties in `...` destructurings. */ ignoreRestSiblings?: boolean; + /** Whether to ignore using or await using declarations. */ + ignoreUsingDeclarations?: boolean; /** Whether to report variables that match any of the valid ignore pattern options if they have been used. */ reportUsedIgnorePattern?: boolean; /** Whether to check all variables or only locally-declared variables. */ From a8de422dc6953bc61176d5fda72e6e81e44633a2 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 7 Aug 2025 17:14:07 +0900 Subject: [PATCH 09/12] refactor: dont use else if after the unconditional continue --- packages/eslint-plugin/src/rules/no-unused-vars.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index fb63c9eb2d41..4fed6a28de82 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -557,7 +557,9 @@ export default createRule({ }); } continue; - } else if ( + } + + if ( def.type === TSESLint.Scope.DefinitionType.Variable && options.ignoreUsingDeclarations && (def.parent.kind === 'await using' || def.parent.kind === 'using') From ebb5da975acbcffb7b872964f3faf340bc02447d Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 7 Aug 2025 17:41:51 +0900 Subject: [PATCH 10/12] test: align tc with eslint --- .../no-unused-vars/no-unused-vars.test.ts | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 1d73032be13c..8f872ea22170 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -1717,35 +1717,45 @@ export {}; }, { code: ` -using foo = bar; +using resource = getResource(); `, errors: [ { data: { action: 'assigned a value', additional: '', - varName: 'foo', + varName: 'resource', }, line: 2, messageId: 'unusedVar', }, ], + languageOptions: { + parserOptions: { + ecmaVersion: 2026, + }, + }, }, { code: ` -await using foo = bar; +await using resource = getResource(); `, errors: [ { data: { action: 'assigned a value', additional: '', - varName: 'foo', + varName: 'resource', }, line: 2, messageId: 'unusedVar', }, ], + languageOptions: { + parserOptions: { + ecmaVersion: 2026, + }, + }, }, ], @@ -3052,15 +3062,36 @@ declare class Bar {} }, { code: ` -using foo = bar; +using resource = getResource(); +resource(); + `, + languageOptions: { + parserOptions: { + ecmaVersion: 2026, + }, + }, + }, + { + code: ` +using resource = getResource(); `, options: [{ ignoreUsingDeclarations: true }], + languageOptions: { + parserOptions: { + ecmaVersion: 2026, + }, + }, }, { code: ` -await using foo = bar; +await using resource = getResource(); `, options: [{ ignoreUsingDeclarations: true }], + languageOptions: { + parserOptions: { + ecmaVersion: 2026, + }, + }, }, ], }); From 75ff46b31be7e0f9518e850b5ab77a838f417953 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 7 Aug 2025 18:05:00 +0900 Subject: [PATCH 11/12] test: fix lint err --- .../tests/rules/no-unused-vars/no-unused-vars.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 8f872ea22170..263d84cb15e3 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -3075,23 +3075,23 @@ resource(); code: ` using resource = getResource(); `, - options: [{ ignoreUsingDeclarations: true }], languageOptions: { parserOptions: { ecmaVersion: 2026, }, }, + options: [{ ignoreUsingDeclarations: true }], }, { code: ` await using resource = getResource(); `, - options: [{ ignoreUsingDeclarations: true }], languageOptions: { parserOptions: { ecmaVersion: 2026, }, }, + options: [{ ignoreUsingDeclarations: true }], }, ], }); From afa9b929b57843247daf27790967b39200b0f395 Mon Sep 17 00:00:00 2001 From: nayounsang Date: Thu, 7 Aug 2025 18:11:02 +0900 Subject: [PATCH 12/12] test: fix minor diff with eslint tc --- .../tests/rules/no-unused-vars/no-unused-vars.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 263d84cb15e3..75dbb87439a7 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -3063,7 +3063,7 @@ declare class Bar {} { code: ` using resource = getResource(); -resource(); +resource; `, languageOptions: { parserOptions: {