diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 869edfaffd4..1266af41840 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -2392,13 +2392,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function isDeprecatedSymbol(symbol: Symbol) {
- if (length(symbol.declarations) > 1) {
- const parentSymbol = getParentOfSymbol(symbol);
- if (parentSymbol && parentSymbol.flags & SymbolFlags.Interface) {
- return some(symbol.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated));
- }
+ const parentSymbol = getParentOfSymbol(symbol);
+ if (parentSymbol && length(symbol.declarations) > 1) {
+ return parentSymbol.flags & SymbolFlags.Interface ? some(symbol.declarations, isDeprecatedDeclaration) : every(symbol.declarations, isDeprecatedDeclaration);
}
- return !!(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Deprecated);
+ return !!symbol.valueDeclaration && isDeprecatedDeclaration(symbol.valueDeclaration)
+ || length(symbol.declarations) && every(symbol.declarations, isDeprecatedDeclaration);
+ }
+
+ function isDeprecatedDeclaration(declaration: Declaration) {
+ return !!(getCombinedNodeFlags(declaration) & NodeFlags.Deprecated);
}
function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) {
@@ -27886,7 +27889,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
- const targetSymbol = checkDeprecatedAliasedSymbol(localOrExportSymbol, node);
+ const targetSymbol = resolveAliasWithDeprecationCheck(localOrExportSymbol, node);
if (isDeprecatedSymbol(targetSymbol) && isUncalledFunctionReference(node, targetSymbol) && targetSymbol.declarations) {
addDeprecatedSuggestion(node, targetSymbol.declarations, node.escapedText as string);
}
@@ -31550,8 +31553,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
else {
- if (isDeprecatedSymbol(prop) && isUncalledFunctionReference(node, prop) && prop.declarations) {
- addDeprecatedSuggestion(right, prop.declarations, right.escapedText as string);
+ const targetPropSymbol = resolveAliasWithDeprecationCheck(prop, right);
+ if (isDeprecatedSymbol(targetPropSymbol) && isUncalledFunctionReference(node, targetPropSymbol) && targetPropSymbol.declarations) {
+ addDeprecatedSuggestion(right, targetPropSymbol.declarations, right.escapedText as string);
}
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, isSelfTypeAccess(left, parentSymbol));
@@ -44164,20 +44168,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (isImportSpecifier(node)) {
- const targetSymbol = checkDeprecatedAliasedSymbol(symbol, node);
- if (isDeprecatedAliasedSymbol(targetSymbol) && targetSymbol.declarations) {
+ const targetSymbol = resolveAliasWithDeprecationCheck(symbol, node);
+ if (isDeprecatedSymbol(targetSymbol) && targetSymbol.declarations) {
addDeprecatedSuggestion(node, targetSymbol.declarations, targetSymbol.escapedName as string);
}
}
}
}
- function isDeprecatedAliasedSymbol(symbol: Symbol) {
- return !!symbol.declarations && every(symbol.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated));
- }
-
- function checkDeprecatedAliasedSymbol(symbol: Symbol, location: Node) {
- if (!(symbol.flags & SymbolFlags.Alias)) return symbol;
+ function resolveAliasWithDeprecationCheck(symbol: Symbol, location: Node) {
+ if (!(symbol.flags & SymbolFlags.Alias) || isDeprecatedSymbol(symbol) || !getDeclarationOfAliasSymbol(symbol)) {
+ return symbol;
+ }
const targetSymbol = resolveAlias(symbol);
if (targetSymbol === unknownSymbol) return targetSymbol;
@@ -44187,7 +44189,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (target) {
if (target === targetSymbol) break;
if (target.declarations && length(target.declarations)) {
- if (isDeprecatedAliasedSymbol(target)) {
+ if (isDeprecatedSymbol(target)) {
addDeprecatedSuggestion(location, target.declarations, target.escapedName as string);
break;
}
diff --git a/tests/cases/fourslash/jsdocDeprecated_suggestion20.ts b/tests/cases/fourslash/jsdocDeprecated_suggestion20.ts
new file mode 100644
index 00000000000..46c190db289
--- /dev/null
+++ b/tests/cases/fourslash/jsdocDeprecated_suggestion20.ts
@@ -0,0 +1,37 @@
+///
+
+// @module: esnext
+// @filename: /a.ts
+////export default function a() {}
+
+// @filename: /b.ts
+////import _a from "./a";
+////export {
+//// /** @deprecated a is deprecated */
+//// _a as a,
+////};
+/////** @deprecated b is deprecated */
+////export const b = (): void => {};
+
+// @filename: /c.ts
+////import * as _ from "./b";
+////
+////_.[|a|]()
+////_.[|b|]()
+
+goTo.file("/c.ts")
+verify.getSuggestionDiagnostics([
+ {
+ "code": 6385,
+ "message": "'a' is deprecated.",
+ "reportsDeprecated": true,
+ "range": test.ranges()[0]
+ },
+ {
+ "code": 6385,
+ "message": "'b' is deprecated.",
+ "reportsDeprecated": true,
+ "range": test.ranges()[1]
+ },
+]);
+
diff --git a/tests/cases/fourslash/jsdocDeprecated_suggestion21.ts b/tests/cases/fourslash/jsdocDeprecated_suggestion21.ts
new file mode 100644
index 00000000000..4fdc2bc69f7
--- /dev/null
+++ b/tests/cases/fourslash/jsdocDeprecated_suggestion21.ts
@@ -0,0 +1,31 @@
+///
+
+// @module: esnext
+// @filename: /a.ts
+////export const a = 1;
+////export const b = 1;
+
+// @filename: /b.ts
+////export {
+//// /** @deprecated a is deprecated */
+//// a
+////} from "./a";
+
+// @filename: /c.ts
+////export {
+//// a
+////} from "./b";
+
+// @filename: /d.ts
+////import * as _ from "./c";
+////_.[|a|]
+
+goTo.file("/d.ts")
+verify.getSuggestionDiagnostics([
+ {
+ "code": 6385,
+ "message": "'a' is deprecated.",
+ "reportsDeprecated": true,
+ "range": test.ranges()[0]
+ },
+]);