diff --git a/packages/eslint-plugin/src/rules/no-deprecated.ts b/packages/eslint-plugin/src/rules/no-deprecated.ts index 880708a866c3..71b333488b55 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated.ts @@ -162,17 +162,17 @@ 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; case AST_NODE_TYPES.ArrowFunctionExpression: + case AST_NODE_TYPES.ExportAllDeclaration: + case AST_NODE_TYPES.ExportNamedDeclaration: case AST_NODE_TYPES.BlockStatement: case AST_NODE_TYPES.ClassDeclaration: case AST_NODE_TYPES.TSInterfaceDeclaration: @@ -366,11 +366,12 @@ export default createRule({ } function checkIdentifier(node: IdentifierLike): void { - if (isDeclaration(node) || isInsideExportOrImport(node)) { + if (isDeclaration(node) || isInsideImport(node)) { return; } const reason = getDeprecationReason(node); + if (reason == null) { return; } @@ -440,7 +441,33 @@ export default createRule({ } return { - Identifier: checkIdentifier, + Identifier(node): void { + const { parent } = node; + + if ( + parent.type === AST_NODE_TYPES.ExportNamedDeclaration || + parent.type === AST_NODE_TYPES.ExportAllDeclaration + ) { + return; + } + + if (parent.type === AST_NODE_TYPES.ExportSpecifier) { + // only deal with the alias (exported) side, not the local binding + if (parent.exported !== node) { + return; + } + + const symbol = services.getSymbolAtLocation(node); + const aliasDeprecation = getJsDocDeprecation(symbol); + + if (aliasDeprecation != null) { + return; + } + } + + // whether it's a plain identifier or the exported alias + 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 6231f9404944..e5a0937f4264 100644 --- a/packages/eslint-plugin/tests/rules/no-deprecated.test.ts +++ b/packages/eslint-plugin/tests/rules/no-deprecated.test.ts @@ -222,6 +222,12 @@ ruleTester.run('no-deprecated', rule, { default as ts, } from 'typescript'; `, + ` + export { deprecatedFunction as 'bur' } from './deprecated'; + `, + ` + export { 'deprecatedFunction' } from './deprecated'; + `, ` namespace A { /** @deprecated */ @@ -329,6 +335,12 @@ ruleTester.run('no-deprecated', rule, { } ; `, + ` + export { + /** @deprecated */ + foo, + }; + `, { code: ` /** @deprecated */ @@ -3274,5 +3286,77 @@ exists('/foo'); }, ], }, + { + 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', + }, + ], + }, + { + code: ` + export { deprecatedFunction as bar } from './deprecated'; + `, + errors: [ + { + column: 40, + endColumn: 43, + endLine: 2, + line: 2, + messageId: 'deprecated', + }, + ], + }, ], }); diff --git a/packages/typescript-eslint/src/index.ts b/packages/typescript-eslint/src/index.ts index 02197940789a..c369d3605d2c 100644 --- a/packages/typescript-eslint/src/index.ts +++ b/packages/typescript-eslint/src/index.ts @@ -223,6 +223,7 @@ export default { }; export { + // eslint-disable-next-line @typescript-eslint/no-deprecated config, type ConfigWithExtends, type InfiniteDepthConfigWithExtends,