Addressing CR feedback:

New SyntaxKind.BindingElement
Introduced new VariableLikeDeclaration and BindingElement types
Cleaned up VariableDeclaration, ParameterDeclaration, PropertyDeclaration types
Node kind of binding element is always SyntaxKind.BindingElement
Changed CheckVariableDeclaration to CheckVariableLikeDeclaration
Reorganized CheckVariableLikeDeclaration
This commit is contained in:
Anders Hejlsberg
2014-12-06 13:53:06 -08:00
parent 4118ffc703
commit 05c9966180
7 changed files with 231 additions and 156 deletions
+2 -6
View File
@@ -389,18 +389,14 @@ module ts {
break;
case SyntaxKind.Parameter:
if (isBindingPattern((<Declaration>node).name)) {
if (isBindingPattern(parent)) {
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
}
else {
bindAnonymousDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(<Declaration>node), /*isBlockScopeContainer*/ false);
}
bindAnonymousDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(<Declaration>node), /*isBlockScopeContainer*/ false);
}
else {
bindDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false);
}
break;
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
if (isBindingPattern((<Declaration>node).name)) {
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
}
+133 -95
View File
@@ -1435,7 +1435,7 @@ module ts {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
}
appendSymbolNameOnly(p, writer);
if (hasQuestionToken(p.valueDeclaration) || (<VariableDeclaration>p.valueDeclaration).initializer) {
if (hasQuestionToken(p.valueDeclaration) || (<ParameterDeclaration>p.valueDeclaration).initializer) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
@@ -1589,6 +1589,7 @@ module ts {
function determineIfDeclarationIsVisible() {
switch (node.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
@@ -1596,8 +1597,7 @@ module ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ImportDeclaration:
// In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
var parent = getDeclarationContainer(node);
// If the node is not exported or it is not ambient module element (except import declaration)
if (!(node.flags & NodeFlags.Export) &&
!(node.kind !== SyntaxKind.ImportDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) {
@@ -1651,6 +1651,18 @@ module ts {
}
}
function getRootDeclaration(node: Node): Node {
while (node.kind === SyntaxKind.BindingElement) {
node = node.parent.parent;
}
return node;
}
function getDeclarationContainer(node: Node): Node {
node = getRootDeclaration(node);
return node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
}
function getTypeOfPrototypeProperty(prototype: Symbol): Type {
// TypeScript 1.0 spec (April 2014): 8.4
// Every class automatically contains a static property member named 'prototype',
@@ -1669,7 +1681,7 @@ module ts {
// Return the inferred type for a binding element
function getTypeForBindingElement(declaration: BindingElement): Type {
var pattern = <BindingPattern>declaration.parent;
var parentType = getTypeForVariableDeclaration(<VariableDeclaration>pattern.parent);
var parentType = getTypeForVariableDeclaration(<VariableLikeDeclaration>pattern.parent);
// If parent has the unknown (error) type, then so does this binding element
if (parentType === unknownType) {
return unknownType;
@@ -1713,7 +1725,7 @@ module ts {
}
// Return the inferred type for a variable, parameter, or property declaration
function getTypeForVariableDeclaration(declaration: VariableDeclaration): Type {
function getTypeForVariableDeclaration(declaration: VariableLikeDeclaration): Type {
// A variable declared in a for..in statement is always of type any
if (declaration.parent.kind === SyntaxKind.ForInStatement) {
return anyType;
@@ -1796,7 +1808,7 @@ module ts {
// Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the
// binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the
// tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string.
function getWidenedTypeForVariableDeclaration(declaration: VariableDeclaration, reportErrors?: boolean): Type {
function getWidenedTypeForVariableDeclaration(declaration: VariableLikeDeclaration, reportErrors?: boolean): Type {
var type = getTypeForVariableDeclaration(declaration);
if (type) {
if (reportErrors) {
@@ -1814,9 +1826,12 @@ module ts {
}
// Rest parameters default to type any[], other parameters default to type any
type = declaration.dotDotDotToken ? anyArrayType : anyType;
// Report implicit any errors unless this is a private property within an ambient declaration
if (reportErrors && compilerOptions.noImplicitAny && !isPrivateWithinAmbient(declaration) && !(declaration.kind === SyntaxKind.Parameter && isPrivateWithinAmbient(declaration.parent))) {
reportImplicitAnyError(declaration, type);
// Report implicit any errors unless this is a private property within an ambient declaration
if (reportErrors && compilerOptions.noImplicitAny) {
var root = getRootDeclaration(declaration);
if (!isPrivateWithinAmbient(root) && !(root.kind === SyntaxKind.Parameter && isPrivateWithinAmbient(root.parent))) {
reportImplicitAnyError(declaration, type);
}
}
return type;
}
@@ -1835,7 +1850,7 @@ module ts {
}
// Handle variable, parameter or property
links.type = resolvingType;
var type = getWidenedTypeForVariableDeclaration(<VariableDeclaration>declaration, /*reportErrors*/ true);
var type = getWidenedTypeForVariableDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
if (links.type === resolvingType) {
links.type = type;
}
@@ -1843,7 +1858,7 @@ module ts {
else if (links.type === resolvingType) {
links.type = anyType;
if (compilerOptions.noImplicitAny) {
var diagnostic = (<VariableDeclaration>symbol.valueDeclaration).type ?
var diagnostic = (<VariableLikeDeclaration>symbol.valueDeclaration).type ?
Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
@@ -3090,7 +3105,7 @@ module ts {
}
return links.resolvedType;
}
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type {
var links = getNodeLinks(node);
if (!links.resolvedType) {
@@ -3912,7 +3927,7 @@ module ts {
return related;
}
return Ternary.True;
}
}
function numberIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
@@ -4375,7 +4390,7 @@ module ts {
}
}
function getInferenceCandidates(context: InferenceContext, index: number): Type[]{
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
var inferences = context.inferences[index];
return inferences.primary || inferences.secondary || emptyArray;
}
@@ -4454,8 +4469,8 @@ module ts {
return type;
}
function hasInitializer(node: VariableDeclaration): boolean {
return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(<VariableDeclaration>node.parent.parent));
function hasInitializer(node: VariableLikeDeclaration): boolean {
return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(<VariableLikeDeclaration>node.parent.parent));
}
// Check if a given variable is assigned within a given syntax node
@@ -4485,7 +4500,7 @@ module ts {
return forEachChild(node, isAssignedIn);
}
function isAssignedInVariableDeclaration(node: VariableDeclaration) {
function isAssignedInVariableDeclaration(node: VariableLikeDeclaration) {
if (!isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
return true;
}
@@ -4497,7 +4512,8 @@ module ts {
case SyntaxKind.BinaryExpression:
return isAssignedInBinaryExpression(<BinaryExpression>node);
case SyntaxKind.VariableDeclaration:
return isAssignedInVariableDeclaration(<VariableDeclaration>node);
case SyntaxKind.BindingElement:
return isAssignedInVariableDeclaration(<VariableLikeDeclaration>node);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ArrayLiteralExpression:
@@ -4856,7 +4872,7 @@ module ts {
container.kind === SyntaxKind.Property ||
container.kind === SyntaxKind.Constructor;
}
}
}
}
if (canUseSuperExpression) {
@@ -4914,7 +4930,7 @@ module ts {
}
// If last parameter is contextually rest parameter get its type
if (indexOfParameter === (func.parameters.length - 1) &&
if (indexOfParameter === (func.parameters.length - 1) &&
funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
return getTypeOfSymbol(contextualSignature.parameters[contextualSignature.parameters.length - 1]);
}
@@ -4930,13 +4946,13 @@ module ts {
// of the parameter. Otherwise, in a variable or parameter declaration with a binding pattern name, the contextual
// type of an initializer expression is the type implied by the binding pattern.
function getContextualTypeForInitializerExpression(node: Expression): Type {
var declaration = <VariableOrParameterDeclaration>node.parent;
var declaration = <VariableLikeDeclaration>node.parent;
if (node === declaration.initializer) {
if (declaration.type) {
return getTypeFromTypeNode(declaration.type);
}
if (declaration.kind === SyntaxKind.Parameter) {
var type = getContextuallyTypedParameterType(declaration);
var type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
if (type) {
return type;
}
@@ -5079,7 +5095,7 @@ module ts {
// In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
function getContextualTypeForConditionalOperand(node: Expression): Type {
var conditional = <ConditionalExpression>node.parent;
return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
}
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
@@ -5097,6 +5113,7 @@ module ts {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.BindingElement:
return getContextualTypeForInitializerExpression(node);
case SyntaxKind.ArrowFunction:
case SyntaxKind.ReturnStatement:
@@ -5225,7 +5242,7 @@ module ts {
}
return createArrayType(getUnionType(elementTypes));
}
function isNumericName(name: string) {
// The intent of numeric names is that
// - they are names with text in a numeric form, and that
@@ -5250,7 +5267,7 @@ module ts {
// with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively.
return (+name).toString() === name;
}
function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type {
var members = node.symbol.members;
var properties: SymbolTable = {};
@@ -5581,10 +5598,7 @@ module ts {
* @param callIsIncomplete Whether or not a call is unfinished, and we should be "lenient" when we have too few arguments.
* @param signature The signature whose arity we are comparing.
*/
function checkArity(adjustedArgCount: number,
typeArguments: NodeArray<TypeNode>,
callIsIncomplete: boolean,
signature: Signature): boolean {
function checkArity(adjustedArgCount: number, typeArguments: NodeArray<TypeNode>, callIsIncomplete: boolean, signature: Signature): boolean {
// Too many arguments implies incorrect arity.
if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
return false;
@@ -5686,7 +5700,7 @@ module ts {
var constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined,
Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
}
}
@@ -6487,7 +6501,7 @@ module ts {
return (type.flags & TypeFlags.Structured) !== 0;
}
function isConstEnumObjectType(type: Type) : boolean {
function isConstEnumObjectType(type: Type): boolean {
return type.flags & (TypeFlags.ObjectType | TypeFlags.Anonymous) && type.symbol && isConstEnumSymbol(type.symbol);
}
@@ -6634,8 +6648,8 @@ module ts {
// if a user tries to apply a bitwise operator to 2 boolean operands
// try and return them a helpful suggestion
if ((leftType.flags & TypeFlags.Boolean) &&
(rightType.flags & TypeFlags.Boolean) &&
(suggestedOperator = getSuggestedBooleanOperator(node.operator)) !== undefined) {
(rightType.flags & TypeFlags.Boolean) &&
(suggestedOperator = getSuggestedBooleanOperator(node.operator)) !== undefined) {
error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operator), tokenToString(suggestedOperator));
}
else {
@@ -6644,7 +6658,7 @@ module ts {
var rightOk = checkArithmeticOperandType(node.right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
if (leftOk && rightOk) {
checkAssignmentOperator(numberType);
}
}
}
return numberType;
@@ -6709,8 +6723,8 @@ module ts {
case SyntaxKind.CommaToken:
return rightType;
}
function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind {
function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind {
switch (operator) {
case SyntaxKind.BarToken:
case SyntaxKind.BarEqualsToken:
@@ -6899,51 +6913,19 @@ module ts {
}
function checkParameter(node: ParameterDeclaration) {
checkVariableDeclaration(node);
if (isBindingPattern(node.name)) {
return;
}
checkVariableLikeDeclaration(node);
var func = getContainingFunction(node);
if (node.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected) &&
!(func.kind === SyntaxKind.Constructor && func.body)) {
error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
if (node.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected)) {
func = getContainingFunction(node);
if (!(func.kind === SyntaxKind.Constructor && func.body)) {
error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
}
}
if (node.dotDotDotToken) {
if (!isArrayType(getTypeOfSymbol(node.symbol))) {
error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
}
}
if (node.initializer) {
if (!func.body) {
error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
}
checkReferencesInInitializer(node.initializer);
}
function checkReferencesInInitializer(n: Node): void {
if (n.kind === SyntaxKind.Identifier) {
var referencedSymbol = getNodeLinks(n).resolvedSymbol;
// check FunctionLikeDeclaration.locals (stores parameters\function local variable)
// if it contains entry with a specified name and if this entry matches the resolved symbol
if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, SymbolFlags.Value) === referencedSymbol) {
if (referencedSymbol.valueDeclaration.kind === SyntaxKind.Parameter) {
if (referencedSymbol.valueDeclaration === node) {
error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(node.name));
return;
}
if (referencedSymbol.valueDeclaration.pos < node.pos) {
// legal case - parameter initializer references some parameter strictly on left of current parameter declaration
return;
}
// fall through to error reporting
}
error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(node.name), declarationNameToString(<Identifier>n));
}
}
else {
forEachChild(n, checkReferencesInInitializer);
}
}
}
function checkSignatureDeclaration(node: SignatureDeclaration) {
@@ -6988,7 +6970,7 @@ module ts {
var seenStringIndexer = false;
for (var i = 0, len = indexSymbol.declarations.length; i < len; ++i) {
var declaration = <SignatureDeclaration>indexSymbol.declarations[i];
if (declaration.parameters.length == 1 && declaration.parameters[0].type) {
if (declaration.parameters.length == 1 && declaration.parameters[0].type) {
switch (declaration.parameters[0].type.kind) {
case SyntaxKind.StringKeyword:
if (!seenStringIndexer) {
@@ -7013,8 +6995,7 @@ module ts {
}
function checkPropertyDeclaration(node: PropertyDeclaration) {
// TODO(andesh): Reconcile declaration types
checkVariableDeclaration(<VariableDeclaration><Declaration>node);
checkVariableLikeDeclaration(node);
}
function checkMethodDeclaration(node: MethodDeclaration) {
@@ -7077,7 +7058,7 @@ module ts {
// Constructors of classes with no extends clause may not contain super calls, whereas
// constructors of derived classes must contain at least one super call somewhere in their function body.
if (getClassBaseTypeNode(<ClassDeclaration>node.parent)) {
if (containsSuperCall(node.body)) {
// The first statement in the body of a constructor must be a super call if both of the following are true:
// - The containing class is a derived class.
@@ -7517,7 +7498,7 @@ module ts {
case SyntaxKind.ImportDeclaration:
var result: SymbolFlags = 0;
var target = resolveImport(getSymbolOfNode(d));
forEach(target.declarations, d => { result |= getDeclarationSpaces(d); } );
forEach(target.declarations, d => { result |= getDeclarationSpaces(d); });
return result;
default:
return SymbolFlags.ExportValue;
@@ -7606,7 +7587,8 @@ module ts {
return false;
}
if (node.kind === SyntaxKind.Parameter && !(<FunctionLikeDeclaration>node.parent).body) {
var root = getRootDeclaration(node);
if (root.kind === SyntaxKind.Parameter && !(<FunctionLikeDeclaration>root.parent).body) {
// just an overload - no codegen impact
return false;
}
@@ -7672,7 +7654,7 @@ module ts {
}
// In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
var parent = getDeclarationContainer(node);
if (parent.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>parent)) {
// If the declaration happens to be in external module, report error that require and exports are reserved keywords
error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module,
@@ -7680,7 +7662,7 @@ module ts {
}
}
function checkCollisionWithConstDeclarations(node: VariableOrParameterDeclaration) {
function checkCollisionWithConstDeclarations(node: VariableLikeDeclaration) {
// Variable declarations are hoisted to the top of their function scope. They can shadow
// block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
// by the binder as the declaration scope is different.
@@ -7712,30 +7694,84 @@ module ts {
}
}
function checkVariableDeclaration(node: VariableDeclaration) {
function isParameterDeclaration(node: VariableLikeDeclaration) {
while (node.kind === SyntaxKind.BindingElement) {
node = <VariableLikeDeclaration>node.parent.parent;
}
return node.kind === SyntaxKind.Parameter;
}
// Check that a parameter initializer contains no references to parameters declared to the right of itself
function checkParameterInitializer(node: VariableLikeDeclaration): void {
if (getRootDeclaration(node).kind === SyntaxKind.Parameter) {
var func = getContainingFunction(node);
visit(node.initializer);
}
function visit(n: Node) {
if (n.kind === SyntaxKind.Identifier) {
var referencedSymbol = getNodeLinks(n).resolvedSymbol;
// check FunctionLikeDeclaration.locals (stores parameters\function local variable)
// if it contains entry with a specified name and if this entry matches the resolved symbol
if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, SymbolFlags.Value) === referencedSymbol) {
if (referencedSymbol.valueDeclaration.kind === SyntaxKind.Parameter) {
if (referencedSymbol.valueDeclaration === node) {
error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(node.name));
return;
}
if (referencedSymbol.valueDeclaration.pos < node.pos) {
// legal case - parameter initializer references some parameter strictly on left of current parameter declaration
return;
}
// fall through to error reporting
}
error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(node.name), declarationNameToString(<Identifier>n));
}
}
else {
forEachChild(n, visit);
}
}
}
// Check variable, parameter, or property declaration
function checkVariableLikeDeclaration(node: VariableLikeDeclaration) {
checkSourceElement(node.type);
if (isBindingPattern(node.name)) {
forEach((<BindingPattern>node.name).elements, checkSourceElement);
// For a computed property, just check the initializer and exit
if (hasComputedNameButNotSymbol(node)) {
if (node.initializer) {
checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableDeclaration(node), node, /*headMessage*/ undefined);
checkExpressionCached(node.initializer);
}
return;
}
if (hasComputedNameButNotSymbol(node)) {
// Just check the initializer, since this property won't contribute to the enclosing type
// For a binding pattern, check contained binding elements
if (isBindingPattern(node.name)) {
forEach((<BindingPattern>node.name).elements, checkSourceElement);
}
// For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && !getContainingFunction(node).body) {
error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
return;
}
// For a binding pattern, validate the initializer and exit
if (isBindingPattern(node.name)) {
if (node.initializer) {
checkExpressionCached(node.initializer);
checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableDeclaration(node), node, /*headMessage*/ undefined);
checkParameterInitializer(node);
}
return;
}
var symbol = getSymbolOfNode(node);
var type = getTypeOfVariableOrParameterOrProperty(symbol);
if (node === symbol.valueDeclaration) {
// Node is the primary declaration of the symbol, just validate the initializer
if (node.initializer) {
checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
checkParameterInitializer(node);
}
}
else {
// Node is a secondary declaration, check that type is identical to primary declaration and check that
// initializer is consistent with type associated with the node
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));
@@ -7747,7 +7783,7 @@ module ts {
if (node.kind !== SyntaxKind.Property) {
// We know we don't have a binding pattern or computed name here
checkExportsOnMergedDeclarations(node);
checkCollisionWithConstDeclarations(<VariableDeclaration>node);
checkCollisionWithConstDeclarations(node);
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
@@ -7779,7 +7815,7 @@ module ts {
}
function checkForStatement(node: ForStatement) {
if (node.declarations) forEach(node.declarations, checkVariableDeclaration);
if (node.declarations) forEach(<VariableLikeDeclaration[]>node.declarations, checkVariableLikeDeclaration);
if (node.initializer) checkExpression(node.initializer);
if (node.condition) checkExpression(node.condition);
if (node.iterator) checkExpression(node.iterator);
@@ -7796,7 +7832,7 @@ module ts {
if (node.declarations) {
if (node.declarations.length >= 1) {
var decl = node.declarations[0];
checkVariableDeclaration(decl);
checkVariableLikeDeclaration(decl);
if (decl.type) {
error(decl, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
}
@@ -8646,7 +8682,8 @@ module ts {
case SyntaxKind.TryStatement:
return checkTryStatement(<TryStatement>node);
case SyntaxKind.VariableDeclaration:
return checkVariableDeclaration(<VariableDeclaration>node);
case SyntaxKind.BindingElement:
return checkVariableLikeDeclaration(<VariableLikeDeclaration>node);
case SyntaxKind.ClassDeclaration:
return checkClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.InterfaceDeclaration:
@@ -8694,6 +8731,7 @@ module ts {
case SyntaxKind.Property:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.BindingElement:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.PropertyAssignment:
@@ -8973,7 +9011,7 @@ module ts {
case SyntaxKind.Property:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
return node === (<VariableDeclaration>parent).type;
return node === (<VariableLikeDeclaration>parent).type;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
@@ -9394,7 +9432,7 @@ module ts {
return undefined;
}
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
// Get type of the symbol if this is the valid symbol otherwise get type at location
var symbol = getSymbolOfNode(declaration);
var type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
+7 -6
View File
@@ -440,7 +440,7 @@ module ts {
handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
}
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, type: TypeNode | StringLiteralExpression, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode | StringLiteralExpression, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
write(": ");
if (type) {
@@ -996,7 +996,7 @@ module ts {
}
}
function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableOrParameterDeclaration) {
function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableLikeDeclaration) {
// if this is property of type literal,
// or is parameter of method/call/construct/index signature of type literal
// emit only if type is specified
@@ -2149,6 +2149,7 @@ module ts {
switch (parent.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
@@ -2761,10 +2762,10 @@ module ts {
emitEnd(node.name);
}
function emitDestructuring(root: BinaryExpression | BindingElement, value?: Expression) {
function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, value?: Expression) {
var emitCount = 0;
// An exported declaration is actually emitted as an assignment (to a property on the module object), so
// temporary variables in an exported declaration need to have real declarations elsewhere.
// temporary variables in an exported declaration need to have real declarations elsewhere
var isDeclaration = (root.kind === SyntaxKind.VariableDeclaration && !(root.flags & NodeFlags.Export)) || root.kind === SyntaxKind.Parameter;
if (root.kind === SyntaxKind.BinaryExpression) {
emitAssignmentExpression(<BinaryExpression>root);
@@ -2777,8 +2778,8 @@ module ts {
if (emitCount++) {
write(", ");
}
if (name.parent && name.parent.kind === SyntaxKind.VariableDeclaration) {
emitModuleMemberName(<VariableDeclaration>name.parent);
if (name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement)) {
emitModuleMemberName(<Declaration>name.parent);
}
else {
emit(name);
+38 -32
View File
@@ -102,6 +102,7 @@ module ts {
// This list is a work in progress. Add missing node kinds to improve their error
// spans.
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
@@ -216,13 +217,14 @@ module ts {
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
return children(node.modifiers) ||
child((<VariableDeclaration>node).propertyName) ||
child((<VariableDeclaration>node).dotDotDotToken) ||
child((<VariableDeclaration>node).name) ||
child((<VariableDeclaration>node).questionToken) ||
child((<VariableDeclaration>node).type) ||
child((<VariableDeclaration>node).initializer);
child((<VariableLikeDeclaration>node).propertyName) ||
child((<VariableLikeDeclaration>node).dotDotDotToken) ||
child((<VariableLikeDeclaration>node).name) ||
child((<VariableLikeDeclaration>node).questionToken) ||
child((<VariableLikeDeclaration>node).type) ||
child((<VariableLikeDeclaration>node).initializer);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.CallSignature:
@@ -580,7 +582,8 @@ module ts {
case SyntaxKind.Property:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
return (<VariableDeclaration>parent).initializer === node;
case SyntaxKind.BindingElement:
return (<VariableLikeDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
@@ -679,6 +682,7 @@ module ts {
case SyntaxKind.TypeParameter:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
@@ -1892,12 +1896,7 @@ module ts {
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
var savedYieldContext = inYieldContext();
if (inGeneratorParameterContext()) {
setYieldContext(true);
}
node.name = parseIdentifierOrPattern(SyntaxKind.Parameter);
setYieldContext(savedYieldContext);
node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
// in cases like
@@ -1913,9 +1912,7 @@ module ts {
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
node.type = parseParameterType();
node.initializer = inGeneratorParameterContext()
? doOutsideOfYieldContext(parseParameterInitializer)
: parseParameterInitializer();
node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
// 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
@@ -3691,11 +3688,11 @@ module ts {
// DECLARATIONS
function parseBindingElement(kind: SyntaxKind, context: ParsingContext): BindingElement {
function parseBindingElement(context: ParsingContext): BindingElement {
if (context === ParsingContext.ArrayBindingElements && token === SyntaxKind.CommaToken) {
return <BindingElement>createNode(SyntaxKind.OmittedExpression);
}
var node = <BindingElement>createNode(kind);
var node = <BindingElement>createNode(SyntaxKind.BindingElement);
if (context === ParsingContext.ObjectBindingElements) {
// TODO(andersh): Handle computed properties
var id = parsePropertyName();
@@ -3705,32 +3702,32 @@ module ts {
else {
parseExpected(SyntaxKind.ColonToken);
node.propertyName = <Identifier>id;
node.name = parseIdentifierOrPattern(kind);
node.name = parseIdentifierOrPattern();
}
}
else {
node.name = parseIdentifierOrPattern(kind);
node.name = parseIdentifierOrPattern();
}
node.initializer = parseInitializer(/*inParameter*/ false);
return finishNode(node);
}
function parseBindingList(kind: SyntaxKind, context: ParsingContext): NodeArray<BindingElement> {
return parseDelimitedList(context, () => parseBindingElement(kind, context));
function parseBindingList(context: ParsingContext): NodeArray<BindingElement> {
return parseDelimitedList(context, () => parseBindingElement(context));
}
function parseObjectBindingPattern(kind: SyntaxKind): BindingPattern {
function parseObjectBindingPattern(): BindingPattern {
var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
parseExpected(SyntaxKind.OpenBraceToken);
node.elements = parseBindingList(kind, ParsingContext.ObjectBindingElements);
node.elements = parseBindingList(ParsingContext.ObjectBindingElements);
parseExpected(SyntaxKind.CloseBraceToken);
return finishNode(node);
}
function parseArrayBindingPattern(kind: SyntaxKind): BindingPattern {
function parseArrayBindingPattern(): BindingPattern {
var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
parseExpected(SyntaxKind.OpenBracketToken);
node.elements = parseBindingList(kind, ParsingContext.ArrayBindingElements);
node.elements = parseBindingList(ParsingContext.ArrayBindingElements);
parseExpected(SyntaxKind.CloseBracketToken);
return finishNode(node);
}
@@ -3739,19 +3736,19 @@ module ts {
return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();
}
function parseIdentifierOrPattern(kind: SyntaxKind): Identifier | BindingPattern {
function parseIdentifierOrPattern(): Identifier | BindingPattern {
if (token === SyntaxKind.OpenBracketToken) {
return parseArrayBindingPattern(kind);
return parseArrayBindingPattern();
}
if (token === SyntaxKind.OpenBraceToken) {
return parseObjectBindingPattern(kind);
return parseObjectBindingPattern();
}
return parseIdentifier();
}
function parseVariableDeclaration(): VariableDeclaration {
var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);
node.name = parseIdentifierOrPattern(SyntaxKind.VariableDeclaration);
node.name = parseIdentifierOrPattern();
node.type = parseTypeAnnotation();
node.initializer = parseInitializer(/*inParameter*/ false);
return finishNode(node);
@@ -4492,6 +4489,7 @@ module ts {
case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.BinaryExpression: return checkBinaryExpression(<BinaryExpression>node);
case SyntaxKind.BindingElement: return checkBindingElement(<BindingElement>node);
case SyntaxKind.CatchClause: return checkCatchClause(<CatchClause>node);
case SyntaxKind.ClassDeclaration: return checkClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.ComputedPropertyName: return checkComputedPropertyName(<ComputedPropertyName>node);
@@ -5594,14 +5592,22 @@ module ts {
return checkTypeArguments(node.typeArguments);
}
function checkBindingElement(node: BindingElement) {
if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.name)) {
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
// and its Identifier is eval or arguments
return reportInvalidUseInStrictMode(<Identifier>node.name);
}
}
function checkVariableDeclaration(node: VariableDeclaration) {
if (inAmbientContext) {
if (isBindingPattern(node.name)) {
return grammarErrorOnNode(node, Diagnostics.Destructuring_declarations_are_not_allowed_in_ambient_contexts);
}
if (node.initializer) {
var equalsPos = node.type ? skipTrivia(sourceText, node.type.end) : skipTrivia(sourceText, node.name.end);
return grammarErrorAtPos(equalsPos, "=".length, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
// Error on equals token which immediate precedes the initializer
return grammarErrorAtPos(node.initializer.pos - 1, 1, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
}
}
else {
+46 -17
View File
@@ -168,6 +168,7 @@ module ts {
// Binding patterns
ObjectBindingPattern,
ArrayBindingPattern,
BindingElement,
// Expression
ArrayLiteralExpression,
ObjectLiteralExpression,
@@ -366,35 +367,63 @@ module ts {
export interface SignatureDeclaration extends Declaration, ParsedSignature {
}
// SyntaxKind.VariableDeclaration
export interface VariableDeclaration extends Declaration {
propertyName?: Identifier; // Binding property name (in object binding pattern)
dotDotDotToken?: Node; // Present on rest parameter or rest element in binding pattern
name: Identifier | BindingPattern; // Declared variable name
questionToken?: Node; // Present on optional parameter or property
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
export interface BindingPattern extends Node {
elements: NodeArray<BindingElement>;
// SyntaxKind.Parameter
export interface ParameterDeclaration extends Declaration {
dotDotDotToken?: Node; // Present on rest parameter
name: Identifier | BindingPattern; // Declared parameter name
questionToken?: Node; // Present on optional parameter
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
export interface BindingElement extends VariableDeclaration { }
export interface ParameterDeclaration extends VariableDeclaration { }
// SyntaxKind.BindingElement
export interface BindingElement extends Declaration {
propertyName?: Identifier; // Binding property name (in object binding pattern)
dotDotDotToken?: Node; // Present on rest binding element
name: Identifier | BindingPattern; // Declared binding element name
initializer?: Expression; // Optional initializer
}
// SyntaxKind.Property
// SyntaxKind.PropertyAssignment
export interface PropertyDeclaration extends Declaration, ClassElement {
name: DeclarationName; // Declared property name
questionToken?: Node; // Present on optional property
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
// SyntaxKind.ShorthandPropertyAssignment
export interface ShorthandPropertyDeclaration extends Declaration {
name: Identifier;
questionToken?: Node;
}
// SyntaxKind.VariableDeclaration
// SyntaxKind.Parameter
// SyntaxKind.BindingElement
// SyntaxKind.Property
// SyntaxKind.PropertyAssignment
// SyntaxKind.ShorthandPropertyAssignment
// SyntaxKind.EnumMember
export interface VariableLikeDeclaration extends Declaration {
propertyName?: Identifier;
dotDotDotToken?: Node;
name: DeclarationName;
questionToken?: Node;
type?: TypeNode;
initializer?: Expression;
}
export type VariableOrParameterDeclaration = VariableDeclaration | ParameterDeclaration;
export type VariableOrParameterOrPropertyDeclaration = VariableOrParameterDeclaration | PropertyDeclaration;
export interface ShorthandPropertyDeclaration extends Declaration {
name: Identifier;
questionToken?: Node;
export interface BindingPattern extends Node {
elements: NodeArray<BindingElement>;
}
/**
@@ -1004,7 +1033,7 @@ module ts {
hasSemanticErrors(sourceFile?: SourceFile): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
@@ -1056,9 +1085,9 @@ module ts {
Module = ValueModule | NamespaceModule,
Accessor = GetAccessor | SetAccessor,
// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
// same name, or any other value that is not a variable, e.g. ValueModule or Class
FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable,
FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable,
// Block-scoped declarations are not allowed to be re-declared
// they can not merge with anything in the value space
+3
View File
@@ -224,6 +224,9 @@ module ts.NavigationBar {
function createChildItem(node: Node): ts.NavigationBarItem {
switch (node.kind) {
case SyntaxKind.Parameter:
if (isBindingPattern((<VariableDeclaration>node).name)) {
break;
}
if ((node.flags & NodeFlags.Modifier) === 0) {
return undefined;
}
+2
View File
@@ -819,6 +819,7 @@ module ts {
}
// fall through
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
if (isBindingPattern((<VariableDeclaration>node).name)) {
forEachChild((<VariableDeclaration>node).name, visit);
break;
@@ -4712,6 +4713,7 @@ module ts {
switch (node.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment: