@@ -2465,10 +2465,21 @@ namespace ts {
24652465
24662466 function getDeclarationContainer(node: Node): Node {
24672467 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;
24682478
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+ }
24722483 }
24732484
24742485 function getTypeOfPrototypeProperty(prototype: Symbol): Type {
@@ -2610,7 +2621,7 @@ namespace ts {
26102621 }
26112622 }
26122623 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
26142625 // annotation.
26152626 const paramTag = getCorrespondingJSDocParameterTag(<ParameterDeclaration>declaration);
26162627 if (paramTag && paramTag.typeExpression) {
@@ -2625,7 +2636,7 @@ namespace ts {
26252636 function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
26262637 if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) {
26272638 // 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
26292640 // try to figure it out.
26302641 const type = getTypeForVariableLikeDeclarationFromJSDocComment(declaration);
26312642 if (type && type !== unknownType) {
@@ -4069,7 +4080,7 @@ namespace ts {
40694080 const isJSConstructSignature = isJSDocConstructSignature(declaration);
40704081 let returnType: Type = undefined;
40714082
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
40734084 // parameter list. The first parameter represents the return type of the construct
40744085 // signature.
40754086 for (let i = isJSConstructSignature ? 1 : 0, n = declaration.parameters.length; i < n; i++) {
@@ -4478,7 +4489,7 @@ namespace ts {
44784489 }
44794490
44804491 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
44824493 // that case, the type of this reference is just the type of the value we resolved
44834494 // to.
44844495 return getTypeOfSymbol(symbol);
@@ -10488,7 +10499,7 @@ namespace ts {
1048810499
1048910500 /*
1049010501 *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,
1049210503 * the Any type, or a union type containing the Void or Any type as a constituent
1049310504 * must have at least one return statement somewhere in its body.
1049410505 * An exception to this rule is if the function implementation consists of a single 'throw' statement.
@@ -11644,6 +11655,9 @@ namespace ts {
1164411655 checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type);
1164511656 }
1164611657 }
11658+ else if (isAsyncFunctionLike(node)) {
11659+ checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
11660+ }
1164711661 }
1164811662 }
1164911663
@@ -12513,6 +12527,36 @@ namespace ts {
1251312527 }
1251412528 }
1251512529
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+
1251612560 /**
1251712561 * Checks the return type of an async function to ensure it is a compatible
1251812562 * Promise implementation.
@@ -12527,6 +12571,11 @@ namespace ts {
1252712571 * callable `then` signature.
1252812572 */
1252912573 function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
12574+ if (languageVersion >= ScriptTarget.ES6) {
12575+ const returnType = getTypeFromTypeNode(node.type);
12576+ return checkCorrectPromiseType(returnType, node.type);
12577+ }
12578+
1253012579 const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
1253112580 if (globalPromiseConstructorLikeType === emptyObjectType) {
1253212581 // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
@@ -12742,6 +12791,7 @@ namespace ts {
1274212791 checkCollisionWithCapturedSuperVariable(node, node.name);
1274312792 checkCollisionWithCapturedThisVariable(node, node.name);
1274412793 checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
12794+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
1274512795 }
1274612796 }
1274712797
@@ -12926,6 +12976,25 @@ namespace ts {
1292612976 }
1292712977 }
1292812978
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+
1292912998 function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
1293012999 // - ScriptBody : StatementList
1293113000 // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
@@ -13104,6 +13173,7 @@ namespace ts {
1310413173 checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
1310513174 checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
1310613175 checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
13176+ checkCollisionWithGlobalPromiseInGeneratedCode(node, <Identifier>node.name);
1310713177 }
1310813178 }
1310913179
@@ -13870,6 +13940,7 @@ namespace ts {
1387013940 checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
1387113941 checkCollisionWithCapturedThisVariable(node, node.name);
1387213942 checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
13943+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
1387313944 }
1387413945 checkTypeParameters(node.typeParameters);
1387513946 checkExportsOnMergedDeclarations(node);
@@ -14376,6 +14447,7 @@ namespace ts {
1437614447 checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
1437714448 checkCollisionWithCapturedThisVariable(node, node.name);
1437814449 checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14450+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
1437914451 checkExportsOnMergedDeclarations(node);
1438014452
1438114453 computeEnumMemberValues(node);
@@ -14480,6 +14552,7 @@ namespace ts {
1448014552
1448114553 checkCollisionWithCapturedThisVariable(node, node.name);
1448214554 checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14555+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
1448314556 checkExportsOnMergedDeclarations(node);
1448414557 const symbol = getSymbolOfNode(node);
1448514558
@@ -14672,6 +14745,7 @@ namespace ts {
1467214745 function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
1467314746 checkCollisionWithCapturedThisVariable(node, node.name);
1467414747 checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
14748+ checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
1467514749 checkAliasSymbol(node);
1467614750 }
1467714751
0 commit comments