Added types, scan, parse, and check for async functions
This commit is contained in:
parent
15f4b58d6c
commit
d19a200750
|
@ -89,7 +89,7 @@ module ts {
|
|||
let nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null");
|
||||
let unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
|
||||
let resolvingType = createIntrinsicType(TypeFlags.Any, "__resolving__");
|
||||
|
||||
|
||||
let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
|
@ -101,6 +101,8 @@ module ts {
|
|||
|
||||
let globalArraySymbol: Symbol;
|
||||
let globalESSymbolConstructorSymbol: Symbol;
|
||||
|
||||
let getGlobalPromiseSymbol: () => Symbol;
|
||||
|
||||
let globalObjectType: ObjectType;
|
||||
let globalFunctionType: ObjectType;
|
||||
|
@ -118,6 +120,11 @@ module ts {
|
|||
let getGlobalParameterDecoratorType: () => ObjectType;
|
||||
let getGlobalPropertyDecoratorType: () => ObjectType;
|
||||
let getGlobalMethodDecoratorType: () => ObjectType;
|
||||
let getGlobalPromiseType: () => ObjectType;
|
||||
let getGlobalPromiseLikeType: () => ObjectType;
|
||||
let getInstantiatedGlobalPromiseLikeType: () => ObjectType;
|
||||
let getGlobalPromiseConstructorLikeType: () => ObjectType;
|
||||
let getGlobalThenableType: () => ObjectType;
|
||||
|
||||
let tupleTypes: Map<TupleType> = {};
|
||||
let unionTypes: Map<UnionType> = {};
|
||||
|
@ -125,11 +132,14 @@ module ts {
|
|||
let emitExtends = false;
|
||||
let emitDecorate = false;
|
||||
let emitParam = false;
|
||||
let emitAwaiter = false;
|
||||
let emitGenerator = false;
|
||||
|
||||
let mergedSymbols: Symbol[] = [];
|
||||
let symbolLinks: SymbolLinks[] = [];
|
||||
let nodeLinks: NodeLinks[] = [];
|
||||
let potentialThisCollisions: Node[] = [];
|
||||
var potentialArgumentsCollisions: Node[] = [];
|
||||
|
||||
let diagnostics = createDiagnosticCollection();
|
||||
|
||||
|
@ -5146,9 +5156,11 @@ module ts {
|
|||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
case SyntaxKind.YieldExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.Block:
|
||||
|
@ -5406,8 +5418,14 @@ module ts {
|
|||
// will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior.
|
||||
// To avoid that we will give an error to users if they use arguments objects in arrow function so that they
|
||||
// can explicitly bound arguments objects
|
||||
if (symbol === argumentsSymbol && getContainingFunction(node).kind === SyntaxKind.ArrowFunction && languageVersion < ScriptTarget.ES6) {
|
||||
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
|
||||
let container = getContainingFunction(node);
|
||||
if (symbol === argumentsSymbol) {
|
||||
if (container.kind === SyntaxKind.ArrowFunction && languageVersion < ScriptTarget.ES6) {
|
||||
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
|
||||
}
|
||||
else if (node.parserContextFlags & ParserContextFlags.Await) {
|
||||
captureLexicalArguments(node, container);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
|
||||
|
@ -5416,6 +5434,7 @@ module ts {
|
|||
|
||||
checkCollisionWithCapturedSuperVariable(node, node);
|
||||
checkCollisionWithCapturedThisVariable(node, node);
|
||||
checkCollisionWithCapturedArgumentsVariable(node, node);
|
||||
checkBlockScopedBindingCapturedInLoop(node, symbol);
|
||||
|
||||
return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
|
||||
|
@ -5497,6 +5516,11 @@ module ts {
|
|||
// When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
|
||||
needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES6);
|
||||
}
|
||||
|
||||
if (node.parserContextFlags & ParserContextFlags.Await) {
|
||||
// if 'this' is part of an async function, we will need to capture 'this'
|
||||
needToCaptureLexicalThis = true;
|
||||
}
|
||||
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
|
@ -5537,6 +5561,14 @@ module ts {
|
|||
return anyType;
|
||||
}
|
||||
|
||||
function captureLexicalArguments(node: Node, container: Node): void {
|
||||
if (node.parent.kind !== SyntaxKind.Parameter) {
|
||||
getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments;
|
||||
}
|
||||
|
||||
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
|
||||
}
|
||||
|
||||
function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
|
||||
for (let n = node; n && n !== constructorDecl; n = n.parent) {
|
||||
if (n.kind === SyntaxKind.Parameter) {
|
||||
|
@ -7220,22 +7252,42 @@ module ts {
|
|||
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
|
||||
}
|
||||
}
|
||||
|
||||
function createPromiseType(promisedType: Type, location: Node): Type {
|
||||
// creates a `Promise<T>` type where `T` is the promisedType argument
|
||||
let globalPromiseType = getGlobalPromiseType();
|
||||
if (globalPromiseType !== emptyObjectType) {
|
||||
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
|
||||
promisedType = getAwaitedType(promisedType);
|
||||
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
|
||||
}
|
||||
|
||||
error(location, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
let contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
|
||||
if (!func.body) {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
let isAsync = isAsyncFunctionLike(func);
|
||||
let type: Type;
|
||||
if (func.body.kind !== SyntaxKind.Block) {
|
||||
type = checkExpressionCached(<Expression>func.body, contextualMapper);
|
||||
type = isAsync
|
||||
? checkAwaitedExpressionCached(<Expression>func.body, contextualMapper)
|
||||
: checkExpressionCached(<Expression>func.body, contextualMapper);
|
||||
}
|
||||
else {
|
||||
// Aggregate the types of expressions within all the return statements.
|
||||
let types = checkAndAggregateReturnExpressionTypes(<Block>func.body, contextualMapper);
|
||||
if (types.length === 0) {
|
||||
return voidType;
|
||||
return isAsync
|
||||
? createPromiseType(voidType, func)
|
||||
: voidType;
|
||||
}
|
||||
|
||||
// When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
|
||||
// return expressions to have a best common supertype.
|
||||
type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
|
||||
|
@ -7247,17 +7299,23 @@ module ts {
|
|||
if (!contextualSignature) {
|
||||
reportErrorsFromWidening(func, type);
|
||||
}
|
||||
return getWidenedType(type);
|
||||
|
||||
let widenedType = getWidenedType(type);
|
||||
return isAsync
|
||||
? createPromiseType(widenedType, func)
|
||||
: type;
|
||||
}
|
||||
|
||||
/// Returns a set of types relating to every return expression relating to a function block.
|
||||
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper): Type[] {
|
||||
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper, isAsync?: boolean): Type[] {
|
||||
let aggregatedTypes: Type[] = [];
|
||||
|
||||
forEachReturnStatement(body, returnStatement => {
|
||||
let expr = returnStatement.expression;
|
||||
if (expr) {
|
||||
let type = checkExpressionCached(expr, contextualMapper);
|
||||
let type = isAsync
|
||||
? checkAwaitedExpressionCached(expr, contextualMapper)
|
||||
: checkExpressionCached(expr, contextualMapper);
|
||||
if (!contains(aggregatedTypes, type)) {
|
||||
aggregatedTypes.push(type);
|
||||
}
|
||||
|
@ -7327,6 +7385,12 @@ module ts {
|
|||
if (contextualMapper === identityMapper && isContextSensitive(node)) {
|
||||
return anyFunctionType;
|
||||
}
|
||||
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
if (isAsync) {
|
||||
emitAwaiter = true;
|
||||
}
|
||||
|
||||
let links = getNodeLinks(node);
|
||||
let type = getTypeOfSymbol(node.symbol);
|
||||
// Check if function expression is contextually typed and assign parameter types if so
|
||||
|
@ -7357,6 +7421,7 @@ module ts {
|
|||
if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
|
||||
checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
|
||||
checkCollisionWithCapturedThisVariable(node, (<FunctionExpression>node).name);
|
||||
checkCollisionWithCapturedArgumentsVariable(node, (<FunctionExpression>node).name);
|
||||
}
|
||||
|
||||
return type;
|
||||
|
@ -7364,8 +7429,21 @@ module ts {
|
|||
|
||||
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
if (node.type && !node.asteriskToken) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
let returnType = node.type && getTypeFromTypeNode(node.type);
|
||||
let promisedType: Type;
|
||||
if (returnType && isAsync) {
|
||||
// From within an async function you can return either a non-promise value or a promise. Any
|
||||
// Promise/A+ compatible implementation will always assimilate any foreign promise, so we
|
||||
// should not be checking assignability of a promise to the return type. Instead, we need to
|
||||
// check assignability of the awaited type of the concise body against the promised type of
|
||||
// its return type annotation.
|
||||
promisedType = checkAsyncFunctionReturnType(node, returnType);
|
||||
}
|
||||
|
||||
if (returnType && !node.asteriskToken) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
|
||||
}
|
||||
|
||||
if (node.body) {
|
||||
|
@ -7374,8 +7452,11 @@ module ts {
|
|||
}
|
||||
else {
|
||||
let exprType = checkExpression(<Expression>node.body);
|
||||
if (node.type) {
|
||||
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
|
||||
if (returnType) {
|
||||
checkTypeAssignableTo(
|
||||
isAsync ? getAwaitedType(exprType) : exprType,
|
||||
isAsync ? promisedType : returnType,
|
||||
node.body);
|
||||
}
|
||||
checkFunctionExpressionBodies(node.body);
|
||||
}
|
||||
|
@ -7490,6 +7571,22 @@ module ts {
|
|||
return undefinedType;
|
||||
}
|
||||
|
||||
function checkAwaitExpression(node: AwaitExpression): Type {
|
||||
// Grammar checking
|
||||
if (!(node.parserContextFlags & ParserContextFlags.Await)) {
|
||||
var parameter = getContainingParameter(node);
|
||||
if (parameter && parameter.parserContextFlags & ParserContextFlags.Await) {
|
||||
grammarErrorAfterFirstToken(node, Diagnostics._0_expression_is_not_allowed_in_an_initializer, "await");
|
||||
}
|
||||
else {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.await_expression_must_be_contained_within_an_async_function);
|
||||
}
|
||||
}
|
||||
|
||||
var operandType = checkExpression(node.expression);
|
||||
return getAwaitedType(operandType);
|
||||
}
|
||||
|
||||
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
|
||||
// Grammar checking
|
||||
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
|
||||
|
@ -7897,7 +7994,13 @@ module ts {
|
|||
function checkYieldExpression(node: YieldExpression): void {
|
||||
// Grammar checking
|
||||
if (!(node.parserContextFlags & ParserContextFlags.Yield)) {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
|
||||
let parameter = getContainingParameter(node);
|
||||
if (parameter && (parameter.parserContextFlags & ParserContextFlags.GeneratorParameter)) {
|
||||
grammarErrorAfterFirstToken(node, Diagnostics._0_expression_is_not_allowed_in_an_initializer, "yield");
|
||||
}
|
||||
else {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.yield_expressions_are_not_currently_supported);
|
||||
|
@ -7931,6 +8034,15 @@ module ts {
|
|||
node.contextualType = saveContextualType;
|
||||
return result;
|
||||
}
|
||||
|
||||
function checkAwaitedExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedAwaitedType) {
|
||||
links.resolvedAwaitedType = getAwaitedType(checkExpressionCached(node, contextualMapper));
|
||||
}
|
||||
|
||||
return links.resolvedAwaitedType;
|
||||
}
|
||||
|
||||
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||
let links = getNodeLinks(node);
|
||||
|
@ -8078,6 +8190,8 @@ module ts {
|
|||
return checkDeleteExpression(<DeleteExpression>node);
|
||||
case SyntaxKind.VoidExpression:
|
||||
return checkVoidExpression(<VoidExpression>node);
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return checkAwaitExpression(<AwaitExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
|
@ -8166,6 +8280,7 @@ module ts {
|
|||
}
|
||||
|
||||
if (produceDiagnostics) {
|
||||
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
|
||||
checkCollisionWithArgumentsInGeneratedCode(node);
|
||||
if (compilerOptions.noImplicitAny && !node.type) {
|
||||
switch (node.kind) {
|
||||
|
@ -8177,6 +8292,22 @@ module ts {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
var promiseConstructor = getPromiseConstructor(node);
|
||||
if (promiseConstructor) {
|
||||
var promiseIdentifier = getFirstIdentifier(promiseConstructor);
|
||||
var promiseName = promiseIdentifier.text;
|
||||
var typeSymbol = resolveName(node, promiseName, SymbolFlags.Type | SymbolFlags.Module, undefined, undefined);
|
||||
var valueSymbol = resolveName(node, promiseName, SymbolFlags.Value, undefined, undefined);
|
||||
if (typeSymbol !== valueSymbol) {
|
||||
var valueLinks = getNodeLinks(valueSymbol.valueDeclaration);
|
||||
if (!(valueLinks.flags & NodeCheckFlags.PromiseCollision)) {
|
||||
valueLinks.flags |= NodeCheckFlags.PromiseCollision;
|
||||
error(valueSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, promiseName, getTextOfNode(promiseConstructor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkSpecializedSignatureDeclaration(node);
|
||||
|
@ -8772,6 +8903,113 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getPromisedType(type: Type): Type {
|
||||
// the "promised type" of a type is the type of the "value" argument of the "onfulfilled" callback.
|
||||
let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType();
|
||||
if (globalPromiseLikeType !== emptyObjectType && isTypeAssignableTo(type, globalPromiseLikeType)) {
|
||||
let awaitedTypes: Type[] = [];
|
||||
let thenProp = getPropertyOfType(type, "then");
|
||||
let thenType = getTypeOfSymbol(thenProp);
|
||||
let thenSignatures = getSignaturesOfType(thenType, SignatureKind.Call);
|
||||
for (let thenSignature of thenSignatures) {
|
||||
thenSignature = getErasedSignature(thenSignature);
|
||||
let onfulfilledParameterType = getTypeAtPosition(thenSignature, 0);
|
||||
let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
|
||||
for (let onfulfilledParameterSignature of onfulfilledParameterSignatures) {
|
||||
let valueParameterType = getTypeAtPosition(onfulfilledParameterSignature, 0);
|
||||
if (valueParameterType !== type) {
|
||||
awaitedTypes.push(valueParameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getUnionType(awaitedTypes);
|
||||
}
|
||||
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
function getAwaitedType(type: Type): Type {
|
||||
// The "awaited type" of an expression is its "promised type" if the expression is a `Promise`; otherwise, it is the type of the expression.
|
||||
|
||||
let promisedType = getPromisedType(type);
|
||||
if (promisedType === emptyObjectType) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// if we have a bad actor in the form of a promise whose promised type is the same promise, return the empty type.
|
||||
// if this were the actual case in the JavaScript, this Promise would never resolve.
|
||||
if (promisedType === type) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
// unwrap any nested promises
|
||||
let seen: boolean[];
|
||||
while (true) {
|
||||
let nestedPromisedType = getPromisedType(promisedType);
|
||||
if (nestedPromisedType === emptyObjectType) {
|
||||
// if this could not be unwrapped further, return the promised type
|
||||
return promisedType;
|
||||
}
|
||||
|
||||
if (!seen) {
|
||||
// `seen` keeps track of types we've tried to await to avoid cycles
|
||||
seen = [];
|
||||
seen[type.id] = true;
|
||||
seen[promisedType.id] = true;
|
||||
}
|
||||
else if (seen[nestedPromisedType.id]) {
|
||||
// if we've already seen this type, this is a promise that would never resolve. As above, we return the empty type.
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
seen[nestedPromisedType.id] = true;
|
||||
promisedType = nestedPromisedType;
|
||||
}
|
||||
|
||||
return promisedType;
|
||||
|
||||
// if we didn't get a promised type, check the type does not have a callable then member.
|
||||
if (isTypeAssignableTo(type, getGlobalThenableType())) {
|
||||
error(null, Diagnostics.Type_for_await_does_not_have_a_valid_callable_then_member);
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
// if the type was not a "promise" or a "thenable", return the type.
|
||||
return type;
|
||||
}
|
||||
|
||||
function checkAsyncFunctionReturnType(node: SignatureDeclaration, returnType: Type): Type {
|
||||
// This checks that an async function has a valid Promise-compatible return type, and returns the *awaited type* of the promise.
|
||||
// An async function has a valid Promise-compatible return type if the resolved value of the return type has a construct
|
||||
// signature that takes in an `initializer` function that in turn supplies a `resolve` function as one of its arguments
|
||||
// and results in an object with a callable `then` signature.
|
||||
let globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
|
||||
if (globalPromiseConstructorLikeType !== emptyObjectType) {
|
||||
if (!returnType) {
|
||||
returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
|
||||
}
|
||||
|
||||
// get the constructor type of the return type
|
||||
var declaredType = returnType.symbol ? getTypeOfSymbol(returnType.symbol) : emptyObjectType;
|
||||
if (isTypeAssignableTo(declaredType, globalPromiseConstructorLikeType)) {
|
||||
var promisedType = getPromisedType(returnType);
|
||||
if (promisedType !== emptyObjectType) {
|
||||
// unwrap the promised type
|
||||
var promiseConstructor = getPromiseConstructor(node);
|
||||
if (promiseConstructor) {
|
||||
emitAwaiter = true;
|
||||
checkExpressionOrQualifiedName(promiseConstructor);
|
||||
return getAwaitedType(promisedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error(node, ts.Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
/** Check a decorator */
|
||||
function checkDecorator(node: Decorator): void {
|
||||
let expression: Expression = node.expression;
|
||||
|
@ -8904,6 +9142,7 @@ module ts {
|
|||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithCapturedArgumentsVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
}
|
||||
}
|
||||
|
@ -8946,7 +9185,14 @@ module ts {
|
|||
|
||||
checkSourceElement(node.body);
|
||||
if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
let returnType = getTypeFromTypeNode(node.type);
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
let promisedType: Type;
|
||||
if (isAsync) {
|
||||
promisedType = checkAsyncFunctionReturnType(node, returnType);
|
||||
}
|
||||
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
|
||||
}
|
||||
|
||||
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
|
||||
|
@ -9016,6 +9262,12 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkCollisionWithCapturedArgumentsVariable(node: Node, name: Identifier): void {
|
||||
if (needCollisionCheckForIdentifier(node, name, "_arguments")) {
|
||||
potentialArgumentsCollisions.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
// this function will run after checking the source file so 'CaptureThis' is correct for all nodes
|
||||
function checkIfThisIsCapturedInEnclosingScope(node: Node): void {
|
||||
let current = node;
|
||||
|
@ -9034,6 +9286,25 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkIfArgumentsIsCapturedInEnclosingScope(node: Node): void {
|
||||
let current = node;
|
||||
while (current) {
|
||||
if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureArguments) {
|
||||
let isDeclaration = node.kind !== SyntaxKind.Identifier;
|
||||
if (isDeclaration) {
|
||||
error((<Declaration>node).name, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_variable_declaration_arguments_to_capture_arguments_reference);
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Expression_resolves_to_variable_declaration_arguments_that_compiler_uses_to_capture_arguments_reference);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
}
|
||||
|
||||
function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) {
|
||||
if (!needCollisionCheckForIdentifier(node, name, "_super")) {
|
||||
return;
|
||||
|
@ -9149,6 +9420,34 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getPromiseConstructor(node: SignatureDeclaration): EntityName {
|
||||
if (node.type && node.type.kind === SyntaxKind.TypeReference) {
|
||||
return (<TypeReferenceNode>node.type).typeName;
|
||||
}
|
||||
|
||||
let globalPromiseSymbol = getGlobalPromiseSymbol();
|
||||
if (globalPromiseSymbol && globalPromiseSymbol === resolveName(node, "Promise", SymbolFlags.Value, undefined, undefined)) {
|
||||
return <Identifier>globalPromiseSymbol.valueDeclaration.name;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function checkCollisionWithAwaiterVariablesInGeneratedCode(node: Node, name: DeclarationName): void {
|
||||
if (!name || name.kind !== SyntaxKind.Identifier || isTypeNode(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let identifier = <Identifier>name;
|
||||
let container = getContainingFunction(name);
|
||||
if (container && isAsyncFunctionLike(container) && node.kind !== SyntaxKind.Identifier) {
|
||||
var promiseConstructor = getPromiseConstructor(container);
|
||||
if (promiseConstructor && promiseConstructor.kind === SyntaxKind.Identifier && (<Identifier>promiseConstructor).text === identifier.text) {
|
||||
error(node, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, identifier.text, getTextOfNode(promiseConstructor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isParameterDeclaration(node: VariableLikeDeclaration) {
|
||||
while (node.kind === SyntaxKind.BindingElement) {
|
||||
node = <VariableLikeDeclaration>node.parent.parent;
|
||||
|
@ -9251,8 +9550,14 @@ module ts {
|
|||
}
|
||||
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithCapturedArgumentsVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
|
||||
}
|
||||
|
||||
if (symbol === argumentsSymbol && (node.parserContextFlags & ParserContextFlags.Await)) {
|
||||
let container = getContainingFunction(node);
|
||||
captureLexicalArguments(node.name, container);
|
||||
}
|
||||
}
|
||||
|
||||
function checkVariableDeclaration(node: VariableDeclaration) {
|
||||
|
@ -9275,7 +9580,10 @@ module ts {
|
|||
function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node: Node) {
|
||||
if (node.modifiers) {
|
||||
if (inBlockOrObjectLiteralExpression(node)) {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
|
||||
// disallow all but the `async` modifier here
|
||||
if (isAccessor(node.kind) || !isFunctionLike(node) || (node.modifiers.flags & ~NodeFlags.Async)) {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9288,6 +9596,8 @@ module ts {
|
|||
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkExpressionStatement(node: ExpressionStatement) {
|
||||
|
@ -9667,8 +9977,11 @@ module ts {
|
|||
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
|
||||
}
|
||||
}
|
||||
else if (func.type && !isAccessor(func.kind) && isAsyncFunctionLike(func)) {
|
||||
checkTypeAssignableTo(getAwaitedType(exprType), getPromisedType(returnType), node.expression);
|
||||
}
|
||||
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
|
||||
checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
|
||||
checkTypeAssignableTo(exprType, returnType, node.expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9943,6 +10256,7 @@ module ts {
|
|||
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
|
||||
}
|
||||
checkTypeParameters(node.typeParameters);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
|
@ -10386,6 +10700,7 @@ module ts {
|
|||
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
|
||||
computeEnumMemberValues(node);
|
||||
|
@ -10885,12 +11200,14 @@ module ts {
|
|||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.YieldExpression:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.VariableStatement:
|
||||
|
@ -10941,6 +11258,7 @@ module ts {
|
|||
emitDecorate = false;
|
||||
emitParam = false;
|
||||
potentialThisCollisions.length = 0;
|
||||
potentialArgumentsCollisions.length = 0;
|
||||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
checkFunctionExpressionBodies(node);
|
||||
|
@ -10953,6 +11271,11 @@ module ts {
|
|||
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
|
||||
potentialThisCollisions.length = 0;
|
||||
}
|
||||
|
||||
if (potentialArgumentsCollisions.length) {
|
||||
forEach(potentialArgumentsCollisions, checkIfArgumentsIsCapturedInEnclosingScope);
|
||||
potentialArgumentsCollisions.length = 0;
|
||||
}
|
||||
|
||||
if (emitExtends) {
|
||||
links.flags |= NodeCheckFlags.EmitExtends;
|
||||
|
@ -10965,6 +11288,14 @@ module ts {
|
|||
if (emitParam) {
|
||||
links.flags |= NodeCheckFlags.EmitParam;
|
||||
}
|
||||
|
||||
if (emitAwaiter) {
|
||||
links.flags |= NodeCheckFlags.EmitAwaiter;
|
||||
}
|
||||
|
||||
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
|
||||
links.flags |= NodeCheckFlags.EmitGenerator;
|
||||
}
|
||||
|
||||
links.flags |= NodeCheckFlags.TypeChecked;
|
||||
}
|
||||
|
@ -11982,6 +12313,12 @@ module ts {
|
|||
getGlobalPropertyDecoratorType = memoize(() => getGlobalType("PropertyDecorator"));
|
||||
getGlobalMethodDecoratorType = memoize(() => getGlobalType("MethodDecorator"));
|
||||
getGlobalParameterDecoratorType = memoize(() => getGlobalType("ParameterDecorator"));
|
||||
getGlobalPromiseSymbol = memoize(() => getGlobalTypeSymbol("Promise"));
|
||||
getGlobalPromiseType = memoize(() => getTypeOfGlobalSymbol(getGlobalPromiseSymbol(), /*arity*/ 1));
|
||||
getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
|
||||
getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
|
||||
getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
|
||||
getGlobalThenableType = memoize(createThenableType);
|
||||
|
||||
// If we're in ES6 mode, load the TemplateStringsArray.
|
||||
// Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
|
||||
|
@ -12003,6 +12340,26 @@ module ts {
|
|||
|
||||
anyArrayType = createArrayType(anyType);
|
||||
}
|
||||
|
||||
function createInstantiatedPromiseLikeType(): ObjectType {
|
||||
let promiseLikeType = getGlobalPromiseLikeType();
|
||||
if (promiseLikeType !== emptyObjectType) {
|
||||
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
|
||||
}
|
||||
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
function createThenableType() {
|
||||
// build the thenable type that is used to verify against a non-promise "thenable" operand to `await`.
|
||||
let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
|
||||
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
|
||||
|
||||
let thenableType = <ResolvedType>createObjectType(TypeFlags.ObjectType);
|
||||
thenableType.properties = [thenPropertySymbol];
|
||||
thenableType.members = createSymbolTable(thenableType.properties);
|
||||
return thenableType;
|
||||
}
|
||||
|
||||
// GRAMMAR CHECKING
|
||||
function isReservedWordInStrictMode(node: Identifier): boolean {
|
||||
|
@ -12203,7 +12560,7 @@ module ts {
|
|||
return;
|
||||
}
|
||||
|
||||
let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node;
|
||||
let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node, lastAsync: Node;
|
||||
let flags = 0;
|
||||
for (let modifier of node.modifiers) {
|
||||
switch (modifier.kind) {
|
||||
|
@ -12229,6 +12586,9 @@ module ts {
|
|||
else if (flags & NodeFlags.Static) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async");
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
|
||||
}
|
||||
|
@ -12239,6 +12599,9 @@ module ts {
|
|||
if (flags & NodeFlags.Static) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async");
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
|
||||
}
|
||||
|
@ -12256,6 +12619,9 @@ module ts {
|
|||
else if (flags & NodeFlags.Ambient) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async");
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
|
||||
}
|
||||
|
@ -12269,6 +12635,9 @@ module ts {
|
|||
if (flags & NodeFlags.Ambient) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
|
||||
}
|
||||
|
@ -12281,6 +12650,20 @@ module ts {
|
|||
flags |= NodeFlags.Ambient;
|
||||
lastDeclare = modifier
|
||||
break;
|
||||
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async");
|
||||
}
|
||||
else if (flags & NodeFlags.Ambient || isInAmbientContext(node.parent)) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
|
||||
}
|
||||
else if (node.kind === SyntaxKind.Parameter) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async");
|
||||
}
|
||||
flags |= NodeFlags.Async;
|
||||
lastAsync = modifier;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12294,16 +12677,42 @@ module ts {
|
|||
else if (flags & NodeFlags.Private) {
|
||||
return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) {
|
||||
return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
|
||||
return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
|
||||
}
|
||||
else if (node.kind === SyntaxKind.InterfaceDeclaration && flags & NodeFlags.Ambient) {
|
||||
return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
|
||||
return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_interface_declaration, "declare");
|
||||
}
|
||||
else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) && isBindingPattern((<ParameterDeclaration>node).name)) {
|
||||
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
|
||||
}
|
||||
if (flags & NodeFlags.Async) {
|
||||
return checkGrammarAsyncModifier(node, lastAsync);
|
||||
}
|
||||
}
|
||||
|
||||
function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
|
||||
if (languageVersion < ScriptTarget.ES6) {
|
||||
return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher);
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
if (!(<FunctionLikeDeclaration>node).asteriskToken) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async");
|
||||
}
|
||||
|
||||
function checkGrammarForDisallowedTrailingComma(list: NodeArray<Node>): boolean {
|
||||
|
|
|
@ -34,8 +34,12 @@ module ts {
|
|||
Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
|
||||
A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
|
||||
Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
|
||||
_0_modifier_cannot_be_used_in_an_ambient_context: { code: 1040, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used in an ambient context." },
|
||||
_0_modifier_cannot_be_used_with_a_class_declaration: { code: 1041, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a class declaration." },
|
||||
_0_modifier_cannot_be_used_here: { code: 1042, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used here." },
|
||||
_0_modifier_cannot_appear_on_a_data_property: { code: 1043, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a data property." },
|
||||
_0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
|
||||
A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
|
||||
A_0_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A '{0}' modifier cannot be used with an interface declaration." },
|
||||
A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
|
||||
A_rest_parameter_cannot_be_optional: { code: 1047, category: DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
|
||||
A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
|
||||
|
@ -45,11 +49,13 @@ module ts {
|
|||
A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
|
||||
A_get_accessor_cannot_have_parameters: { code: 1054, category: DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
|
||||
Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
|
||||
An_async_function_or_method_must_have_a_valid_awaitable_return_type: { code: 1057, category: DiagnosticCategory.Error, key: "An async function or method must have a valid awaitable return type." },
|
||||
Type_for_await_does_not_have_a_valid_callable_then_member: { code: 1058, category: DiagnosticCategory.Error, key: "Type for 'await' does not have a valid callable 'then' member." },
|
||||
Enum_member_must_have_initializer: { code: 1061, category: DiagnosticCategory.Error, key: "Enum member must have initializer." },
|
||||
An_export_assignment_cannot_be_used_in_a_namespace: { code: 1063, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in a namespace." },
|
||||
Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
|
||||
Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
|
||||
A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
|
||||
A_0_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A '{0}' modifier cannot be used with an import declaration." },
|
||||
Invalid_reference_directive_syntax: { code: 1084, category: DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
|
||||
Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
|
||||
An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
|
||||
|
@ -120,7 +126,7 @@ module ts {
|
|||
Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
|
||||
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
|
||||
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
|
||||
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
|
||||
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained within a generator declaration." },
|
||||
Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
|
||||
A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
|
||||
A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
|
||||
|
@ -174,6 +180,18 @@ module ts {
|
|||
Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
|
||||
Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
|
||||
Export_assignment_is_not_supported_when_module_flag_is_system: { code: 1218, category: DiagnosticCategory.Error, key: "Export assignment is not supported when '--module' flag is 'system'." },
|
||||
with_statements_are_not_allowed_in_an_async_function_block: { code: 1300, category: DiagnosticCategory.Error, key: "'with' statements are not allowed in an async function block." },
|
||||
_0_modifier_cannot_be_used_with_a_generator: { code: 1301, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a generator." },
|
||||
_0_modifier_cannot_be_used_with_a_module_declaration: { code: 1302, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a module declaration." },
|
||||
_0_modifier_cannot_be_used_with_an_enum_declaration: { code: 1303, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with an enum declaration." },
|
||||
_0_modifier_cannot_be_used_with_an_export_assignment_declaration: { code: 1304, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with an export assignment declaration." },
|
||||
_0_modifier_cannot_be_used_on_a_variable_statement: { code: 1305, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used on a variable statement." },
|
||||
_0_modifier_cannot_be_used_with_a_type_declaration: { code: 1306, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a type declaration." },
|
||||
_0_modifier_cannot_be_used_with_a_parameter_declaration: { code: 1307, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a parameter declaration." },
|
||||
await_expression_must_be_contained_within_an_async_function: { code: 1308, category: DiagnosticCategory.Error, key: "'await' expression must be contained within an async function." },
|
||||
_0_modifier_cannot_be_used_on_an_object_literal_element: { code: 1309, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used on an object literal element." },
|
||||
_0_expression_is_not_allowed_in_an_initializer: { code: 1310, category: DiagnosticCategory.Error, key: "'{0}' expression is not allowed in an initializer." },
|
||||
Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1311, category: DiagnosticCategory.Error, key: "Async functions are only available when targeting ECMAScript 6 and higher." },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
|
||||
|
@ -363,6 +381,10 @@ module ts {
|
|||
An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
|
||||
A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
|
||||
A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
|
||||
Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." },
|
||||
Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." },
|
||||
Duplicate_identifier_arguments_Compiler_uses_variable_declaration_arguments_to_capture_arguments_reference: { code: 2522, category: DiagnosticCategory.Error, key: "Duplicate identifier '_arguments'. Compiler uses variable declaration '_arguments' to capture 'arguments' reference." },
|
||||
Expression_resolves_to_variable_declaration_arguments_that_compiler_uses_to_capture_arguments_reference: { code: 2523, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_arguments' that compiler uses to capture 'arguments' reference." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
|
||||
|
@ -505,6 +527,7 @@ module ts {
|
|||
Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix: { code: 6060, category: DiagnosticCategory.Message, key: "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix)." },
|
||||
NEWLINE: { code: 6061, category: DiagnosticCategory.Message, key: "NEWLINE" },
|
||||
Argument_for_newLine_option_must_be_CRLF_or_LF: { code: 6062, category: DiagnosticCategory.Error, key: "Argument for '--newLine' option must be 'CRLF' or 'LF'." },
|
||||
Emit_async_functions_when_ECMAScript_target_version_is_lower_than_ES6: { code: 6063, category: DiagnosticCategory.Message, key: "Emit async functions when ECMAScript target version is lower than 'ES6'." },
|
||||
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
|
||||
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
|
||||
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
|
||||
|
|
|
@ -123,11 +123,27 @@
|
|||
"category": "Error",
|
||||
"code": 1039
|
||||
},
|
||||
"'{0}' modifier cannot be used in an ambient context.": {
|
||||
"category": "Error",
|
||||
"code": 1040
|
||||
},
|
||||
"'{0}' modifier cannot be used with a class declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1041
|
||||
},
|
||||
"'{0}' modifier cannot be used here.": {
|
||||
"category": "Error",
|
||||
"code": 1042
|
||||
},
|
||||
"'{0}' modifier cannot appear on a data property.": {
|
||||
"category": "Error",
|
||||
"code": 1043
|
||||
},
|
||||
"'{0}' modifier cannot appear on a module element.": {
|
||||
"category": "Error",
|
||||
"code": 1044
|
||||
},
|
||||
"A 'declare' modifier cannot be used with an interface declaration.": {
|
||||
"A '{0}' modifier cannot be used with an interface declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1045
|
||||
},
|
||||
|
@ -167,6 +183,14 @@
|
|||
"category": "Error",
|
||||
"code": 1056
|
||||
},
|
||||
"An async function or method must have a valid awaitable return type.": {
|
||||
"category": "Error",
|
||||
"code": 1057
|
||||
},
|
||||
"Type for 'await' does not have a valid callable 'then' member.": {
|
||||
"category": "Error",
|
||||
"code": 1058
|
||||
},
|
||||
"Enum member must have initializer.": {
|
||||
"category": "Error",
|
||||
"code": 1061
|
||||
|
@ -183,7 +207,7 @@
|
|||
"category": "Error",
|
||||
"code": 1068
|
||||
},
|
||||
"A 'declare' modifier cannot be used with an import declaration.": {
|
||||
"A '{0}' modifier cannot be used with an import declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1079
|
||||
},
|
||||
|
@ -467,7 +491,7 @@
|
|||
"category": "Error",
|
||||
"code": 1162
|
||||
},
|
||||
"'yield' expression must be contained_within a generator declaration.": {
|
||||
"'yield' expression must be contained within a generator declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1163
|
||||
},
|
||||
|
@ -684,6 +708,55 @@
|
|||
"code": 1218
|
||||
},
|
||||
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
},
|
||||
"'{0}' modifier cannot be used with a generator.": {
|
||||
"category": "Error",
|
||||
"code": 1301
|
||||
},
|
||||
"'{0}' modifier cannot be used with a module declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1302
|
||||
},
|
||||
"'{0}' modifier cannot be used with an enum declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1303
|
||||
},
|
||||
"'{0}' modifier cannot be used with an export assignment declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1304
|
||||
},
|
||||
"'{0}' modifier cannot be used on a variable statement.": {
|
||||
"category": "Error",
|
||||
"code": 1305
|
||||
},
|
||||
"'{0}' modifier cannot be used with a type declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1306
|
||||
},
|
||||
"'{0}' modifier cannot be used with a parameter declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1307
|
||||
},
|
||||
"'await' expression must be contained within an async function.": {
|
||||
"category": "Error",
|
||||
"code": 1308
|
||||
},
|
||||
"'{0}' modifier cannot be used on an object literal element.": {
|
||||
"category": "Error",
|
||||
"code": 1309
|
||||
},
|
||||
"'{0}' expression is not allowed in an initializer.": {
|
||||
"category": "Error",
|
||||
"code": 1310
|
||||
},
|
||||
"Async functions are only available when targeting ECMAScript 6 and higher.": {
|
||||
"category": "Error",
|
||||
"code": 1311
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2300
|
||||
|
@ -1441,6 +1514,23 @@
|
|||
"code": 2501
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
|
||||
"category": "Error",
|
||||
"code": 2520
|
||||
},
|
||||
"Expression resolves to variable declaration '{0}' that compiler uses to support async functions.": {
|
||||
"category": "Error",
|
||||
"code": 2521
|
||||
},
|
||||
"Duplicate identifier '_arguments'. Compiler uses variable declaration '_arguments' to capture 'arguments' reference.": {
|
||||
"category": "Error",
|
||||
"code": 2522
|
||||
},
|
||||
"Expression resolves to variable declaration '_arguments' that compiler uses to capture 'arguments' reference.": {
|
||||
"category": "Error",
|
||||
"code": 2523
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
|
@ -2010,7 +2100,10 @@
|
|||
"category": "Error",
|
||||
"code": 6062
|
||||
},
|
||||
|
||||
"Emit async functions when ECMAScript target version is lower than 'ES6'.": {
|
||||
"category": "Message",
|
||||
"code": 6063
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
|
|
@ -153,6 +153,8 @@ module ts {
|
|||
case SyntaxKind.YieldExpression:
|
||||
return visitNode(cbNode, (<YieldExpression>node).asteriskToken) ||
|
||||
visitNode(cbNode, (<YieldExpression>node).expression);
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return visitNode(cbNode, (<AwaitExpression>node).expression);
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
|
@ -556,9 +558,17 @@ module ts {
|
|||
function setDecoratorContext(val: boolean) {
|
||||
setContextFlag(val, ParserContextFlags.Decorator);
|
||||
}
|
||||
|
||||
function doOutsideOfContext<T>(flags: ParserContextFlags, func: () => T): T {
|
||||
let currentContextFlags = contextFlags & flags;
|
||||
|
||||
function setAwaitContext(val: boolean) {
|
||||
setContextFlag(val, ParserContextFlags.Await);
|
||||
}
|
||||
|
||||
function setAsyncParameterContext(val: boolean) {
|
||||
setContextFlag(val, ParserContextFlags.AsyncParameter);
|
||||
}
|
||||
|
||||
function doOutsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
|
||||
let currentContextFlags = contextFlags & context;
|
||||
if (currentContextFlags) {
|
||||
setContextFlag(false, currentContextFlags);
|
||||
let result = func();
|
||||
|
@ -569,85 +579,86 @@ module ts {
|
|||
// no need to do anything special as we are not in any of the requested contexts
|
||||
return func();
|
||||
}
|
||||
|
||||
function allowInAnd<T>(func: () => T): T {
|
||||
if (contextFlags & ParserContextFlags.DisallowIn) {
|
||||
setDisallowInContext(false);
|
||||
|
||||
function doInsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
|
||||
let unsetContextFlags = context & ~contextFlags;
|
||||
if (!unsetContextFlags) {
|
||||
setContextFlag(true, unsetContextFlags);
|
||||
let result = func();
|
||||
setDisallowInContext(true);
|
||||
setContextFlag(false, unsetContextFlags);
|
||||
return result;
|
||||
}
|
||||
|
||||
// no need to do anything special if 'in' is already allowed.
|
||||
|
||||
// no need to do anything special as we are already in all of the requested contexts
|
||||
return func();
|
||||
}
|
||||
|
||||
function allowInAnd<T>(func: () => T): T {
|
||||
return doInsideOfContext(ParserContextFlags.DisallowIn, func);
|
||||
}
|
||||
|
||||
function disallowInAnd<T>(func: () => T): T {
|
||||
if (contextFlags & ParserContextFlags.DisallowIn) {
|
||||
// no need to do anything special if 'in' is already disallowed.
|
||||
return func();
|
||||
}
|
||||
|
||||
setDisallowInContext(true);
|
||||
let result = func();
|
||||
setDisallowInContext(false);
|
||||
return result;
|
||||
return doOutsideOfContext(ParserContextFlags.DisallowIn, func);
|
||||
}
|
||||
|
||||
|
||||
function doInYieldContext<T>(func: () => T): T {
|
||||
if (contextFlags & ParserContextFlags.Yield) {
|
||||
// no need to do anything special if we're already in the [Yield] context.
|
||||
return func();
|
||||
}
|
||||
|
||||
setYieldContext(true);
|
||||
let result = func();
|
||||
setYieldContext(false);
|
||||
return result;
|
||||
return doInsideOfContext(ParserContextFlags.Yield, func);
|
||||
}
|
||||
|
||||
function doOutsideOfYieldContext<T>(func: () => T): T {
|
||||
if (contextFlags & ParserContextFlags.Yield) {
|
||||
setYieldContext(false);
|
||||
let result = func();
|
||||
setYieldContext(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
// no need to do anything special if we're not in the [Yield] context.
|
||||
return func();
|
||||
return doOutsideOfContext(ParserContextFlags.Yield, func);
|
||||
}
|
||||
|
||||
function doInDecoratorContext<T>(func: () => T): T {
|
||||
if (contextFlags & ParserContextFlags.Decorator) {
|
||||
// no need to do anything special if we're already in the [Decorator] context.
|
||||
return func();
|
||||
}
|
||||
|
||||
setDecoratorContext(true);
|
||||
let result = func();
|
||||
setDecoratorContext(false);
|
||||
return result;
|
||||
return doInsideOfContext(ParserContextFlags.Decorator, func);
|
||||
}
|
||||
|
||||
function doInAwaitContext<T>(func: () => T): T {
|
||||
return doInsideOfContext(ParserContextFlags.Await, func);
|
||||
}
|
||||
|
||||
function doOutsideOfAwaitContext<T>(func: () => T): T {
|
||||
return doOutsideOfContext(ParserContextFlags.Await, func);
|
||||
}
|
||||
|
||||
function doOutsideOfYieldAndAwaitContext<T>(func: () => T): T {
|
||||
return doOutsideOfContext(ParserContextFlags.Yield | ParserContextFlags.Await, func);
|
||||
}
|
||||
|
||||
function inContext(flags: ParserContextFlags) {
|
||||
return (contextFlags & flags) === flags;
|
||||
}
|
||||
|
||||
function inYieldContext() {
|
||||
return (contextFlags & ParserContextFlags.Yield) !== 0;
|
||||
return inContext(ParserContextFlags.Yield);
|
||||
}
|
||||
|
||||
function inStrictModeContext() {
|
||||
return (contextFlags & ParserContextFlags.StrictMode) !== 0;
|
||||
return inContext(ParserContextFlags.StrictMode);
|
||||
}
|
||||
|
||||
function inGeneratorParameterContext() {
|
||||
return (contextFlags & ParserContextFlags.GeneratorParameter) !== 0;
|
||||
return inContext(ParserContextFlags.GeneratorParameter);
|
||||
}
|
||||
|
||||
function inDisallowInContext() {
|
||||
return (contextFlags & ParserContextFlags.DisallowIn) !== 0;
|
||||
return inContext(ParserContextFlags.DisallowIn);
|
||||
}
|
||||
|
||||
function inDecoratorContext() {
|
||||
return (contextFlags & ParserContextFlags.Decorator) !== 0;
|
||||
return inContext(ParserContextFlags.Decorator);
|
||||
}
|
||||
|
||||
function inAwaitContext() {
|
||||
return inContext(ParserContextFlags.Await);
|
||||
}
|
||||
|
||||
function inAsyncParameterContext() {
|
||||
return inContext(ParserContextFlags.AsyncParameter);
|
||||
}
|
||||
|
||||
function inGeneratorParameterOrAsyncParameterContext() {
|
||||
return inContext(ParserContextFlags.GeneratorParameter | ParserContextFlags.AsyncParameter);
|
||||
}
|
||||
|
||||
function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
|
||||
|
@ -927,7 +938,8 @@ module ts {
|
|||
// PropertyName[Yield,GeneratorParameter] :
|
||||
// LiteralPropertyName
|
||||
// [+GeneratorParameter] ComputedPropertyName
|
||||
// [~GeneratorParameter] ComputedPropertyName[?Yield]
|
||||
// [+AsyncParameter] ComputedPropertyName
|
||||
// [~GeneratorParameter,~AsyncParameter] ComputedPropertyName[?Yield,?Await]
|
||||
//
|
||||
// ComputedPropertyName[Yield] :
|
||||
// [ AssignmentExpression[In, ?Yield] ]
|
||||
|
@ -938,34 +950,40 @@ module ts {
|
|||
// We parse any expression (including a comma expression). But the grammar
|
||||
// says that only an assignment expression is allowed, so the grammar checker
|
||||
// will error if it sees a comma expression.
|
||||
let yieldContext = inYieldContext();
|
||||
if (inGeneratorParameterContext()) {
|
||||
setYieldContext(false);
|
||||
}
|
||||
|
||||
node.expression = allowInAnd(parseExpression);
|
||||
if (inGeneratorParameterContext()) {
|
||||
setYieldContext(yieldContext);
|
||||
}
|
||||
node.expression = inGeneratorParameterOrAsyncParameterContext()
|
||||
? doOutsideOfYieldAndAwaitContext(parseExpression)
|
||||
: parseExpression();
|
||||
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseContextualModifier(t: SyntaxKind): boolean {
|
||||
return token === t && tryParse(nextTokenCanFollowModifier);
|
||||
function parseContextualModifier(t: SyntaxKind, isArrowFunction?: boolean): boolean {
|
||||
return token === t && tryParse(isArrowFunction
|
||||
? nextTokenCanFollowModifierForArrowFunction
|
||||
: nextTokenCanFollowModifier);
|
||||
}
|
||||
|
||||
function nextTokenCanFollowModifierForArrowFunction() {
|
||||
return nextTokenCanFollowModifier(/*isArrowFunction*/ true);
|
||||
}
|
||||
|
||||
function nextTokenCanFollowModifier() {
|
||||
function nextTokenCanFollowModifier(isArrowFunction?: boolean) {
|
||||
nextToken();
|
||||
return canFollowModifier();
|
||||
return canFollowModifier(isArrowFunction);
|
||||
}
|
||||
|
||||
function parseAnyContextualModifier(): boolean {
|
||||
return isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
|
||||
function parseAnyContextualModifier(isArrowFunction?: boolean): boolean {
|
||||
return isModifier(token) && tryParse(isArrowFunction
|
||||
? nextTokenCanFollowContextualModifierForArrowFunction
|
||||
: nextTokenCanFollowContextualModifier);
|
||||
}
|
||||
|
||||
function nextTokenCanFollowContextualModifierForArrowFunction() {
|
||||
return nextTokenCanFollowContextualModifier(/*isArrowFunction*/ true);
|
||||
}
|
||||
|
||||
function nextTokenCanFollowContextualModifier() {
|
||||
function nextTokenCanFollowContextualModifier(isArrowFunction?: boolean) {
|
||||
if (token === SyntaxKind.ConstKeyword) {
|
||||
// 'const' is only a modifier if followed by 'enum'.
|
||||
return nextToken() === SyntaxKind.EnumKeyword;
|
||||
|
@ -981,10 +999,19 @@ module ts {
|
|||
return nextTokenIsClassOrFunction();
|
||||
}
|
||||
nextToken();
|
||||
return canFollowModifier();
|
||||
return canFollowModifier(isArrowFunction);
|
||||
}
|
||||
|
||||
function canFollowModifier(): boolean {
|
||||
function canFollowModifier(isArrowFunction?: boolean): boolean {
|
||||
if (isArrowFunction) {
|
||||
if (scanner.hasPrecedingLineBreak()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return token === SyntaxKind.OpenParenToken
|
||||
|| token === SyntaxKind.LessThanToken;
|
||||
}
|
||||
|
||||
return token === SyntaxKind.OpenBracketToken
|
||||
|| token === SyntaxKind.OpenBraceToken
|
||||
|| token === SyntaxKind.AsteriskToken
|
||||
|
@ -1827,11 +1854,10 @@ module ts {
|
|||
setModifiers(node, parseModifiers());
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
|
||||
// SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3
|
||||
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
|
||||
// FormalParameter[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.1
|
||||
// BindingElement[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
|
||||
|
||||
node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
|
||||
node.name = parseIdentifierOrPattern();
|
||||
|
||||
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
|
||||
// in cases like
|
||||
|
@ -1847,7 +1873,7 @@ module ts {
|
|||
|
||||
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
|
||||
node.type = parseParameterType();
|
||||
node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ true);
|
||||
|
||||
// Do not check for initializers in an ambient context for parameters. This is not
|
||||
// a grammar error because the grammar allows arbitrary call signatures in
|
||||
|
@ -1859,19 +1885,36 @@ module ts {
|
|||
// ambient contexts.
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseBindingElementInitializer(inParameter: boolean) {
|
||||
// BindingElement[Yield,GeneratorParameter,Await,AsyncParameter] :
|
||||
// [+GeneratorParameter] BindingPattern[?Yield,?Await,GeneratorParameter] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingPattern[?Yield,?Await,AsyncParameter] Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter] BindingPattern[?Yield,?Await] Initializer[In,?Yield,?Await]opt
|
||||
// SingleNameBinding[Yield,GeneratorParameter,Await,AsyncParameter] :
|
||||
// [+GeneratorParameter] BindingIdentifier[Yield] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingIdentifier[Await] Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter] BindingIdentifier[?Yield,?Await] Initializer[In,?Yield,?Await]opt
|
||||
|
||||
let parseInitializer = inParameter ? parseParameterInitializer : parseNonParameterInitializer;
|
||||
return inGeneratorParameterOrAsyncParameterContext()
|
||||
? doOutsideOfYieldAndAwaitContext(parseInitializer)
|
||||
: parseInitializer();
|
||||
}
|
||||
|
||||
function parseParameterInitializer() {
|
||||
return parseInitializer(/*inParameter*/ true);
|
||||
}
|
||||
|
||||
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind,
|
||||
yieldAndGeneratorParameterContext: boolean,
|
||||
awaitAndAsyncParameterContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
signature: SignatureDeclaration): void {
|
||||
let returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken;
|
||||
signature.typeParameters = parseTypeParameters();
|
||||
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
|
||||
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, awaitAndAsyncParameterContext, requireCompleteParameterList);
|
||||
|
||||
if (returnTokenRequired) {
|
||||
parseExpected(returnToken);
|
||||
|
@ -1886,32 +1929,48 @@ module ts {
|
|||
// have 'Yield' And 'GeneratorParameter' not in sync. i.e. any production calling
|
||||
// this FormalParameters production either always sets both to true, or always sets
|
||||
// both to false. As such we only have a single parameter to represent both.
|
||||
function parseParameterList(yieldAndGeneratorParameterContext: boolean, requireCompleteParameterList: boolean) {
|
||||
// FormalParameters[Yield,GeneratorParameter] :
|
||||
function parseParameterList(yieldAndGeneratorParameterContext: boolean, awaitAndAsyncParameterContext: boolean, requireCompleteParameterList: boolean) {
|
||||
// FormalParameters[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified)
|
||||
// ...
|
||||
//
|
||||
// FormalParameter[Yield,GeneratorParameter] :
|
||||
// BindingElement[?Yield, ?GeneratorParameter]
|
||||
// FormalParameter[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified)
|
||||
// BindingElement[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
|
||||
//
|
||||
// BindingElement[Yield, GeneratorParameter ] : See 13.2.3
|
||||
// SingleNameBinding[?Yield, ?GeneratorParameter]
|
||||
// [+GeneratorParameter]BindingPattern[?Yield, GeneratorParameter]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingPattern[?Yield]Initializer[In, ?Yield]opt
|
||||
// BindingElement[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 13.2.3
|
||||
// SingleNameBinding[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
|
||||
// [+GeneratorParameter]BindingPattern[?Yield,?Await,?AsyncParameter,GeneratorParameter] Initializer[In]opt
|
||||
// [+AsyncParameter]BindingPattern[?Yield,?Await,?GeneratorParameter,AsyncParameter] Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter]BindingPattern[?Yield,?Await]Initializer[In,?Yield,?Await]opt
|
||||
//
|
||||
// SingleNameBinding[Yield, GeneratorParameter] : See 13.2.3
|
||||
// SingleNameBinding[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 13.2.3
|
||||
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
|
||||
// [+AsyncParameter]BindingIdentifier[Await]Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter]BindingIdentifier[?Yield,?Await]Initializer[In,?Yield,?Await]opt
|
||||
if (parseExpected(SyntaxKind.OpenParenToken)) {
|
||||
let savedYieldContext = inYieldContext();
|
||||
let savedGeneratorParameterContext = inGeneratorParameterContext();
|
||||
let savedAwaitContext = inAwaitContext();
|
||||
let savedAsyncParameterContext = inAsyncParameterContext();
|
||||
|
||||
setYieldContext(yieldAndGeneratorParameterContext);
|
||||
if (yieldAndGeneratorParameterContext) {
|
||||
setYieldContext(true);
|
||||
}
|
||||
|
||||
setGeneratorParameterContext(yieldAndGeneratorParameterContext);
|
||||
|
||||
if (awaitAndAsyncParameterContext) {
|
||||
setAwaitContext(true);
|
||||
}
|
||||
|
||||
setAsyncParameterContext(awaitAndAsyncParameterContext);
|
||||
|
||||
let result = parseDelimitedList(ParsingContext.Parameters, parseParameter);
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setGeneratorParameterContext(savedGeneratorParameterContext);
|
||||
|
||||
setAwaitContext(savedAwaitContext);
|
||||
setAsyncParameterContext(savedAsyncParameterContext);
|
||||
|
||||
if (!parseExpected(SyntaxKind.CloseParenToken) && requireCompleteParameterList) {
|
||||
// Caller insisted that we had to end with a ) We didn't. So just return
|
||||
|
@ -1944,7 +2003,7 @@ module ts {
|
|||
if (kind === SyntaxKind.ConstructSignature) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
@ -2034,7 +2093,7 @@ module ts {
|
|||
|
||||
// Method signatues don't exist in expression contexts. So they have neither
|
||||
// [Yield] nor [GeneratorParameter]
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, method);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, method);
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(method);
|
||||
}
|
||||
|
@ -2173,7 +2232,7 @@ module ts {
|
|||
if (kind === SyntaxKind.ConstructorType) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -2302,19 +2361,8 @@ module ts {
|
|||
|
||||
function parseType(): TypeNode {
|
||||
// The rules about 'yield' only apply to actual code/expression contexts. They don't
|
||||
// apply to 'type' contexts. So we disable these parameters here before moving on.
|
||||
let savedYieldContext = inYieldContext();
|
||||
let savedGeneratorParameterContext = inGeneratorParameterContext();
|
||||
|
||||
setYieldContext(false);
|
||||
setGeneratorParameterContext(false);
|
||||
|
||||
let result = parseTypeWorker();
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setGeneratorParameterContext(savedGeneratorParameterContext);
|
||||
|
||||
return result;
|
||||
// apply to 'type' contexts. So we disable these parameters here before moving on.
|
||||
return doOutsideOfContext(ParserContextFlags.ContextParameterFlags, parseTypeWorker);
|
||||
}
|
||||
|
||||
function parseTypeWorker(): TypeNode {
|
||||
|
@ -2374,6 +2422,7 @@ module ts {
|
|||
case SyntaxKind.PlusPlusToken:
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
case SyntaxKind.LessThanToken:
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
case SyntaxKind.YieldKeyword:
|
||||
// Yield always starts an expression. Either it is an identifier (in which case
|
||||
// it is definitely an expression). Or it's a keyword (either because we're in
|
||||
|
@ -2586,7 +2635,7 @@ module ts {
|
|||
node.parameters.end = parameter.end;
|
||||
|
||||
node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>");
|
||||
node.body = parseArrowFunctionExpressionBody();
|
||||
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ false);
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
|
@ -2617,7 +2666,7 @@ module ts {
|
|||
var lastToken = token;
|
||||
arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition:*/false, Diagnostics._0_expected, "=>");
|
||||
arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
|
||||
? parseArrowFunctionExpressionBody()
|
||||
? parseArrowFunctionExpressionBody(/*isAsync*/ isAsyncFunctionLike(arrowFunction))
|
||||
: parseIdentifier();
|
||||
|
||||
return finishNode(arrowFunction);
|
||||
|
@ -2628,7 +2677,7 @@ module ts {
|
|||
// Unknown -> There *might* be a parenthesized arrow function here.
|
||||
// Speculatively look ahead to be sure, and rollback if not.
|
||||
function isParenthesizedArrowFunctionExpression(): Tristate {
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken || token === SyntaxKind.AsyncKeyword) {
|
||||
return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
|
||||
}
|
||||
|
||||
|
@ -2643,6 +2692,10 @@ module ts {
|
|||
}
|
||||
|
||||
function isParenthesizedArrowFunctionExpressionWorker() {
|
||||
if (token === SyntaxKind.AsyncKeyword && !parseContextualModifier(SyntaxKind.AsyncKeyword, /*isArrowFunction*/ true)) {
|
||||
return Tristate.False;
|
||||
}
|
||||
|
||||
let first = token;
|
||||
let second = nextToken();
|
||||
|
||||
|
@ -2718,6 +2771,9 @@ module ts {
|
|||
|
||||
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
|
||||
let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
|
||||
setModifiers(node, parseModifiers(/*isArrowFunction*/ true));
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
|
||||
// Arrow functions are never generators.
|
||||
//
|
||||
// If we're speculatively parsing a signature for a parenthesized arrow function, then
|
||||
|
@ -2725,7 +2781,7 @@ module ts {
|
|||
// a => (b => c)
|
||||
// And think that "(b =>" was actually a parenthesized arrow function with a missing
|
||||
// close paren.
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
|
||||
|
||||
// If we couldn't get parameters, we definitely could not parse out an arrow function.
|
||||
if (!node.parameters) {
|
||||
|
@ -2748,9 +2804,9 @@ module ts {
|
|||
return node;
|
||||
}
|
||||
|
||||
function parseArrowFunctionExpressionBody(): Block | Expression {
|
||||
function parseArrowFunctionExpressionBody(isAsync: boolean): Block | Expression {
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
|
||||
return parseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
|
||||
}
|
||||
|
||||
if (isStartOfStatement(/*inErrorRecovery:*/ true) &&
|
||||
|
@ -2772,10 +2828,12 @@ module ts {
|
|||
// up preemptively closing the containing construct.
|
||||
//
|
||||
// Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
|
||||
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
|
||||
return parseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ true);
|
||||
}
|
||||
|
||||
return parseAssignmentExpressionOrHigher();
|
||||
|
||||
return isAsync
|
||||
? doInAwaitContext(parseAssignmentExpressionOrHigher)
|
||||
: doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher);
|
||||
}
|
||||
|
||||
function parseConditionalExpressionRest(leftOperand: Expression): Expression {
|
||||
|
@ -2915,8 +2973,32 @@ module ts {
|
|||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function isAwaitExpression(): boolean {
|
||||
if (token === SyntaxKind.AwaitKeyword) {
|
||||
if (inAwaitContext()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// here we are using similar heuristics as 'isYieldExpression'
|
||||
return lookAhead(nextTokenIsIdentifierOnSameLine);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseAwaitExpression() {
|
||||
var node = <AwaitExpression>createNode(SyntaxKind.AwaitExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseUnaryExpressionOrHigher(): UnaryExpression {
|
||||
if (isAwaitExpression()) {
|
||||
return parseAwaitExpression();
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
case SyntaxKind.PlusToken:
|
||||
case SyntaxKind.MinusToken:
|
||||
|
@ -3230,6 +3312,11 @@ module ts {
|
|||
return parseArrayLiteralExpression();
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return parseObjectLiteralExpression();
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
|
||||
break;
|
||||
}
|
||||
return parseFunctionExpression();
|
||||
case SyntaxKind.ClassKeyword:
|
||||
return parseClassExpression();
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
|
@ -3353,15 +3440,32 @@ module ts {
|
|||
if (saveDecoratorContext) {
|
||||
setDecoratorContext(false);
|
||||
}
|
||||
|
||||
let node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression);
|
||||
setModifiers(node, parseModifiers());
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
|
||||
let savedYieldContext = inYieldContext();
|
||||
let isGenerator = node.asteriskToken != undefined;
|
||||
setYieldContext(isGenerator);
|
||||
|
||||
let savedAwaitContext = inAwaitContext();
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
setAwaitContext(isAsync);
|
||||
|
||||
node.name = parseOptionalIdentifier();
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setAwaitContext(savedAwaitContext);
|
||||
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
|
||||
|
||||
if (saveDecoratorContext) {
|
||||
setDecoratorContext(true);
|
||||
}
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -3394,9 +3498,12 @@ module ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseFunctionBlock(allowYield: boolean, ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
|
||||
function parseFunctionBlock(allowYield: boolean, allowAwait: boolean, ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
|
||||
let savedYieldContext = inYieldContext();
|
||||
setYieldContext(allowYield);
|
||||
|
||||
let savedAwaitContext = inAwaitContext();
|
||||
setAwaitContext(allowAwait);
|
||||
|
||||
// We may be in a [Decorator] context when parsing a function expression or
|
||||
// arrow function. The body of the function is not in [Decorator] context.
|
||||
|
@ -3412,6 +3519,7 @@ module ts {
|
|||
}
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setAwaitContext(savedAwaitContext);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
@ -3702,6 +3810,15 @@ module ts {
|
|||
// In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
|
||||
let isConstEnum = lookAhead(nextTokenIsEnumKeyword);
|
||||
return !isConstEnum;
|
||||
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
// When followed by the function keyword on the same line, this is a statement
|
||||
if (lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isStartOfExpression();
|
||||
|
||||
case SyntaxKind.InterfaceKeyword:
|
||||
case SyntaxKind.ModuleKeyword:
|
||||
case SyntaxKind.NamespaceKeyword:
|
||||
|
@ -3835,13 +3952,13 @@ module ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function parseFunctionBlockOrSemicolon(isGenerator: boolean, diagnosticMessage?: DiagnosticMessage): Block {
|
||||
function parseFunctionBlockOrSemicolon(isGenerator: boolean, isAsync: boolean, diagnosticMessage?: DiagnosticMessage): Block {
|
||||
if (token !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
|
||||
parseSemicolon();
|
||||
return;
|
||||
}
|
||||
|
||||
return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage);
|
||||
return parseFunctionBlock(isGenerator, isAsync, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage);
|
||||
}
|
||||
|
||||
// DECLARATIONS
|
||||
|
@ -3853,7 +3970,7 @@ module ts {
|
|||
let node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
node.name = parseIdentifierOrPattern();
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -3870,7 +3987,7 @@ module ts {
|
|||
node.propertyName = <Identifier>propertyName;
|
||||
node.name = parseIdentifierOrPattern();
|
||||
}
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -3976,8 +4093,10 @@ module ts {
|
|||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, Diagnostics.or_expected);
|
||||
let isGenerator = node.asteriskToken != undefined;
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -3986,8 +4105,8 @@ module ts {
|
|||
node.decorators = decorators;
|
||||
setModifiers(node, modifiers);
|
||||
parseExpected(SyntaxKind.ConstructorKeyword);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false, Diagnostics.or_expected);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, Diagnostics.or_expected);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -3998,8 +4117,10 @@ module ts {
|
|||
method.asteriskToken = asteriskToken;
|
||||
method.name = name;
|
||||
method.questionToken = questionToken;
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, /*requireCompleteParameterList:*/ false, method);
|
||||
method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
|
||||
let isGenerator = asteriskToken != undefined;
|
||||
let isAsync = isAsyncFunctionLike(method);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, method);
|
||||
method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage);
|
||||
return finishNode(method);
|
||||
}
|
||||
|
||||
|
@ -4039,8 +4160,8 @@ module ts {
|
|||
node.decorators = decorators;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = parsePropertyName();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
@ -4147,14 +4268,14 @@ module ts {
|
|||
return decorators;
|
||||
}
|
||||
|
||||
function parseModifiers(): ModifiersArray {
|
||||
function parseModifiers(isArrowFunction?: boolean): ModifiersArray {
|
||||
let flags = 0;
|
||||
let modifiers: ModifiersArray;
|
||||
while (true) {
|
||||
let modifierStart = scanner.getStartPos();
|
||||
let modifierKind = token;
|
||||
|
||||
if (!parseAnyContextualModifier()) {
|
||||
if (!parseAnyContextualModifier(isArrowFunction)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4228,7 +4349,7 @@ module ts {
|
|||
function parseClassDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassDeclaration {
|
||||
return <ClassDeclaration>parseClassDeclarationOrExpression(fullStart, decorators, modifiers, SyntaxKind.ClassDeclaration);
|
||||
}
|
||||
|
||||
|
||||
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
|
||||
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
|
||||
let savedStrictModeContext = inStrictModeContext();
|
||||
|
@ -4243,13 +4364,15 @@ module ts {
|
|||
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ true);
|
||||
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
// ClassTail[Yield,GeneratorParameter] : See 14.5
|
||||
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
|
||||
// ClassTail[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.5
|
||||
// [~GeneratorParameter,~AsyncParameter]ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
|
||||
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
|
||||
|
||||
node.members = inGeneratorParameterContext()
|
||||
? doOutsideOfYieldContext(parseClassMembers)
|
||||
// [+AsyncParameter] ClassHeritageopt { ClassBodyopt }
|
||||
|
||||
node.members = inGeneratorParameterOrAsyncParameterContext()
|
||||
? doOutsideOfYieldAndAwaitContext(parseClassMembers)
|
||||
: parseClassMembers();
|
||||
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
else {
|
||||
|
@ -4262,13 +4385,14 @@ module ts {
|
|||
}
|
||||
|
||||
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
|
||||
// ClassTail[Yield,GeneratorParameter] : See 14.5
|
||||
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
|
||||
// ClassTail[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.5
|
||||
// [~GeneratorParameter,~AsyncParameter]ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
|
||||
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
|
||||
// [+AsyncParameter] ClassHeritageopt { ClassBodyopt }
|
||||
|
||||
if (isHeritageClause()) {
|
||||
return isClassHeritageClause && inGeneratorParameterContext()
|
||||
? doOutsideOfYieldContext(parseHeritageClausesWorker)
|
||||
return isClassHeritageClause && inGeneratorParameterOrAsyncParameterContext()
|
||||
? doOutsideOfYieldAndAwaitContext(parseHeritageClausesWorker)
|
||||
: parseHeritageClausesWorker();
|
||||
}
|
||||
|
||||
|
@ -4652,6 +4776,11 @@ module ts {
|
|||
case SyntaxKind.StaticKeyword:
|
||||
// Check for modifier on source element
|
||||
return lookAhead(nextTokenIsDeclarationStart);
|
||||
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
// Check for modifier on source element
|
||||
return lookAhead(nextTokenIsDeclarationStartOnSameLine);
|
||||
|
||||
case SyntaxKind.AtToken:
|
||||
// a lookahead here is too costly, and decorators are only valid on a declaration.
|
||||
// We will assume we are parsing a declaration here and report an error later
|
||||
|
@ -4690,6 +4819,16 @@ module ts {
|
|||
return isDeclarationStart(/*followsModifier*/ true);
|
||||
}
|
||||
|
||||
function nextTokenIsDeclarationStartOnSameLine() {
|
||||
nextToken();
|
||||
return !scanner.hasPrecedingLineBreak() && isDeclarationStart();
|
||||
}
|
||||
|
||||
function nextTokenIsFunctionKeywordOnSameLine() {
|
||||
nextToken();
|
||||
return !scanner.hasPrecedingLineBreak() && token === SyntaxKind.FunctionKeyword;
|
||||
}
|
||||
|
||||
function nextTokenIsAsKeyword() {
|
||||
return nextToken() === SyntaxKind.AsKeyword;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ module ts {
|
|||
"while": SyntaxKind.WhileKeyword,
|
||||
"with": SyntaxKind.WithKeyword,
|
||||
"yield": SyntaxKind.YieldKeyword,
|
||||
"async": SyntaxKind.AsyncKeyword,
|
||||
"await": SyntaxKind.AwaitKeyword,
|
||||
"of": SyntaxKind.OfKeyword,
|
||||
"{": SyntaxKind.OpenBraceToken,
|
||||
"}": SyntaxKind.CloseBraceToken,
|
||||
|
|
|
@ -133,6 +133,8 @@ module ts {
|
|||
// Contextual keywords
|
||||
AsKeyword,
|
||||
AnyKeyword,
|
||||
AsyncKeyword,
|
||||
AwaitKeyword,
|
||||
BooleanKeyword,
|
||||
ConstructorKeyword,
|
||||
DeclareKeyword,
|
||||
|
@ -197,6 +199,7 @@ module ts {
|
|||
DeleteExpression,
|
||||
TypeOfExpression,
|
||||
VoidExpression,
|
||||
AwaitExpression,
|
||||
PrefixUnaryExpression,
|
||||
PostfixUnaryExpression,
|
||||
BinaryExpression,
|
||||
|
@ -316,8 +319,9 @@ module ts {
|
|||
OctalLiteral = 0x00004000, // Octal numeric literal
|
||||
Namespace = 0x00008000, // Namespace declaration
|
||||
ExportContext = 0x00010000, // Export context (initialized by binding)
|
||||
Async = 0x00020000, // Property/Method/Function
|
||||
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static | Default,
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static | Default | Async,
|
||||
AccessibilityModifier = Public | Private | Protected,
|
||||
BlockScoped = Let | Const
|
||||
}
|
||||
|
@ -345,17 +349,29 @@ module ts {
|
|||
// error.
|
||||
ThisNodeHasError = 1 << 5,
|
||||
|
||||
// Context flags set directly by the parser.
|
||||
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,
|
||||
// If this node was parsed in the parameters of an async function.
|
||||
AsyncParameter = 1 << 6,
|
||||
|
||||
// If this node was parsed in the 'await' context created when parsing an async function.
|
||||
Await = 1 << 7,
|
||||
|
||||
// Context flags set directly by the parser.
|
||||
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError | AsyncParameter | Await,
|
||||
|
||||
// Context flags passed as part of the modified ES6 grammar.
|
||||
ContextParameterFlags = Yield | GeneratorParameter | AsyncParameter | Await,
|
||||
|
||||
// Context flags computed by aggregating child flags upwards.
|
||||
|
||||
// Used during incremental parsing to determine if this node or any of its children had an
|
||||
// error. Computed only once and then cached.
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 6,
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 8,
|
||||
|
||||
// Used to know if we've computed whether any children of this node are or contain an 'await' or 'yield' expression.
|
||||
ThisNodeOrAnySubNodesHasAwaitOrYield = 1 << 9,
|
||||
|
||||
// Used to know if we've computed data from children and cached it in this node.
|
||||
HasAggregatedChildData = 1 << 7
|
||||
HasAggregatedChildData = 1 << 10
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
@ -658,6 +674,10 @@ module ts {
|
|||
expression: UnaryExpression;
|
||||
}
|
||||
|
||||
export interface AwaitExpression extends UnaryExpression {
|
||||
expression: UnaryExpression;
|
||||
}
|
||||
|
||||
export interface YieldExpression extends Expression {
|
||||
asteriskToken?: Node;
|
||||
expression: Expression;
|
||||
|
@ -1403,22 +1423,28 @@ module ts {
|
|||
TypeChecked = 0x00000001, // Node has been type checked
|
||||
LexicalThis = 0x00000002, // Lexical 'this' reference
|
||||
CaptureThis = 0x00000004, // Lexical 'this' used in body
|
||||
EmitExtends = 0x00000008, // Emit __extends
|
||||
SuperInstance = 0x00000010, // Instance 'super' reference
|
||||
SuperStatic = 0x00000020, // Static 'super' reference
|
||||
ContextChecked = 0x00000040, // Contextual types have been assigned
|
||||
LexicalArguments = 0x00000008, // Lexical 'arguments' reference
|
||||
CaptureArguments = 0x00000010, // Lexical 'arguments' used in body
|
||||
EmitExtends = 0x00000020, // Emit __extends
|
||||
EmitDecorate = 0x00000040, // Emit __decorate
|
||||
EmitParam = 0x00000080, // Emit __param helper for decorators
|
||||
EmitAwaiter = 0x00000100, // Emit __awaiter
|
||||
EmitGenerator = 0x00000200, // Emit __generator
|
||||
SuperInstance = 0x00000400, // Instance 'super' reference
|
||||
SuperStatic = 0x00000800, // Static 'super' reference
|
||||
ContextChecked = 0x00001000, // Contextual types have been assigned
|
||||
PromiseCollision = 0x00002000, // Declaration collides with the global 'Promise'
|
||||
|
||||
// Values for enum members have been computed, and any errors have been reported for them.
|
||||
EnumValuesComputed = 0x00000080,
|
||||
BlockScopedBindingInLoop = 0x00000100,
|
||||
EmitDecorate = 0x00000200, // Emit __decorate
|
||||
EmitParam = 0x00000400, // Emit __param helper for decorators
|
||||
LexicalModuleMergesWithClass = 0x00000800, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
EnumValuesComputed = 0x00004000,
|
||||
BlockScopedBindingInLoop = 0x00008000,
|
||||
LexicalModuleMergesWithClass= 0x00010000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NodeLinks {
|
||||
resolvedType?: Type; // Cached type of type node
|
||||
resolvedAwaitedType?: Type; // Cached awaited type of type node
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
|
|
|
@ -511,6 +511,19 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
export function getContainingParameter(node: Node): ParameterDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node || isFunctionLike(node)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.Parameter) {
|
||||
return <ParameterDeclaration>node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
|
@ -1087,6 +1100,10 @@ module ts {
|
|||
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
|
||||
}
|
||||
|
||||
export function isAsyncFunctionLike(node: Node): boolean {
|
||||
return isFunctionLike(node) && !isAccessor(node) && (node.flags & NodeFlags.Async) === NodeFlags.Async;
|
||||
}
|
||||
|
||||
/**
|
||||
* A declaration has a dynamic name if both of the following are true:
|
||||
* 1. The declaration has a computed property name
|
||||
|
@ -1145,6 +1162,7 @@ module ts {
|
|||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1630,6 +1648,7 @@ module ts {
|
|||
case SyntaxKind.DeclareKeyword: return NodeFlags.Ambient;
|
||||
case SyntaxKind.ConstKeyword: return NodeFlags.Const;
|
||||
case SyntaxKind.DefaultKeyword: return NodeFlags.Default;
|
||||
case SyntaxKind.AsyncKeyword: return NodeFlags.Async;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
12
src/lib/core.d.ts
vendored
12
src/lib/core.d.ts
vendored
|
@ -1169,3 +1169,15 @@ declare type ClassDecorator = <TFunction extends Function>(target: TFunction) =>
|
|||
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
|
||||
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
|
||||
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
||||
|
||||
declare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;
|
||||
|
||||
interface PromiseLike<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
|
||||
}
|
10
src/lib/es6.d.ts
vendored
10
src/lib/es6.d.ts
vendored
|
@ -3572,16 +3572,6 @@ declare module Reflect {
|
|||
function setPrototypeOf(target: any, proto: any): boolean;
|
||||
}
|
||||
|
||||
interface PromiseLike<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue