@@ -1121,6 +1121,31 @@ namespace ts {
11211121 return diagnostic;
11221122 }
11231123
1124+ function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) {
1125+ const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations);
1126+ if (deprecatedTag) {
1127+ addRelatedInfo(
1128+ diagnostic,
1129+ createDiagnosticForNode(deprecatedTag, Diagnostics.The_declaration_was_marked_as_deprecated_here)
1130+ );
1131+ }
1132+ // We call `addRelatedInfo()` before adding the diagnostic to prevent duplicates.
1133+ suggestionDiagnostics.add(diagnostic);
1134+ return diagnostic;
1135+ }
1136+
1137+ function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) {
1138+ const diagnostic = createDiagnosticForNode(location, Diagnostics._0_is_deprecated, deprecatedEntity);
1139+ return addDeprecatedSuggestionWorker(declarations, diagnostic);
1140+ }
1141+
1142+ function addDeprecatedSuggestionWithSignature(location: Node, declaration: Node, deprecatedEntity: string | undefined, signatureString: string) {
1143+ const diagnostic = deprecatedEntity
1144+ ? createDiagnosticForNode(location, Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity)
1145+ : createDiagnosticForNode(location, Diagnostics._0_is_deprecated, signatureString);
1146+ return addDeprecatedSuggestionWorker(declaration, diagnostic);
1147+ }
1148+
11241149 function createSymbol(flags: SymbolFlags, name: __String, checkFlags?: CheckFlags) {
11251150 symbolCount++;
11261151 const symbol = <TransientSymbol>(new Symbol(flags | SymbolFlags.Transient, name));
@@ -14147,7 +14172,7 @@ namespace ts {
1414714172 if (prop) {
1414814173 if (reportDeprecated && accessNode && getDeclarationNodeFlagsFromSymbol(prop) & NodeFlags.Deprecated && isUncalledFunctionReference(accessNode, prop)) {
1414914174 const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode);
14150- errorOrSuggestion(/* isError */ false, deprecatedNode, Diagnostics._0_is_deprecated , propName as string);
14175+ addDeprecatedSuggestion( deprecatedNode, prop.declarations , propName as string);
1415114176 }
1415214177 if (accessExpression) {
1415314178 markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
@@ -22599,10 +22624,13 @@ namespace ts {
2259922624 if (propName === undefined) {
2260022625 return type;
2260122626 }
22602- const propType = getTypeOfPropertyOfType(type, propName);
22627+ const includesUndefined = strictNullChecks && maybeTypeOfKind(type, TypeFlags.Undefined);
22628+ const removeOptional = includesUndefined && isOptionalChain(access);
22629+ let propType = getTypeOfPropertyOfType(removeOptional ? getTypeWithFacts(type, TypeFacts.NEUndefined) : type, propName);
2260322630 if (!propType) {
2260422631 return type;
2260522632 }
22633+ propType = removeOptional ? getOptionalType(propType) : propType;
2260622634 const narrowedPropType = narrowType(propType);
2260722635 return filterType(type, t => {
2260822636 const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName);
@@ -23306,7 +23334,7 @@ namespace ts {
2330623334 const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
2330723335 const sourceSymbol = localOrExportSymbol.flags & SymbolFlags.Alias ? resolveAlias(localOrExportSymbol) : localOrExportSymbol;
2330823336 if (getDeclarationNodeFlagsFromSymbol(sourceSymbol) & NodeFlags.Deprecated && isUncalledFunctionReference(node, sourceSymbol)) {
23309- errorOrSuggestion(/* isError */ false, node, Diagnostics._0_is_deprecated , node.escapedText as string);
23337+ addDeprecatedSuggestion( node, sourceSymbol.declarations , node.escapedText as string);
2331023338 }
2331123339
2331223340 let declaration: Declaration | undefined = localOrExportSymbol.valueDeclaration;
@@ -26359,7 +26387,7 @@ namespace ts {
2635926387 }
2636026388 else {
2636126389 if (getDeclarationNodeFlagsFromSymbol(prop) & NodeFlags.Deprecated && isUncalledFunctionReference(node, prop)) {
26362- errorOrSuggestion(/* isError */ false, right, Diagnostics._0_is_deprecated , right.escapedText as string);
26390+ addDeprecatedSuggestion( right, prop.declarations , right.escapedText as string);
2636326391 }
2636426392 checkPropertyNotUsedBeforeDeclaration(prop, node, right);
2636526393 markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
@@ -28968,7 +28996,8 @@ namespace ts {
2896828996 function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) {
2896928997 if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) {
2897028998 const suggestionNode = getDeprecatedSuggestionNode(node);
28971- errorOrSuggestion(/*isError*/ false, suggestionNode, Diagnostics._0_is_deprecated, signatureToString(signature));
28999+ const name = tryGetPropertyAccessOrIdentifierToString(getInvokedExpression(node));
29000+ addDeprecatedSuggestionWithSignature(suggestionNode, signature.declaration, name, signatureToString(signature));
2897229001 }
2897329002 }
2897429003
@@ -32477,7 +32506,11 @@ namespace ts {
3247732506 const symbol = getNodeLinks(node).resolvedSymbol;
3247832507 if (symbol) {
3247932508 if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) {
32480- errorOrSuggestion(/* isError */ false, getDeprecatedSuggestionNode(node), Diagnostics._0_is_deprecated, symbol.escapedName as string);
32509+ addDeprecatedSuggestion(
32510+ getDeprecatedSuggestionNode(node),
32511+ symbol.declarations,
32512+ symbol.escapedName as string
32513+ );
3248132514 }
3248232515 if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) {
3248332516 error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
@@ -36924,7 +36957,7 @@ namespace ts {
3692436957 }
3692536958
3692636959 if (isImportSpecifier(node) && every(target.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated))) {
36927- errorOrSuggestion(/* isError */ false, node.name, Diagnostics._0_is_deprecated , symbol.escapedName as string);
36960+ addDeprecatedSuggestion( node.name, target.declarations , symbol.escapedName as string);
3692836961 }
3692936962 }
3693036963 }
@@ -40170,19 +40203,33 @@ namespace ts {
4017040203 }
4017140204
4017240205 if (forInOrOfStatement.kind === SyntaxKind.ForOfStatement && forInOrOfStatement.awaitModifier) {
40173- if ((forInOrOfStatement.flags & NodeFlags.AwaitContext) === NodeFlags.None) {
40174- // use of 'for-await-of' in non-async function
40206+ if (!(forInOrOfStatement.flags & NodeFlags.AwaitContext)) {
4017540207 const sourceFile = getSourceFileOfNode(forInOrOfStatement);
40176- if (!hasParseDiagnostics(sourceFile)) {
40177- const diagnostic = createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator);
40178- const func = getContainingFunction(forInOrOfStatement);
40179- if (func && func.kind !== SyntaxKind.Constructor) {
40180- Debug.assert((getFunctionFlags(func) & FunctionFlags.Async) === 0, "Enclosing function should never be an async function.");
40181- const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async);
40182- addRelatedInfo(diagnostic, relatedInfo);
40183- }
40184- diagnostics.add(diagnostic);
40185- return true;
40208+ if (isInTopLevelContext(forInOrOfStatement)) {
40209+ if (!hasParseDiagnostics(sourceFile)) {
40210+ if (!isEffectiveExternalModule(sourceFile, compilerOptions)) {
40211+ diagnostics.add(createDiagnosticForNode(forInOrOfStatement.awaitModifier,
40212+ Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module));
40213+ }
40214+ if ((moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.System) || languageVersion < ScriptTarget.ES2017) {
40215+ diagnostics.add(createDiagnosticForNode(forInOrOfStatement.awaitModifier,
40216+ Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_esnext_or_system_and_the_target_option_is_set_to_es2017_or_higher));
40217+ }
40218+ }
40219+ }
40220+ else {
40221+ // use of 'for-await-of' in non-async function
40222+ if (!hasParseDiagnostics(sourceFile)) {
40223+ const diagnostic = createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules);
40224+ const func = getContainingFunction(forInOrOfStatement);
40225+ if (func && func.kind !== SyntaxKind.Constructor) {
40226+ Debug.assert((getFunctionFlags(func) & FunctionFlags.Async) === 0, "Enclosing function should never be an async function.");
40227+ const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async);
40228+ addRelatedInfo(diagnostic, relatedInfo);
40229+ }
40230+ diagnostics.add(diagnostic);
40231+ return true;
40232+ }
4018640233 }
4018740234 return false;
4018840235 }
0 commit comments