@@ -5787,6 +5787,90 @@ namespace ts {
5787
5787
}
5788
5788
}
5789
5789
5790
+ function getStaticTypeFromTypeNode(node: TypeNode) {
5791
+ switch (node.kind) {
5792
+ case SyntaxKind.AnyKeyword:
5793
+ case SyntaxKind.JSDocAllType:
5794
+ case SyntaxKind.JSDocUnknownType:
5795
+ return anyType;
5796
+ case SyntaxKind.StringKeyword:
5797
+ return stringType;
5798
+ case SyntaxKind.NumberKeyword:
5799
+ return numberType;
5800
+ case SyntaxKind.BooleanKeyword:
5801
+ return booleanType;
5802
+ case SyntaxKind.SymbolKeyword:
5803
+ return esSymbolType;
5804
+ case SyntaxKind.VoidKeyword:
5805
+ return voidType;
5806
+ case SyntaxKind.UndefinedKeyword:
5807
+ return undefinedType;
5808
+ case SyntaxKind.NullKeyword:
5809
+ return nullType;
5810
+ case SyntaxKind.NeverKeyword:
5811
+ return neverType;
5812
+ case SyntaxKind.JSDocNullKeyword:
5813
+ return nullType;
5814
+ case SyntaxKind.JSDocUndefinedKeyword:
5815
+ return undefinedType;
5816
+ case SyntaxKind.JSDocNeverKeyword:
5817
+ return neverType;
5818
+ case SyntaxKind.ThisType:
5819
+ case SyntaxKind.ThisKeyword:
5820
+ return getTypeFromThisTypeNode(node);
5821
+ case SyntaxKind.LiteralType:
5822
+ return getTypeFromLiteralTypeNode(<LiteralTypeNode>node);
5823
+ case SyntaxKind.JSDocLiteralType:
5824
+ return getTypeFromLiteralTypeNode((<JSDocLiteralType>node).literal);
5825
+ case SyntaxKind.TypeReference:
5826
+ case SyntaxKind.JSDocTypeReference:
5827
+ return getTypeFromTypeReference(<TypeReferenceNode>node);
5828
+ case SyntaxKind.TypePredicate:
5829
+ return booleanType;
5830
+ case SyntaxKind.ExpressionWithTypeArguments:
5831
+ return getTypeFromTypeReference(<ExpressionWithTypeArguments>node);
5832
+ case SyntaxKind.TypeQuery:
5833
+ return getTypeFromTypeQueryNode(<TypeQueryNode>node);
5834
+ case SyntaxKind.ArrayType:
5835
+ case SyntaxKind.JSDocArrayType:
5836
+ return getTypeFromArrayTypeNode(<ArrayTypeNode>node);
5837
+ case SyntaxKind.TupleType:
5838
+ return getTypeFromTupleTypeNode(<TupleTypeNode>node);
5839
+ case SyntaxKind.UnionType:
5840
+ case SyntaxKind.JSDocUnionType:
5841
+ return getTypeFromUnionTypeNode(<UnionTypeNode>node, aliasSymbol, aliasTypeArguments);
5842
+ case SyntaxKind.IntersectionType:
5843
+ return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node, aliasSymbol, aliasTypeArguments);
5844
+ case SyntaxKind.ParenthesizedType:
5845
+ case SyntaxKind.JSDocNullableType:
5846
+ case SyntaxKind.JSDocNonNullableType:
5847
+ case SyntaxKind.JSDocConstructorType:
5848
+ case SyntaxKind.JSDocThisType:
5849
+ case SyntaxKind.JSDocOptionalType:
5850
+ return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode>node).type);
5851
+ case SyntaxKind.JSDocRecordType:
5852
+ return getTypeFromTypeNode((node as JSDocRecordType).literal);
5853
+ case SyntaxKind.FunctionType:
5854
+ case SyntaxKind.ConstructorType:
5855
+ case SyntaxKind.TypeLiteral:
5856
+ case SyntaxKind.JSDocTypeLiteral:
5857
+ case SyntaxKind.JSDocFunctionType:
5858
+ return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments);
5859
+ // This function assumes that an identifier or qualified name is a type expression
5860
+ // Callers should first ensure this by calling isTypeNode
5861
+ case SyntaxKind.Identifier:
5862
+ case SyntaxKind.QualifiedName:
5863
+ const symbol = getSymbolAtLocation(node);
5864
+ return symbol && getDeclaredTypeOfSymbol(symbol);
5865
+ case SyntaxKind.JSDocTupleType:
5866
+ return getTypeFromJSDocTupleType(<JSDocTupleType>node);
5867
+ case SyntaxKind.JSDocVariadicType:
5868
+ return getTypeFromJSDocVariadicType(<JSDocVariadicType>node);
5869
+ default:
5870
+ return unknownType;
5871
+ }
5872
+ }
5873
+
5790
5874
function instantiateList<T>(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] {
5791
5875
if (items && items.length) {
5792
5876
const result: T[] = [];
@@ -15181,31 +15265,24 @@ namespace ts {
15181
15265
}
15182
15266
15183
15267
/**
15184
- * Checks the return type of an async function to ensure it is a compatible
15185
- * Promise implementation.
15186
- * @param node The signature to check
15187
- * @param returnType The return type for the function
15188
- * @remarks
15189
- * This checks that an async function has a valid Promise-compatible return type,
15190
- * and returns the *awaited type* of the promise. An async function has a valid
15191
- * Promise-compatible return type if the resolved value of the return type has a
15192
- * construct signature that takes in an `initializer` function that in turn supplies
15193
- * a `resolve` function as one of its arguments and results in an object with a
15194
- * callable `then` signature.
15195
- */
15268
+ * Checks the return type of an async function to ensure it is a compatible
15269
+ * Promise implementation.
15270
+ *
15271
+ * This checks that an async function has a valid Promise-compatible return type,
15272
+ * and returns the *awaited type* of the promise. An async function has a valid
15273
+ * Promise-compatible return type if the resolved value of the return type has a
15274
+ * construct signature that takes in an `initializer` function that in turn supplies
15275
+ * a `resolve` function as one of its arguments and results in an object with a
15276
+ * callable `then` signature.
15277
+ *
15278
+ * @param node The signature to check
15279
+ */
15196
15280
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
15197
15281
if (languageVersion >= ScriptTarget.ES6) {
15198
15282
const returnType = getTypeFromTypeNode(node.type);
15199
15283
return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
15200
15284
}
15201
15285
15202
- const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
15203
- if (globalPromiseConstructorLikeType === emptyObjectType) {
15204
- // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
15205
- // compatibility with __awaiter.
15206
- return unknownType;
15207
- }
15208
-
15209
15286
// As part of our emit for an async function, we will need to emit the entity name of
15210
15287
// the return type annotation as an expression. To meet the necessary runtime semantics
15211
15288
// for __awaiter, we must also check that the type of the declaration (e.g. the static
@@ -15230,18 +15307,35 @@ namespace ts {
15230
15307
// then<U>(...): Promise<U>;
15231
15308
// }
15232
15309
//
15233
- // When we get the type of the `Promise` symbol here, we get the type of the static
15234
- // side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
15310
+
15311
+ const promiseName = getEntityNameFromTypeNode(node.type);
15312
+ const rootName = getFirstIdentifier(promiseName);
15313
+
15314
+ // Mark the root symbol as referenced.
15315
+ getSymbolLinks(rootName.symbol).referenced = true;
15235
15316
15236
15317
const promiseType = getTypeFromTypeNode(node.type);
15237
15318
if (promiseType === unknownType && compilerOptions.isolatedModules) {
15238
15319
// If we are compiling with isolatedModules, we may not be able to resolve the
15239
- // type as a value. As such, we will just return unknownType;
15320
+ // type as a value. As such, we will just return unknownType.
15240
15321
return unknownType;
15241
15322
}
15242
15323
15324
+ const promiseConstructorType = getStaticTypeFromTypeNode(node.type);
15325
+
15326
+ const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
15327
+ if (globalPromiseConstructorLikeType === emptyObjectType) {
15328
+ // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
15329
+ // compatibility with __awaiter.
15330
+ error(node.type || node.name || node, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
15331
+ return unknownType;
15332
+ }
15333
+
15334
+ // When we get the type of the `Promise` symbol here, we get the type of the static
15335
+ // side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
15336
+
15243
15337
const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
15244
- if (!promiseConstructor || !symbolIsValue(promiseConstructor) ) {
15338
+ if (!promiseConstructor) {
15245
15339
// try to fall back to global promise type.
15246
15340
const typeName = promiseConstructor
15247
15341
? symbolToString(promiseConstructor)
@@ -15259,12 +15353,10 @@ namespace ts {
15259
15353
}
15260
15354
15261
15355
// Verify there is no local declaration that could collide with the promise constructor.
15262
- const promiseName = getEntityNameFromTypeNode(node.type);
15263
- const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
15264
- const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
15356
+ const rootSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value);
15265
15357
if (rootSymbol) {
15266
15358
error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
15267
- promiseNameOrNamespaceRoot .text,
15359
+ rootName .text,
15268
15360
getFullyQualifiedName(promiseConstructor));
15269
15361
return unknownType;
15270
15362
}
@@ -18086,9 +18178,33 @@ namespace ts {
18086
18178
function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] {
18087
18179
throwIfNonDiagnosticsProducing();
18088
18180
if (sourceFile) {
18181
+ // Some global diagnostics are deferred until they are needed and
18182
+ // may not be reported in the firt call to getGlobalDiagnostics.
18183
+ // We should catch these changes and report them.
18184
+ const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
18185
+ const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length;
18186
+
18089
18187
checkSourceFile(sourceFile);
18090
- return diagnostics.getDiagnostics(sourceFile.fileName);
18188
+
18189
+ const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
18190
+ const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
18191
+ if (currentGlobalDiagnostics !== previousGlobalDiagnostics) {
18192
+ // If the arrays are not the same reference, new diagnostics were added.
18193
+ const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics);
18194
+ return concatenate(deferredGlobalDiagnostics, semanticDiagnostics);
18195
+ }
18196
+ else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) {
18197
+ // If the arrays are the same reference, but the length has changed, a single
18198
+ // new diagnostic was added as DiagnosticCollection attempts to reuse the
18199
+ // same array.
18200
+ return concatenate(currentGlobalDiagnostics, semanticDiagnostics);
18201
+ }
18202
+
18203
+ return semanticDiagnostics;
18091
18204
}
18205
+
18206
+ // Global diagnostics are always added when a file is not provided to
18207
+ // getDiagnostics
18092
18208
forEach(host.getSourceFiles(), checkSourceFile);
18093
18209
return diagnostics.getDiagnostics();
18094
18210
}
0 commit comments