@@ -15546,31 +15546,24 @@ namespace ts {
1554615546 }
1554715547
1554815548 /**
15549- * Checks the return type of an async function to ensure it is a compatible
15550- * Promise implementation.
15551- * @param node The signature to check
15552- * @param returnType The return type for the function
15553- * @remarks
15554- * This checks that an async function has a valid Promise-compatible return type,
15555- * and returns the *awaited type* of the promise. An async function has a valid
15556- * Promise-compatible return type if the resolved value of the return type has a
15557- * construct signature that takes in an `initializer` function that in turn supplies
15558- * a `resolve` function as one of its arguments and results in an object with a
15559- * callable `then` signature.
15560- */
15549+ * Checks the return type of an async function to ensure it is a compatible
15550+ * Promise implementation.
15551+ *
15552+ * This checks that an async function has a valid Promise-compatible return type,
15553+ * and returns the *awaited type* of the promise. An async function has a valid
15554+ * Promise-compatible return type if the resolved value of the return type has a
15555+ * construct signature that takes in an `initializer` function that in turn supplies
15556+ * a `resolve` function as one of its arguments and results in an object with a
15557+ * callable `then` signature.
15558+ *
15559+ * @param node The signature to check
15560+ */
1556115561 function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
1556215562 if (languageVersion >= ScriptTarget.ES2015) {
1556315563 const returnType = getTypeFromTypeNode(node.type);
1556415564 return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
1556515565 }
1556615566
15567- const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
15568- if (globalPromiseConstructorLikeType === emptyObjectType) {
15569- // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
15570- // compatibility with __awaiter.
15571- return unknownType;
15572- }
15573-
1557415567 // As part of our emit for an async function, we will need to emit the entity name of
1557515568 // the return type annotation as an expression. To meet the necessary runtime semantics
1557615569 // for __awaiter, we must also check that the type of the declaration (e.g. the static
@@ -15595,42 +15588,56 @@ namespace ts {
1559515588 // then<U>(...): Promise<U>;
1559615589 // }
1559715590 //
15598- // When we get the type of the `Promise` symbol here, we get the type of the static
15599- // side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
1560015591
15592+ // Always mark the type node as referenced if it points to a value
15593+ markTypeNodeAsReferenced(node.type);
15594+
15595+ const promiseConstructorName = getEntityNameFromTypeNode(node.type);
1560115596 const promiseType = getTypeFromTypeNode(node.type);
15602- if (promiseType === unknownType && compilerOptions.isolatedModules) {
15603- // If we are compiling with isolatedModules, we may not be able to resolve the
15604- // type as a value. As such, we will just return unknownType;
15597+ if (promiseType === unknownType) {
15598+ if (!compilerOptions.isolatedModules) {
15599+ if (promiseConstructorName) {
15600+ error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
15601+ }
15602+ else {
15603+ error(node.type, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
15604+ }
15605+ }
1560515606 return unknownType;
1560615607 }
1560715608
15608- const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
15609- if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
15610- // try to fall back to global promise type.
15611- const typeName = promiseConstructor
15612- ? symbolToString(promiseConstructor)
15613- : typeToString(promiseType);
15614- return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
15609+ if (promiseConstructorName === undefined) {
15610+ error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(promiseType));
15611+ return unknownType;
1561515612 }
1561615613
15617- // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
15618- checkReturnTypeAnnotationAsExpression(node);
15614+ const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true);
15615+ const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : unknownType;
15616+ if (promiseConstructorType === unknownType) {
15617+ error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
15618+ return unknownType;
15619+ }
1561915620
15620- // Validate the promise constructor type.
15621- const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
15622- if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
15621+ const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
15622+ if (globalPromiseConstructorLikeType === emptyObjectType) {
15623+ // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
15624+ // compatibility with __awaiter.
15625+ error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
15626+ return unknownType;
15627+ }
15628+
15629+ if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type,
15630+ Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) {
1562315631 return unknownType;
1562415632 }
1562515633
1562615634 // Verify there is no local declaration that could collide with the promise constructor.
15627- const promiseName = getEntityNameFromTypeNode(node.type);
15628- const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
15629- const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
15630- if (rootSymbol) {
15631- error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
15632- promiseNameOrNamespaceRoot.text,
15633- getFullyQualifiedName(promiseConstructor));
15635+ const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName);
15636+ const collidingSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value);
15637+ if (collidingSymbol) {
15638+ error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
15639+ rootName.text,
15640+ entityNameToString(promiseConstructorName));
1563415641 return unknownType;
1563515642 }
1563615643
@@ -15688,44 +15695,19 @@ namespace ts {
1568815695 errorInfo);
1568915696 }
1569015697
15691- /** Checks a type reference node as an expression. */
15692- function checkTypeNodeAsExpression(node: TypeNode) {
15693- // When we are emitting type metadata for decorators, we need to try to check the type
15694- // as if it were an expression so that we can emit the type in a value position when we
15695- // serialize the type metadata.
15696- if (node && node.kind === SyntaxKind.TypeReference) {
15697- const root = getFirstIdentifier((<TypeReferenceNode>node).typeName);
15698- const meaning = root.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
15699- // Resolve type so we know which symbol is referenced
15700- const rootSymbol = resolveName(root, root.text, meaning | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
15701- // Resolved symbol is alias
15702- if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) {
15703- const aliasTarget = resolveAlias(rootSymbol);
15704- // If alias has value symbol - mark alias as referenced
15705- if (aliasTarget.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
15706- markAliasSymbolAsReferenced(rootSymbol);
15707- }
15708- }
15709- }
15710- }
15711-
1571215698 /**
15713- * Checks the type annotation of an accessor declaration or property declaration as
15714- * an expression if it is a type reference to a type with a value declaration.
15715- */
15716- function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) {
15717- checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
15718- }
15719-
15720- function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) {
15721- checkTypeNodeAsExpression(node.type);
15722- }
15723-
15724- /** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
15725- function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
15726- // ensure all type annotations with a value declaration are checked as an expression
15727- for (const parameter of node.parameters) {
15728- checkTypeAnnotationAsExpression(parameter);
15699+ * If a TypeNode can be resolved to a value symbol imported from an external module, it is
15700+ * marked as referenced to prevent import elision.
15701+ */
15702+ function markTypeNodeAsReferenced(node: TypeNode) {
15703+ const typeName = node && getEntityNameFromTypeNode(node);
15704+ const rootName = typeName && getFirstIdentifier(typeName);
15705+ const rootSymbol = rootName && resolveName(rootName, rootName.text, (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
15706+ if (rootSymbol
15707+ && rootSymbol.flags & SymbolFlags.Alias
15708+ && symbolIsValue(rootSymbol)
15709+ && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
15710+ markAliasSymbolAsReferenced(rootSymbol);
1572915711 }
1573015712 }
1573115713
@@ -15751,20 +15733,25 @@ namespace ts {
1575115733 case SyntaxKind.ClassDeclaration:
1575215734 const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
1575315735 if (constructor) {
15754- checkParameterTypeAnnotationsAsExpressions(constructor);
15736+ for (const parameter of constructor.parameters) {
15737+ markTypeNodeAsReferenced(parameter.type);
15738+ }
1575515739 }
1575615740 break;
1575715741
1575815742 case SyntaxKind.MethodDeclaration:
1575915743 case SyntaxKind.GetAccessor:
1576015744 case SyntaxKind.SetAccessor:
15761- checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
15762- checkReturnTypeAnnotationAsExpression(<FunctionLikeDeclaration>node);
15745+ for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
15746+ markTypeNodeAsReferenced(parameter.type);
15747+ }
15748+
15749+ markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
1576315750 break;
1576415751
1576515752 case SyntaxKind.PropertyDeclaration:
1576615753 case SyntaxKind.Parameter:
15767- checkTypeAnnotationAsExpression( <PropertyDeclaration | ParameterDeclaration>node);
15754+ markTypeNodeAsReferenced(( <PropertyDeclaration | ParameterDeclaration>node).type );
1576815755 break;
1576915756 }
1577015757 }
@@ -18476,9 +18463,33 @@ namespace ts {
1847618463 function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] {
1847718464 throwIfNonDiagnosticsProducing();
1847818465 if (sourceFile) {
18466+ // Some global diagnostics are deferred until they are needed and
18467+ // may not be reported in the firt call to getGlobalDiagnostics.
18468+ // We should catch these changes and report them.
18469+ const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
18470+ const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length;
18471+
1847918472 checkSourceFile(sourceFile);
18480- return diagnostics.getDiagnostics(sourceFile.fileName);
18473+
18474+ const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
18475+ const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
18476+ if (currentGlobalDiagnostics !== previousGlobalDiagnostics) {
18477+ // If the arrays are not the same reference, new diagnostics were added.
18478+ const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics);
18479+ return concatenate(deferredGlobalDiagnostics, semanticDiagnostics);
18480+ }
18481+ else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) {
18482+ // If the arrays are the same reference, but the length has changed, a single
18483+ // new diagnostic was added as DiagnosticCollection attempts to reuse the
18484+ // same array.
18485+ return concatenate(currentGlobalDiagnostics, semanticDiagnostics);
18486+ }
18487+
18488+ return semanticDiagnostics;
1848118489 }
18490+
18491+ // Global diagnostics are always added when a file is not provided to
18492+ // getDiagnostics
1848218493 forEach(host.getSourceFiles(), checkSourceFile);
1848318494 return diagnostics.getDiagnostics();
1848418495 }
0 commit comments