@@ -2465,10 +2465,21 @@ namespace ts {
2465
2465
2466
2466
function getDeclarationContainer(node: Node): Node {
2467
2467
node = getRootDeclaration(node);
2468
+ while (node) {
2469
+ switch (node.kind) {
2470
+ case SyntaxKind.VariableDeclaration:
2471
+ case SyntaxKind.VariableDeclarationList:
2472
+ case SyntaxKind.ImportSpecifier:
2473
+ case SyntaxKind.NamedImports:
2474
+ case SyntaxKind.NamespaceImport:
2475
+ case SyntaxKind.ImportClause:
2476
+ node = node.parent;
2477
+ break;
2468
2478
2469
- // Parent chain:
2470
- // VaribleDeclaration -> VariableDeclarationList -> VariableStatement -> 'Declaration Container'
2471
- return node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent.parent : node.parent;
2479
+ default:
2480
+ return node.parent;
2481
+ }
2482
+ }
2472
2483
}
2473
2484
2474
2485
function getTypeOfPrototypeProperty(prototype: Symbol): Type {
@@ -2610,7 +2621,7 @@ namespace ts {
2610
2621
}
2611
2622
}
2612
2623
else if (declaration.kind === SyntaxKind.Parameter) {
2613
- // If it's a parameter, see if the parent has a jsdoc comment with an @param
2624
+ // If it's a parameter, see if the parent has a jsdoc comment with an @param
2614
2625
// annotation.
2615
2626
const paramTag = getCorrespondingJSDocParameterTag(<ParameterDeclaration>declaration);
2616
2627
if (paramTag && paramTag.typeExpression) {
@@ -2625,7 +2636,7 @@ namespace ts {
2625
2636
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
2626
2637
if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) {
2627
2638
// If this is a variable in a JavaScript file, then use the JSDoc type (if it has
2628
- // one as its type), otherwise fallback to the below standard TS codepaths to
2639
+ // one as its type), otherwise fallback to the below standard TS codepaths to
2629
2640
// try to figure it out.
2630
2641
const type = getTypeForVariableLikeDeclarationFromJSDocComment(declaration);
2631
2642
if (type && type !== unknownType) {
@@ -4069,7 +4080,7 @@ namespace ts {
4069
4080
const isJSConstructSignature = isJSDocConstructSignature(declaration);
4070
4081
let returnType: Type = undefined;
4071
4082
4072
- // If this is a JSDoc construct signature, then skip the first parameter in the
4083
+ // If this is a JSDoc construct signature, then skip the first parameter in the
4073
4084
// parameter list. The first parameter represents the return type of the construct
4074
4085
// signature.
4075
4086
for (let i = isJSConstructSignature ? 1 : 0, n = declaration.parameters.length; i < n; i++) {
@@ -4478,7 +4489,7 @@ namespace ts {
4478
4489
}
4479
4490
4480
4491
if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
4481
- // A JSDocTypeReference may have resolved to a value (as opposed to a type). In
4492
+ // A JSDocTypeReference may have resolved to a value (as opposed to a type). In
4482
4493
// that case, the type of this reference is just the type of the value we resolved
4483
4494
// to.
4484
4495
return getTypeOfSymbol(symbol);
@@ -10488,7 +10499,7 @@ namespace ts {
10488
10499
10489
10500
/*
10490
10501
*TypeScript Specification 1.0 (6.3) - July 2014
10491
- * An explicitly typed function whose return type isn't the Void type,
10502
+ * An explicitly typed function whose return type isn't the Void type,
10492
10503
* the Any type, or a union type containing the Void or Any type as a constituent
10493
10504
* must have at least one return statement somewhere in its body.
10494
10505
* An exception to this rule is if the function implementation consists of a single 'throw' statement.
@@ -11644,6 +11655,9 @@ namespace ts {
11644
11655
checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type);
11645
11656
}
11646
11657
}
11658
+ else if (isAsyncFunctionLike(node)) {
11659
+ checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
11660
+ }
11647
11661
}
11648
11662
}
11649
11663
@@ -12513,6 +12527,36 @@ namespace ts {
12513
12527
}
12514
12528
}
12515
12529
12530
+ /**
12531
+ * Checks that the return type provided is an instantiation of the global Promise<T> type
12532
+ * and returns the awaited type of the return type.
12533
+ *
12534
+ * @param returnType The return type of a FunctionLikeDeclaration
12535
+ * @param location The node on which to report the error.
12536
+ */
12537
+ function checkCorrectPromiseType(returnType: Type, location: Node) {
12538
+ if (returnType === unknownType) {
12539
+ // The return type already had some other error, so we ignore and return
12540
+ // the unknown type.
12541
+ return unknownType;
12542
+ }
12543
+
12544
+ const globalPromiseType = getGlobalPromiseType();
12545
+ if (globalPromiseType === emptyGenericType
12546
+ || globalPromiseType === getTargetType(returnType)) {
12547
+ // Either we couldn't resolve the global promise type, which would have already
12548
+ // reported an error, or we could resolve it and the return type is a valid type
12549
+ // reference to the global type. In either case, we return the awaited type for
12550
+ // the return type.
12551
+ return checkAwaitedType(returnType, location, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
12552
+ }
12553
+
12554
+ // The promise type was not a valid type reference to the global promise type, so we
12555
+ // report an error and return the unknown type.
12556
+ error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
12557
+ return unknownType;
12558
+ }
12559
+
12516
12560
/**
12517
12561
* Checks the return type of an async function to ensure it is a compatible
12518
12562
* Promise implementation.
@@ -12527,6 +12571,11 @@ namespace ts {
12527
12571
* callable `then` signature.
12528
12572
*/
12529
12573
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
12574
+ if (languageVersion >= ScriptTarget.ES6) {
12575
+ const returnType = getTypeFromTypeNode(node.type);
12576
+ return checkCorrectPromiseType(returnType, node.type);
12577
+ }
12578
+
12530
12579
const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
12531
12580
if (globalPromiseConstructorLikeType === emptyObjectType) {
12532
12581
// If we couldn't resolve the global PromiseConstructorLike type we cannot verify
@@ -12742,6 +12791,7 @@ namespace ts {
12742
12791
checkCollisionWithCapturedSuperVariable(node, node.name);
12743
12792
checkCollisionWithCapturedThisVariable(node, node.name);
12744
12793
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
12794
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
12745
12795
}
12746
12796
}
12747
12797
@@ -12926,6 +12976,25 @@ namespace ts {
12926
12976
}
12927
12977
}
12928
12978
12979
+ function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void {
12980
+ if (!needCollisionCheckForIdentifier(node, name, "Promise")) {
12981
+ return;
12982
+ }
12983
+
12984
+ // Uninstantiated modules shouldnt do this check
12985
+ if (node.kind === SyntaxKind.ModuleDeclaration && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
12986
+ return;
12987
+ }
12988
+
12989
+ // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
12990
+ const parent = getDeclarationContainer(node);
12991
+ if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(<SourceFile>parent) && parent.flags & NodeFlags.HasAsyncFunctions) {
12992
+ // If the declaration happens to be in external module, report error that Promise is a reserved identifier.
12993
+ error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions,
12994
+ declarationNameToString(name), declarationNameToString(name));
12995
+ }
12996
+ }
12997
+
12929
12998
function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
12930
12999
// - ScriptBody : StatementList
12931
13000
// It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
@@ -13104,6 +13173,7 @@ namespace ts {
13104
13173
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
13105
13174
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
13106
13175
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
13176
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, <Identifier>node.name);
13107
13177
}
13108
13178
}
13109
13179
@@ -13870,6 +13940,7 @@ namespace ts {
13870
13940
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
13871
13941
checkCollisionWithCapturedThisVariable(node, node.name);
13872
13942
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
13943
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
13873
13944
}
13874
13945
checkTypeParameters(node.typeParameters);
13875
13946
checkExportsOnMergedDeclarations(node);
@@ -14376,6 +14447,7 @@ namespace ts {
14376
14447
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
14377
14448
checkCollisionWithCapturedThisVariable(node, node.name);
14378
14449
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14450
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
14379
14451
checkExportsOnMergedDeclarations(node);
14380
14452
14381
14453
computeEnumMemberValues(node);
@@ -14480,6 +14552,7 @@ namespace ts {
14480
14552
14481
14553
checkCollisionWithCapturedThisVariable(node, node.name);
14482
14554
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14555
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
14483
14556
checkExportsOnMergedDeclarations(node);
14484
14557
const symbol = getSymbolOfNode(node);
14485
14558
@@ -14672,6 +14745,7 @@ namespace ts {
14672
14745
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
14673
14746
checkCollisionWithCapturedThisVariable(node, node.name);
14674
14747
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14748
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
14675
14749
checkAliasSymbol(node);
14676
14750
}
14677
14751
0 commit comments