mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-23 01:42:07 -06:00
End-to-end support for destructuring in variable declarations
This commit is contained in:
parent
3d3212b8aa
commit
af00c718cc
@ -340,17 +340,14 @@ module ts {
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.PatternDeclaration:
|
||||
if ((<Declaration>node).name) {
|
||||
if (node.flags & NodeFlags.BlockScoped) {
|
||||
bindBlockScopedVariableDeclaration(<Declaration>node);
|
||||
}
|
||||
else {
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
if (isBindingPattern((<Declaration>node).name)) {
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
else if (node.flags & NodeFlags.BlockScoped) {
|
||||
bindBlockScopedVariableDeclaration(<Declaration>node);
|
||||
}
|
||||
else {
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.Property:
|
||||
|
||||
@ -1628,11 +1628,48 @@ module ts {
|
||||
return classType.typeParameters ? createTypeReference(<GenericType>classType, map(classType.typeParameters, _ => anyType)) : classType;
|
||||
}
|
||||
|
||||
function getTypeOfVariableOrPropertyDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type {
|
||||
function getTypeOfPropertyOfType(type: Type, name: string): Type {
|
||||
var prop = getPropertyOfType(type, name);
|
||||
return prop ? getTypeOfSymbol(prop) : undefined;
|
||||
}
|
||||
|
||||
function getTypeForBindingElement(declaration: BindingElement): Type {
|
||||
var pattern = <BindingPattern>declaration.parent;
|
||||
var parentType = getTypeForVariableDeclaration(<VariableDeclaration>pattern.parent);
|
||||
if (parentType === unknownType) {
|
||||
return unknownType;
|
||||
}
|
||||
if (!parentType || parentType === anyType) {
|
||||
if (declaration.initializer) {
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
}
|
||||
return parentType;
|
||||
}
|
||||
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
var name = (declaration.propertyName || <Identifier>declaration.name).text;
|
||||
var type = getTypeOfPropertyOfType(parentType, name) ||
|
||||
isNumericName(name) && getIndexTypeOfType(parentType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(parentType, IndexKind.String);
|
||||
}
|
||||
else {
|
||||
var index = indexOf(pattern.elements, declaration);
|
||||
var type = getTypeOfPropertyOfType(parentType, "" + index) || getIndexTypeOfType(parentType, IndexKind.Number);
|
||||
}
|
||||
if (!type) {
|
||||
// Error: Type {0} has no property {1}
|
||||
return unknownType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getTypeForVariableDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type {
|
||||
// A variable declared in a for..in statement is always of type any
|
||||
if (declaration.parent.kind === SyntaxKind.ForInStatement) {
|
||||
return anyType;
|
||||
}
|
||||
if (isBindingPattern(declaration.parent)) {
|
||||
return getTypeForBindingElement(<BindingElement>declaration);
|
||||
}
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
@ -1654,7 +1691,26 @@ module ts {
|
||||
}
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
var type = checkAndMarkExpression(declaration.initializer);
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
}
|
||||
// No type specified and nothing can be inferred
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getWidenedTypeForVariableDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type {
|
||||
var type = getTypeForVariableDeclaration(declaration);
|
||||
if (type) {
|
||||
return getWidenedType(type);
|
||||
}
|
||||
if (declaration.flags & NodeFlags.Rest) {
|
||||
return createArrayType(anyType);
|
||||
}
|
||||
return anyType;
|
||||
}
|
||||
|
||||
function getTypeOfVariableOrPropertyDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type {
|
||||
var type = getTypeForVariableDeclaration(declaration);
|
||||
if (type) {
|
||||
if (declaration.kind !== SyntaxKind.PropertyAssignment) {
|
||||
reportErrorsFromWidening(declaration, type);
|
||||
type = getWidenedType(type);
|
||||
@ -1670,6 +1726,48 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
//function getTypeOfVariableOrPropertyDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type {
|
||||
// // A variable declared in a for..in statement is always of type any
|
||||
// if (declaration.parent.kind === SyntaxKind.ForInStatement) {
|
||||
// return anyType;
|
||||
// }
|
||||
// // Use type from type annotation if one is present
|
||||
// if (declaration.type) {
|
||||
// return getTypeFromTypeNode(declaration.type);
|
||||
// }
|
||||
// if (declaration.kind === SyntaxKind.Parameter) {
|
||||
// var func = <FunctionLikeDeclaration>declaration.parent;
|
||||
// // For a parameter of a set accessor, use the type of the get accessor if one is present
|
||||
// if (func.kind === SyntaxKind.SetAccessor) {
|
||||
// var getter = <AccessorDeclaration>getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor);
|
||||
// if (getter) {
|
||||
// return getReturnTypeOfSignature(getSignatureFromDeclaration(getter));
|
||||
// }
|
||||
// }
|
||||
// // Use contextual parameter type if one is available
|
||||
// var type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
// if (type) {
|
||||
// return type;
|
||||
// }
|
||||
// }
|
||||
// // Use the type of the initializer expression if one is present
|
||||
// if (declaration.initializer) {
|
||||
// var type = checkAndMarkExpression(declaration.initializer);
|
||||
// if (declaration.kind !== SyntaxKind.PropertyAssignment) {
|
||||
// reportErrorsFromWidening(declaration, type);
|
||||
// type = getWidenedType(type);
|
||||
// }
|
||||
// return type;
|
||||
// }
|
||||
// // Rest parameters default to type any[], other parameters default to type any
|
||||
// var type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType;
|
||||
// // Report implicit any errors unless this is a private property within an ambient declaration
|
||||
// if (compilerOptions.noImplicitAny && !isPrivateWithinAmbient(declaration) && !(declaration.kind === SyntaxKind.Parameter && isPrivateWithinAmbient(declaration.parent))) {
|
||||
// reportImplicitAnyError(declaration, type);
|
||||
// }
|
||||
// return type;
|
||||
//}
|
||||
|
||||
function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type {
|
||||
var links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
@ -4245,6 +4343,10 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function hasInitializer(node: VariableDeclaration): boolean {
|
||||
return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(<VariableDeclaration>node.parent.parent));
|
||||
}
|
||||
|
||||
// Check if a given variable is assigned within a given syntax node
|
||||
function isVariableAssignedWithin(symbol: Symbol, node: Node): boolean {
|
||||
var links = getNodeLinks(node);
|
||||
@ -4273,7 +4375,7 @@ module ts {
|
||||
}
|
||||
|
||||
function isAssignedInVariableDeclaration(node: VariableDeclaration) {
|
||||
if (getSymbolOfNode(node) === symbol && node.initializer) {
|
||||
if (!isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
|
||||
return true;
|
||||
}
|
||||
return forEachChild(node, isAssignedIn);
|
||||
@ -4284,7 +4386,6 @@ module ts {
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return isAssignedInBinaryExpression(<BinaryExpression>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.PatternDeclaration:
|
||||
return isAssignedInVariableDeclaration(<VariableDeclaration>node);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
@ -5743,7 +5844,7 @@ module ts {
|
||||
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
var contextualSignature = getContextualSignature(func);
|
||||
if (func.body.kind !== SyntaxKind.FunctionBlock) {
|
||||
var type = checkAndMarkExpression(func.body, contextualMapper);
|
||||
var type = checkExpressionCached(func.body, contextualMapper);
|
||||
}
|
||||
else {
|
||||
// Aggregate the types of expressions within all the return statements.
|
||||
@ -5772,7 +5873,7 @@ module ts {
|
||||
forEachReturnStatement(body, returnStatement => {
|
||||
var expr = returnStatement.expression;
|
||||
if (expr) {
|
||||
var type = checkAndMarkExpression(expr, contextualMapper);
|
||||
var type = checkExpressionCached(expr, contextualMapper);
|
||||
if (!contains(aggregatedTypes, type)) {
|
||||
aggregatedTypes.push(type);
|
||||
}
|
||||
@ -6225,10 +6326,12 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function checkAndMarkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||
var result = checkExpression(node, contextualMapper);
|
||||
getNodeLinks(node).flags |= NodeCheckFlags.TypeChecked;
|
||||
return result;
|
||||
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = checkExpression(node, contextualMapper);
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
|
||||
@ -7221,53 +7324,40 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isBindingPattern(name: DeclarationName) {
|
||||
return name.kind === SyntaxKind.ArrayBindingPattern || name.kind === SyntaxKind.ObjectBindingPattern;
|
||||
}
|
||||
|
||||
// TODO(andersh): Support destructuring
|
||||
function checkVariableDeclaration(node: VariableDeclaration | PropertyDeclaration) {
|
||||
if (isBindingPattern(node.name)) {
|
||||
forEach((<BindingPattern>node.name).elements, e => {
|
||||
if (e.kind === SyntaxKind.VariableDeclaration) {
|
||||
checkVariableDeclaration(e);
|
||||
}
|
||||
});
|
||||
if (node.initializer) {
|
||||
checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableDeclaration(node), node, /*headMessage*/ undefined);
|
||||
}
|
||||
return;
|
||||
}
|
||||
checkSourceElement(node.type);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
|
||||
if (fullTypeCheck) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
|
||||
var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
var type: Type;
|
||||
var useTypeFromValueDeclaration = node === symbol.valueDeclaration;
|
||||
if (useTypeFromValueDeclaration) {
|
||||
type = typeOfValueDeclaration;
|
||||
}
|
||||
else {
|
||||
type = getTypeOfVariableOrPropertyDeclaration(node);
|
||||
}
|
||||
|
||||
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var type = getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
if (node === symbol.valueDeclaration) {
|
||||
if (node.initializer) {
|
||||
if (!(getNodeLinks(node.initializer).flags & NodeCheckFlags.TypeChecked)) {
|
||||
// Use default messages
|
||||
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*headMessage*/ undefined);
|
||||
}
|
||||
//TODO(jfreeman): Check that it is not a computed property
|
||||
checkCollisionWithConstDeclarations(<VariableDeclaration>node);
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
if (!useTypeFromValueDeclaration) {
|
||||
// TypeScript 1.0 spec (April 2014): 5.1
|
||||
// Multiple declarations for the same variable name in the same declaration space are permitted,
|
||||
// provided that each declaration associates the same type with the variable.
|
||||
if (typeOfValueDeclaration !== unknownType && type !== unknownType && !isTypeIdenticalTo(typeOfValueDeclaration, type)) {
|
||||
error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(node.name), typeToString(typeOfValueDeclaration), typeToString(type));
|
||||
}
|
||||
checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var declarationType = getWidenedTypeForVariableDeclaration(node);
|
||||
if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
|
||||
error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
|
||||
}
|
||||
if (node.initializer) {
|
||||
checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
checkCollisionWithConstDeclarations(<VariableDeclaration>node);
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
}
|
||||
|
||||
function checkVariableStatement(node: VariableStatement) {
|
||||
@ -7345,34 +7435,28 @@ module ts {
|
||||
// TODO: Check that target label is valid
|
||||
}
|
||||
|
||||
function isGetAccessorWithAnnotatatedSetAccessor(node: FunctionLikeDeclaration) {
|
||||
return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)));
|
||||
}
|
||||
|
||||
function checkReturnStatement(node: ReturnStatement) {
|
||||
if (node.expression && !(getNodeLinks(node.expression).flags & NodeCheckFlags.TypeChecked)) {
|
||||
if (node.expression) {
|
||||
var func = getContainingFunction(node);
|
||||
if (func) {
|
||||
var returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
|
||||
var exprType = checkExpressionCached(node.expression);
|
||||
if (func.kind === SyntaxKind.SetAccessor) {
|
||||
if (node.expression) {
|
||||
error(node.expression, Diagnostics.Setters_cannot_return_a_value);
|
||||
}
|
||||
error(node.expression, Diagnostics.Setters_cannot_return_a_value);
|
||||
}
|
||||
else {
|
||||
var returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
|
||||
// do assignability check only if we short circuited in determining return type
|
||||
// - function has explicit type annotation
|
||||
// - function is getter with no type annotation and setter parameter type is used
|
||||
// - function is a constructor (will be special cased below)
|
||||
var checkAssignability =
|
||||
func.type ||
|
||||
(func.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(func.symbol, SyntaxKind.SetAccessor)));
|
||||
if (checkAssignability) {
|
||||
checkTypeAssignableTo(checkExpression(node.expression), returnType, node.expression, /*headMessage*/ undefined);
|
||||
}
|
||||
else if (func.kind == SyntaxKind.Constructor) {
|
||||
// constructor doesn't have explicit return type annotation and yet its return type is known - declaring type
|
||||
// handle constructors and issue specialized error message for them.
|
||||
if (!isTypeAssignableTo(checkExpression(node.expression), returnType)) {
|
||||
if (func.kind === SyntaxKind.Constructor) {
|
||||
if (!isTypeAssignableTo(exprType, returnType)) {
|
||||
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
|
||||
}
|
||||
}
|
||||
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
|
||||
checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8201,7 +8285,6 @@ module ts {
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.PatternDeclaration:
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
|
||||
@ -990,6 +990,18 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitObjectBindingPattern(node: BindingPattern) {
|
||||
write("{ ");
|
||||
emitCommaList(node.elements, /*includeTrailingComma*/ true);
|
||||
write(" }");
|
||||
}
|
||||
|
||||
function emitArrayBindingPattern(node: BindingPattern) {
|
||||
write("[");
|
||||
emitCommaList(node.elements, /*includeTrailingComma*/ true);
|
||||
write("]");
|
||||
}
|
||||
|
||||
function emitArrayLiteral(node: ArrayLiteral) {
|
||||
if (node.flags & NodeFlags.MultiLine) {
|
||||
write("[");
|
||||
@ -1437,7 +1449,16 @@ module ts {
|
||||
|
||||
function emitVariableDeclaration(node: VariableDeclaration) {
|
||||
emitLeadingComments(node);
|
||||
emitModuleMemberName(node);
|
||||
if (node.propertyName) {
|
||||
emit(node.propertyName);
|
||||
write(": ");
|
||||
}
|
||||
if (node.name.kind === SyntaxKind.Identifier) {
|
||||
emitModuleMemberName(node);
|
||||
}
|
||||
else {
|
||||
emit(node.name);
|
||||
}
|
||||
emitOptional(" = ", node.initializer);
|
||||
emitTrailingComments(node);
|
||||
}
|
||||
@ -2207,11 +2228,9 @@ module ts {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.flags & NodeFlags.Ambient) {
|
||||
return emitPinnedOrTripleSlashComments(node);
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return emitIdentifier(<Identifier>node);
|
||||
@ -2244,6 +2263,10 @@ module ts {
|
||||
return emitTemplateSpan(<TemplateSpan>node);
|
||||
case SyntaxKind.QualifiedName:
|
||||
return emitPropertyAccess(<QualifiedName>node);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return emitObjectBindingPattern(<BindingPattern>node);
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return emitArrayBindingPattern(<BindingPattern>node);
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
return emitArrayLiteral(<ArrayLiteral>node);
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
|
||||
@ -236,11 +236,7 @@ module ts {
|
||||
return child((<ParenTypeNode>node).type);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return children((<BindingPattern>node).declarations);
|
||||
case SyntaxKind.PatternDeclaration:
|
||||
return child((<PatternDeclaration>node).propertyName) ||
|
||||
child((<PatternDeclaration>node).name) ||
|
||||
child((<PatternDeclaration>node).initializer);
|
||||
return children((<BindingPattern>node).elements);
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
return children((<ArrayLiteral>node).elements);
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
@ -334,7 +330,8 @@ module ts {
|
||||
return child((<CatchBlock>node).variable) ||
|
||||
children((<CatchBlock>node).statements);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return child((<VariableDeclaration>node).name) ||
|
||||
return child((<VariableDeclaration>node).propertyName) ||
|
||||
child((<VariableDeclaration>node).name) ||
|
||||
child((<VariableDeclaration>node).type) ||
|
||||
child((<VariableDeclaration>node).initializer);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
@ -421,11 +418,11 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getContainingFunction(node: Node): SignatureDeclaration {
|
||||
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node || isAnyFunction(node)) {
|
||||
return <SignatureDeclaration>node;
|
||||
return <FunctionLikeDeclaration>node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -518,7 +515,6 @@ module ts {
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.PatternDeclaration:
|
||||
return (<VariableDeclaration>parent).initializer === node;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
case SyntaxKind.IfStatement:
|
||||
@ -565,6 +561,10 @@ module ts {
|
||||
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
|
||||
}
|
||||
|
||||
export function isBindingPattern(node: Node) {
|
||||
return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern;
|
||||
}
|
||||
|
||||
export function isInAmbientContext(node: Node): boolean {
|
||||
while (node) {
|
||||
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
|
||||
@ -573,7 +573,6 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export function isDeclaration(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeParameter:
|
||||
@ -676,26 +675,26 @@ module ts {
|
||||
}
|
||||
|
||||
enum ParsingContext {
|
||||
SourceElements, // Elements in source file
|
||||
ModuleElements, // Elements in module declaration
|
||||
BlockStatements, // Statements in block
|
||||
SwitchClauses, // Clauses in switch statement
|
||||
SwitchClauseStatements, // Statements in switch clause
|
||||
TypeMembers, // Members in interface or type literal
|
||||
ClassMembers, // Members in class declaration
|
||||
EnumMembers, // Members in enum declaration
|
||||
BaseTypeReferences, // Type references in extends or implements clause
|
||||
VariableDeclarations, // Variable declarations in variable statement
|
||||
ObjectBindingDeclarations, // Binding elements in object binding list
|
||||
ArrayBindingDeclarations, // Binding elements in array binding list
|
||||
ArgumentExpressions, // Expressions in argument list
|
||||
ObjectLiteralMembers, // Members in object literal
|
||||
ArrayLiteralMembers, // Members in array literal
|
||||
Parameters, // Parameters in parameter list
|
||||
TypeParameters, // Type parameters in type parameter list
|
||||
TypeArguments, // Type arguments in type argument list
|
||||
TupleElementTypes, // Element types in tuple element type list
|
||||
Count // Number of parsing contexts
|
||||
SourceElements, // Elements in source file
|
||||
ModuleElements, // Elements in module declaration
|
||||
BlockStatements, // Statements in block
|
||||
SwitchClauses, // Clauses in switch statement
|
||||
SwitchClauseStatements, // Statements in switch clause
|
||||
TypeMembers, // Members in interface or type literal
|
||||
ClassMembers, // Members in class declaration
|
||||
EnumMembers, // Members in enum declaration
|
||||
BaseTypeReferences, // Type references in extends or implements clause
|
||||
VariableDeclarations, // Variable declarations in variable statement
|
||||
ObjectBindingElements, // Binding elements in object binding list
|
||||
ArrayBindingElements, // Binding elements in array binding list
|
||||
ArgumentExpressions, // Expressions in argument list
|
||||
ObjectLiteralMembers, // Members in object literal
|
||||
ArrayLiteralMembers, // Members in array literal
|
||||
Parameters, // Parameters in parameter list
|
||||
TypeParameters, // Type parameters in type parameter list
|
||||
TypeArguments, // Type arguments in type argument list
|
||||
TupleElementTypes, // Element types in tuple element type list
|
||||
Count // Number of parsing contexts
|
||||
}
|
||||
|
||||
const enum Tristate {
|
||||
@ -716,8 +715,8 @@ module ts {
|
||||
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
|
||||
case ParsingContext.BaseTypeReferences: return Diagnostics.Type_reference_expected;
|
||||
case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
|
||||
case ParsingContext.ObjectBindingDeclarations: return Diagnostics.Property_destructuring_pattern_expected;
|
||||
case ParsingContext.ArrayBindingDeclarations: return Diagnostics.Array_element_destructuring_pattern_expected;
|
||||
case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
|
||||
case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
|
||||
case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
|
||||
case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
|
||||
case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
|
||||
@ -1191,9 +1190,10 @@ module ts {
|
||||
case ParsingContext.BaseTypeReferences:
|
||||
return isIdentifier() && ((token !== SyntaxKind.ExtendsKeyword && token !== SyntaxKind.ImplementsKeyword) || !lookAhead(() => (nextToken(), isIdentifier())));
|
||||
case ParsingContext.VariableDeclarations:
|
||||
case ParsingContext.ObjectBindingDeclarations:
|
||||
case ParsingContext.ArrayBindingDeclarations:
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return isIdentifierOrPattern();
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
return token === SyntaxKind.CommaToken || isIdentifierOrPattern();
|
||||
case ParsingContext.TypeParameters:
|
||||
return isIdentifier();
|
||||
case ParsingContext.ArgumentExpressions:
|
||||
@ -1225,7 +1225,7 @@ module ts {
|
||||
case ParsingContext.ClassMembers:
|
||||
case ParsingContext.EnumMembers:
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
case ParsingContext.ObjectBindingDeclarations:
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token === SyntaxKind.CloseBraceToken;
|
||||
case ParsingContext.SwitchClauseStatements:
|
||||
return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
|
||||
@ -1241,7 +1241,7 @@ module ts {
|
||||
return token === SyntaxKind.CloseParenToken || token === SyntaxKind.SemicolonToken;
|
||||
case ParsingContext.ArrayLiteralMembers:
|
||||
case ParsingContext.TupleElementTypes:
|
||||
case ParsingContext.ArrayBindingDeclarations:
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
return token === SyntaxKind.CloseBracketToken;
|
||||
case ParsingContext.Parameters:
|
||||
// Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
|
||||
@ -3389,10 +3389,13 @@ module ts {
|
||||
|
||||
// DECLARATIONS
|
||||
|
||||
function parseBindingDeclaration(flags: NodeFlags, context: ParsingContext): PatternDeclaration {
|
||||
var node = <PatternDeclaration>createNode(SyntaxKind.PatternDeclaration);
|
||||
function parseBindingElement(kind: SyntaxKind, flags: NodeFlags, context: ParsingContext): BindingElement {
|
||||
if (context === ParsingContext.ArrayBindingElements && token === SyntaxKind.CommaToken) {
|
||||
return <BindingElement>createNode(SyntaxKind.OmittedExpression);
|
||||
}
|
||||
var node = <BindingElement>createNode(kind);
|
||||
node.flags = flags;
|
||||
if (context === ParsingContext.ObjectBindingDeclarations) {
|
||||
if (context === ParsingContext.ObjectBindingElements) {
|
||||
var id = parseIdentifier();
|
||||
if (parseOptional(SyntaxKind.ColonToken)) {
|
||||
node.propertyName = id;
|
||||
@ -3405,18 +3408,19 @@ module ts {
|
||||
else {
|
||||
node.name = parseIdentifierOrPattern(flags);
|
||||
}
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseBindingList(flags: NodeFlags, context: ParsingContext): NodeArray<PatternDeclaration> {
|
||||
return parseDelimitedList(context, () => parseBindingDeclaration(flags, context), /*allowTrailingComma*/ true);
|
||||
function parseBindingList(flags: NodeFlags, context: ParsingContext): NodeArray<BindingElement> {
|
||||
return parseDelimitedList(context, () => parseBindingElement(SyntaxKind.VariableDeclaration, flags, context), /*allowTrailingComma*/ true);
|
||||
}
|
||||
|
||||
function parseObjectBindingPattern(flags: NodeFlags): BindingPattern {
|
||||
var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
|
||||
node.flags = flags;
|
||||
parseExpected(SyntaxKind.OpenBraceToken);
|
||||
node.declarations = parseBindingList(flags, ParsingContext.ObjectBindingDeclarations);
|
||||
node.elements = parseBindingList(flags, ParsingContext.ObjectBindingElements);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -3425,7 +3429,7 @@ module ts {
|
||||
var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
|
||||
node.flags = flags;
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
node.declarations = parseBindingList(flags, ParsingContext.ArrayBindingDeclarations);
|
||||
node.elements = parseBindingList(flags, ParsingContext.ArrayBindingElements);
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -3441,7 +3445,13 @@ module ts {
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
return parseObjectBindingPattern(flags);
|
||||
}
|
||||
return parseIdentifier();
|
||||
var id = parseIdentifier();
|
||||
if (isInStrictMode && isEvalOrArgumentsIdentifier(id)) {
|
||||
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
|
||||
// and its Identifier is eval or arguments
|
||||
reportInvalidUseInStrictMode(id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function parseVariableDeclaration(flags: NodeFlags, noIn?: boolean): VariableDeclaration {
|
||||
@ -3462,11 +3472,6 @@ module ts {
|
||||
if (!inAmbientContext && !node.initializer && flags & NodeFlags.Const) {
|
||||
grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
|
||||
}
|
||||
if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name)) {
|
||||
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
|
||||
// and its Identifier is eval or arguments
|
||||
reportInvalidUseInStrictMode(<Identifier>node.name);
|
||||
}
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
||||
@ -164,7 +164,6 @@ module ts {
|
||||
// Binding patterns
|
||||
ObjectBindingPattern,
|
||||
ArrayBindingPattern,
|
||||
PatternDeclaration,
|
||||
// Expression
|
||||
ArrayLiteral,
|
||||
ObjectLiteral,
|
||||
@ -323,20 +322,17 @@ module ts {
|
||||
export interface SignatureDeclaration extends Declaration, ParsedSignature { }
|
||||
|
||||
export interface VariableDeclaration extends Declaration {
|
||||
name: Identifier | BindingPattern;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
propertyName?: Identifier; // Binding property name (in object binding pattern)
|
||||
name: Identifier | BindingPattern; // Declared variable name
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
export interface BindingPattern extends Node {
|
||||
declarations: PatternDeclaration[];
|
||||
elements: NodeArray<BindingElement>;
|
||||
}
|
||||
|
||||
export interface PatternDeclaration extends Declaration {
|
||||
propertyName?: Identifier; // Binding property name
|
||||
name: Identifier | BindingPattern; // Declared variable name (pattern = undefined)
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
export interface BindingElement extends VariableDeclaration { }
|
||||
|
||||
export interface PropertyDeclaration extends Declaration {
|
||||
type?: TypeNode;
|
||||
@ -866,7 +862,7 @@ module ts {
|
||||
Prototype = 0x20000000, // Prototype property (no source representation)
|
||||
UnionProperty = 0x40000000, // Property in union type
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
|
||||
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user