From a1d06d3f70b94b4852fad9e3fc5acbeeac2b0999 Mon Sep 17 00:00:00 2001 From: mainframev Date: Mon, 30 Jun 2025 16:45:05 +0200 Subject: [PATCH] fix(eslint-plugin): add support of exports/reexports to no-deprecated rule --- .../eslint-plugin/src/rules/no-deprecated.ts | 20 ++++-- .../tests/fixtures/deprecated.ts | 5 ++ .../tests/rules/no-deprecated.test.ts | 64 +++++++++++++++++++ 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-deprecated.ts b/packages/eslint-plugin/src/rules/no-deprecated.ts index 725ddaf3fce9..eb12b788e926 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated.ts @@ -161,13 +161,11 @@ export default createRule({ } } - function isInsideExportOrImport(node: TSESTree.Node): boolean { + function isInsideImport(node: TSESTree.Node): boolean { let current = node; while (true) { switch (current.type) { - case AST_NODE_TYPES.ExportAllDeclaration: - case AST_NODE_TYPES.ExportNamedDeclaration: case AST_NODE_TYPES.ImportDeclaration: return true; @@ -178,6 +176,7 @@ export default createRule({ case AST_NODE_TYPES.FunctionDeclaration: case AST_NODE_TYPES.FunctionExpression: case AST_NODE_TYPES.Program: + case AST_NODE_TYPES.ExportSpecifier: case AST_NODE_TYPES.TSUnionType: case AST_NODE_TYPES.VariableDeclarator: return false; @@ -365,7 +364,7 @@ export default createRule({ } function checkIdentifier(node: IdentifierLike): void { - if (isDeclaration(node) || isInsideExportOrImport(node)) { + if (isDeclaration(node) || isInsideImport(node)) { return; } @@ -436,7 +435,18 @@ export default createRule({ } return { - Identifier: checkIdentifier, + ExportSpecifier(node): void { + const symbol = services.getSymbolAtLocation(node.exported); + + if (searchForDeprecationInAliasesChain(symbol, false) == null) { + checkIdentifier(node.exported as TSESTree.Identifier); + } + }, + Identifier(node): void { + if (node.parent.type !== AST_NODE_TYPES.ExportSpecifier) { + checkIdentifier(node); + } + }, JSXIdentifier(node): void { if (node.parent.type !== AST_NODE_TYPES.JSXClosingElement) { checkIdentifier(node); diff --git a/packages/eslint-plugin/tests/fixtures/deprecated.ts b/packages/eslint-plugin/tests/fixtures/deprecated.ts index 2302eabd3f54..b8dc49fcf16d 100644 --- a/packages/eslint-plugin/tests/fixtures/deprecated.ts +++ b/packages/eslint-plugin/tests/fixtures/deprecated.ts @@ -36,6 +36,11 @@ export { ClassWithDeprecatedConstructor as ReexportedClassWithDeprecatedConstructor, }; +/** @deprecated Reason */ +export type T = { a: string }; + +export type U = { b: string }; + /** @deprecated */ export default { foo: 1, diff --git a/packages/eslint-plugin/tests/rules/no-deprecated.test.ts b/packages/eslint-plugin/tests/rules/no-deprecated.test.ts index 1c8f354886df..ecb14cc817f0 100644 --- a/packages/eslint-plugin/tests/rules/no-deprecated.test.ts +++ b/packages/eslint-plugin/tests/rules/no-deprecated.test.ts @@ -329,6 +329,12 @@ ruleTester.run('no-deprecated', rule, { } ; `, + ` + export { + /** @deprecated */ + foo, + }; + `, { code: ` /** @deprecated */ @@ -3173,5 +3179,63 @@ class B extends A { }, ], }, + { + code: ` + import { deprecatedFunction } from './deprecated'; + + export { deprecatedFunction }; + `, + errors: [ + { + column: 18, + endColumn: 36, + endLine: 4, + line: 4, + messageId: 'deprecated', + }, + ], + }, + { + code: ` + export { deprecatedFunction } from './deprecated'; + `, + errors: [ + { + column: 18, + endColumn: 36, + endLine: 2, + line: 2, + messageId: 'deprecated', + }, + ], + }, + { + code: ` + export type { T, U } from './deprecated'; + `, + errors: [ + { + column: 23, + endColumn: 24, + endLine: 2, + line: 2, + messageId: 'deprecatedWithReason', + }, + ], + }, + { + code: ` + export { default as foo } from './deprecated'; + `, + errors: [ + { + column: 29, + endColumn: 32, + endLine: 2, + line: 2, + messageId: 'deprecated', + }, + ], + }, ], });