This commit is contained in:
Ron Buckton 2015-11-30 14:10:39 -08:00
parent 266600da08
commit c108042886
5 changed files with 101 additions and 8 deletions

View File

@ -9858,7 +9858,7 @@ namespace ts {
return aggregatedTypes;
}
/*
/*
*TypeScript Specification 1.0 (6.3) - July 2014
* An explicitly typed function whose return type isn't the Void or the Any type
* must have at least one return statement somewhere in its body.
@ -9893,7 +9893,7 @@ namespace ts {
}
else {
// This function does not conform to the specification.
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
}
}
@ -11914,6 +11914,14 @@ namespace ts {
return unknownType;
}
// If the constructor, resolved locally, is an alias symbol we should mark it as referenced.
const promiseName = getEntityNameFromTypeNode(node.type);
const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
const promiseAliasSymbol = resolveName(node, promiseNameOrNamespaceRoot.text, SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
if (promiseAliasSymbol) {
markAliasSymbolAsReferenced(promiseAliasSymbol);
}
// Validate the promise constructor type.
const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
@ -11921,12 +11929,10 @@ namespace ts {
}
// Verify there is no local declaration that could collide with the promise constructor.
const promiseName = getEntityNameFromTypeNode(node.type);
const root = getFirstIdentifier(promiseName);
const rootSymbol = getSymbol(node.locals, root.text, SymbolFlags.Value);
const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
if (rootSymbol) {
error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
root.text,
promiseNameOrNamespaceRoot.text,
getFullyQualifiedName(promiseConstructor));
return unknownType;
}
@ -12119,8 +12125,8 @@ namespace ts {
const symbol = getSymbolOfNode(node);
const localSymbol = node.localSymbol || symbol;
// Since the javascript won't do semantic analysis like typescript,
// if the javascript file comes before the typescript file and both contain same name functions,
// Since the javascript won't do semantic analysis like typescript,
// if the javascript file comes before the typescript file and both contain same name functions,
// checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function.
const firstDeclaration = forEach(localSymbol.declarations,
// Get first non javascript function declaration

View File

@ -0,0 +1,37 @@
//// [tests/cases/conformance/async/es6/asyncImportedPromise_es6.ts] ////
//// [task.ts]
export class Task<T> extends Promise<T> { }
//// [test.ts]
import { Task } from "./task";
class Test {
async example<T>(): Task<T> { return; }
}
//// [task.js]
"use strict";
class Task extends Promise {
}
exports.Task = Task;
//// [test.js]
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
return new Promise(function (resolve, reject) {
generator = generator.call(thisArg, _arguments);
function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
function step(verb, value) {
var result = generator[verb](value);
result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject);
}
step("next", void 0);
});
};
var task_1 = require("./task");
class Test {
example() {
return __awaiter(this, void 0, Task, function* () { return; });
}
}

View File

@ -0,0 +1,20 @@
=== tests/cases/conformance/async/es6/task.ts ===
export class Task<T> extends Promise<T> { }
>Task : Symbol(Task, Decl(task.ts, 0, 0))
>T : Symbol(T, Decl(task.ts, 0, 18))
>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(task.ts, 0, 18))
=== tests/cases/conformance/async/es6/test.ts ===
import { Task } from "./task";
>Task : Symbol(Task, Decl(test.ts, 0, 8))
class Test {
>Test : Symbol(Test, Decl(test.ts, 0, 30))
async example<T>(): Task<T> { return; }
>example : Symbol(example, Decl(test.ts, 1, 12))
>T : Symbol(T, Decl(test.ts, 2, 18))
>Task : Symbol(Task, Decl(test.ts, 0, 8))
>T : Symbol(T, Decl(test.ts, 2, 18))
}

View File

@ -0,0 +1,20 @@
=== tests/cases/conformance/async/es6/task.ts ===
export class Task<T> extends Promise<T> { }
>Task : Task<T>
>T : T
>Promise : Promise<T>
>T : T
=== tests/cases/conformance/async/es6/test.ts ===
import { Task } from "./task";
>Task : typeof Task
class Test {
>Test : Test
async example<T>(): Task<T> { return; }
>example : <T>() => Task<T>
>T : T
>Task : Task<T>
>T : T
}

View File

@ -0,0 +1,10 @@
// @target: es6
// @module: commonjs
// @filename: task.ts
export class Task<T> extends Promise<T> { }
// @filename: test.ts
import { Task } from "./task";
class Test {
async example<T>(): Task<T> { return; }
}