mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-22 09:49:44 -05:00
Merge pull request #1463 from Microsoft/spreadAndRest
ECMAScript 6 spread and rest support
This commit is contained in:
@@ -1674,19 +1674,26 @@ module ts {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
|
||||
return unknownType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
// For an array binding element the specified or inferred type of the parent must be assignable to any[]
|
||||
if (!isTypeAssignableTo(parentType, anyArrayType)) {
|
||||
error(pattern, Diagnostics.Type_0_is_not_an_array_type, typeToString(parentType));
|
||||
return unknownType;
|
||||
}
|
||||
// Use specific property type when parent is a tuple or numeric index type when parent is an array
|
||||
var propName = "" + indexOf(pattern.elements, declaration);
|
||||
var type = isTupleLikeType(parentType) ? getTypeOfPropertyOfType(parentType, propName) : getIndexTypeOfType(parentType, IndexKind.Number);
|
||||
if (!type) {
|
||||
error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
|
||||
return unknownType;
|
||||
else {
|
||||
// For an array binding element the specified or inferred type of the parent must be assignable to any[]
|
||||
if (!isTypeAssignableTo(parentType, anyArrayType)) {
|
||||
error(pattern, Diagnostics.Type_0_is_not_an_array_type, typeToString(parentType));
|
||||
return unknownType;
|
||||
}
|
||||
if (!declaration.dotDotDotToken) {
|
||||
// Use specific property type when parent is a tuple or numeric index type when parent is an array
|
||||
var propName = "" + indexOf(pattern.elements, declaration);
|
||||
var type = isTupleLikeType(parentType) ? getTypeOfPropertyOfType(parentType, propName) : getIndexTypeOfType(parentType, IndexKind.Number);
|
||||
if (!type) {
|
||||
error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Rest element has an array type with the same element type as the parent type
|
||||
var type = createArrayType(getIndexTypeOfType(parentType, IndexKind.Number));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -1744,17 +1751,8 @@ module ts {
|
||||
return anyType;
|
||||
}
|
||||
|
||||
// Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
|
||||
// and without regard to its context (i.e. without regard any type annotation or initializer associated with the
|
||||
// declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any]
|
||||
// and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is
|
||||
// used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
|
||||
// parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
|
||||
// the parameter.
|
||||
function getTypeFromBindingPattern(pattern: BindingPattern): Type {
|
||||
if (pattern.kind === SyntaxKind.ArrayBindingPattern) {
|
||||
return createTupleType(map(pattern.elements, e => e.kind === SyntaxKind.OmittedExpression ? anyType : getTypeFromBindingElement(e)));
|
||||
}
|
||||
// Return the type implied by an object binding pattern
|
||||
function getTypeFromObjectBindingPattern(pattern: BindingPattern): Type {
|
||||
var members: SymbolTable = {};
|
||||
forEach(pattern.elements, e => {
|
||||
var flags = SymbolFlags.Property | SymbolFlags.Transient | (e.initializer ? SymbolFlags.Optional : 0);
|
||||
@@ -1766,6 +1764,32 @@ module ts {
|
||||
return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
|
||||
}
|
||||
|
||||
// Return the type implied by an array binding pattern
|
||||
function getTypeFromArrayBindingPattern(pattern: BindingPattern): Type {
|
||||
var hasSpreadElement: boolean = false;
|
||||
var elementTypes: Type[] = [];
|
||||
forEach(pattern.elements, e => {
|
||||
elementTypes.push(e.kind === SyntaxKind.OmittedExpression || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
|
||||
if (e.dotDotDotToken) {
|
||||
hasSpreadElement = true;
|
||||
}
|
||||
});
|
||||
return !elementTypes.length ? anyArrayType : hasSpreadElement ? createArrayType(getUnionType(elementTypes)) : createTupleType(elementTypes);
|
||||
}
|
||||
|
||||
// Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
|
||||
// and without regard to its context (i.e. without regard any type annotation or initializer associated with the
|
||||
// declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any]
|
||||
// and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is
|
||||
// used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
|
||||
// parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
|
||||
// the parameter.
|
||||
function getTypeFromBindingPattern(pattern: BindingPattern): Type {
|
||||
return pattern.kind === SyntaxKind.ObjectBindingPattern
|
||||
? getTypeFromObjectBindingPattern(pattern)
|
||||
: getTypeFromArrayBindingPattern(pattern);
|
||||
}
|
||||
|
||||
// Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
|
||||
// specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it
|
||||
// is a bit more involved. For example:
|
||||
@@ -4510,6 +4534,7 @@ module ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.VariableStatement:
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
@@ -5306,15 +5331,37 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkSpreadElementExpression(node: SpreadElementExpression, contextualMapper?: TypeMapper): Type {
|
||||
var type = checkExpressionCached(node.expression, contextualMapper);
|
||||
if (!isTypeAssignableTo(type, anyArrayType)) {
|
||||
error(node.expression, Diagnostics.Type_0_is_not_an_array_type, typeToString(type));
|
||||
return unknownType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type {
|
||||
var elements = node.elements;
|
||||
if (!elements.length) {
|
||||
return createArrayType(undefinedType);
|
||||
}
|
||||
var elementTypes = map(elements, e => checkExpression(e, contextualMapper));
|
||||
var contextualType = getContextualType(node);
|
||||
if ((contextualType && contextualTypeIsTupleLikeType(contextualType)) || isAssignmentTarget(node)) {
|
||||
return createTupleType(elementTypes);
|
||||
var hasSpreadElement: boolean = false;
|
||||
var elementTypes: Type[] = [];
|
||||
forEach(elements, e => {
|
||||
var type = checkExpression(e, contextualMapper);
|
||||
if (e.kind === SyntaxKind.SpreadElementExpression) {
|
||||
elementTypes.push(getIndexTypeOfType(type, IndexKind.Number) || anyType);
|
||||
hasSpreadElement = true;
|
||||
}
|
||||
else {
|
||||
elementTypes.push(type);
|
||||
}
|
||||
});
|
||||
if (!hasSpreadElement) {
|
||||
var contextualType = getContextualType(node);
|
||||
if (contextualType && contextualTypeIsTupleLikeType(contextualType) || isAssignmentTarget(node)) {
|
||||
return createTupleType(elementTypes);
|
||||
}
|
||||
}
|
||||
return createArrayType(getUnionType(elementTypes));
|
||||
}
|
||||
@@ -6715,15 +6762,25 @@ module ts {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var e = elements[i];
|
||||
if (e.kind !== SyntaxKind.OmittedExpression) {
|
||||
var propName = "" + i;
|
||||
var type = sourceType.flags & TypeFlags.Any ? sourceType :
|
||||
isTupleLikeType(sourceType) ? getTypeOfPropertyOfType(sourceType, propName) :
|
||||
getIndexTypeOfType(sourceType, IndexKind.Number);
|
||||
if (type) {
|
||||
checkDestructuringAssignment(e, type, contextualMapper);
|
||||
if (e.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
var propName = "" + i;
|
||||
var type = sourceType.flags & TypeFlags.Any ? sourceType :
|
||||
isTupleLikeType(sourceType) ? getTypeOfPropertyOfType(sourceType, propName) :
|
||||
getIndexTypeOfType(sourceType, IndexKind.Number);
|
||||
if (type) {
|
||||
checkDestructuringAssignment(e, type, contextualMapper);
|
||||
}
|
||||
else {
|
||||
error(e, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(e, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
|
||||
if (i === elements.length - 1) {
|
||||
checkReferenceAssignment((<SpreadElementExpression>e).expression, sourceType, contextualMapper);
|
||||
}
|
||||
else {
|
||||
error(e, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6741,6 +6798,10 @@ module ts {
|
||||
if (target.kind === SyntaxKind.ArrayLiteralExpression) {
|
||||
return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, contextualMapper);
|
||||
}
|
||||
return checkReferenceAssignment(target, sourceType, contextualMapper);
|
||||
}
|
||||
|
||||
function checkReferenceAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
|
||||
var targetType = checkExpression(target, contextualMapper);
|
||||
if (checkReferenceExpression(target, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
|
||||
checkTypeAssignableTo(sourceType, targetType, target, /*headMessage*/ undefined);
|
||||
@@ -7081,6 +7142,8 @@ module ts {
|
||||
return checkBinaryExpression(<BinaryExpression>node, contextualMapper);
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return checkConditionalExpression(<ConditionalExpression>node, contextualMapper);
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
return checkSpreadElementExpression(<SpreadElementExpression>node, contextualMapper);
|
||||
case SyntaxKind.OmittedExpression:
|
||||
return undefinedType;
|
||||
case SyntaxKind.YieldExpression:
|
||||
@@ -7987,15 +8050,6 @@ module ts {
|
||||
|
||||
// Check variable, parameter, or property declaration
|
||||
function checkVariableLikeDeclaration(node: VariableLikeDeclaration) {
|
||||
// Grammar checking
|
||||
// TODO (yuisu) : Revisit this check once move all grammar checking
|
||||
if (node.kind === SyntaxKind.BindingElement) {
|
||||
checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
checkGrammarVariableDeclaration(<VariableDeclaration>node);
|
||||
}
|
||||
|
||||
checkSourceElement(node.type);
|
||||
// For a computed property, just check the initializer and exit
|
||||
if (hasComputedNameButNotSymbol(node)) {
|
||||
@@ -8051,6 +8105,16 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkVariableDeclaration(node: VariableDeclaration) {
|
||||
checkGrammarVariableDeclaration(node);
|
||||
return checkVariableLikeDeclaration(node);
|
||||
}
|
||||
|
||||
function checkBindingElement(node: BindingElement) {
|
||||
checkGrammarBindingElement(<BindingElement>node);
|
||||
return checkVariableLikeDeclaration(node);
|
||||
}
|
||||
|
||||
function checkVariableStatement(node: VariableStatement) {
|
||||
// Grammar checking
|
||||
checkGrammarModifiers(node) || checkGrammarVariableDeclarations(node, node.declarations) || checkGrammarForDisallowedLetOrConstStatement(node);
|
||||
@@ -8094,7 +8158,7 @@ module ts {
|
||||
// Grammar checking
|
||||
checkGrammarForStatementInAmbientContext(node) || checkGrammarVariableDeclarations(node, node.declarations);
|
||||
|
||||
if (node.declarations) forEach(<VariableLikeDeclaration[]>node.declarations, checkVariableLikeDeclaration);
|
||||
if (node.declarations) forEach(node.declarations, checkVariableDeclaration);
|
||||
if (node.initializer) checkExpression(node.initializer);
|
||||
if (node.condition) checkExpression(node.condition);
|
||||
if (node.iterator) checkExpression(node.iterator);
|
||||
@@ -8120,7 +8184,7 @@ module ts {
|
||||
if (node.declarations) {
|
||||
if (node.declarations.length >= 1) {
|
||||
var decl = node.declarations[0];
|
||||
checkVariableLikeDeclaration(decl);
|
||||
checkVariableDeclaration(decl);
|
||||
if (decl.type) {
|
||||
error(decl, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
|
||||
}
|
||||
@@ -9092,8 +9156,9 @@ module ts {
|
||||
case SyntaxKind.TryStatement:
|
||||
return checkTryStatement(<TryStatement>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return checkVariableDeclaration(<VariableDeclaration>node);
|
||||
case SyntaxKind.BindingElement:
|
||||
return checkVariableLikeDeclaration(<VariableLikeDeclaration>node);
|
||||
return checkBindingElement(<BindingElement>node);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return checkClassDeclaration(<ClassDeclaration>node);
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
@@ -9172,6 +9237,7 @@ module ts {
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.VariableStatement:
|
||||
@@ -10535,6 +10601,22 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkGrammarBindingElement(node: BindingElement) {
|
||||
if (node.dotDotDotToken) {
|
||||
var elements = (<BindingPattern>node.parent).elements;
|
||||
if (node !== elements[elements.length - 1]) {
|
||||
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
}
|
||||
if (node.initializer) {
|
||||
// Error on equals token which immediate precedes the initializer
|
||||
return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
|
||||
}
|
||||
}
|
||||
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
|
||||
// and its Identifier is eval or arguments
|
||||
return checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
|
||||
}
|
||||
|
||||
function checkGrammarVariableDeclaration(node: VariableDeclaration) {
|
||||
if (isInAmbientContext(node)) {
|
||||
if (isBindingPattern(node.name)) {
|
||||
@@ -10557,7 +10639,7 @@ module ts {
|
||||
}
|
||||
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
|
||||
// and its Identifier is eval or arguments
|
||||
return checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
|
||||
return checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
|
||||
}
|
||||
|
||||
function checkGrammarVariableDeclarations(container: Node, declarations: NodeArray<VariableDeclaration>): boolean {
|
||||
|
||||
@@ -144,6 +144,7 @@ module ts {
|
||||
Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts.", isEarly: true },
|
||||
An_implementation_cannot_be_declared_in_ambient_contexts: { code: 1184, category: DiagnosticCategory.Error, key: "An implementation cannot be declared in ambient contexts.", isEarly: true },
|
||||
Merge_conflict_marker_encountered: { code: 1184, category: DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
|
||||
A_rest_element_cannot_have_an_initializer: { code: 1185, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
|
||||
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." },
|
||||
@@ -294,6 +295,7 @@ module ts {
|
||||
Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." },
|
||||
Type_0_has_no_property_1: { code: 2460, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." },
|
||||
Type_0_is_not_an_array_type: { code: 2461, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type." },
|
||||
A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" },
|
||||
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}'." },
|
||||
|
||||
@@ -665,6 +665,10 @@
|
||||
"category": "Error",
|
||||
"code": 1184
|
||||
},
|
||||
"A rest element cannot have an initializer.": {
|
||||
"category": "Error",
|
||||
"code": 1185
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
@@ -1270,6 +1274,10 @@
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
"A rest element must be last in an array destructuring pattern": {
|
||||
"category": "Error",
|
||||
"code": 2462
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -1949,35 +1949,58 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitParenthesized(node: Node, parenthesized: boolean) {
|
||||
if (parenthesized) {
|
||||
write("(");
|
||||
}
|
||||
emit(node);
|
||||
if (parenthesized) {
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingCommaIfPresent(nodeList: NodeArray<Node>): void {
|
||||
if (nodeList.hasTrailingComma) {
|
||||
write(",");
|
||||
}
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[], count?: number) {
|
||||
if (!(count >= 0)) {
|
||||
count = nodes.length;
|
||||
function emitList(nodes: Node[], start: number, count: number, multiLine: boolean, trailingComma: boolean) {
|
||||
if (multiLine) {
|
||||
increaseIndent();
|
||||
}
|
||||
if (nodes) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (multiLine) {
|
||||
if (i) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
}
|
||||
else {
|
||||
if (i) {
|
||||
write(", ");
|
||||
}
|
||||
emit(nodes[i]);
|
||||
}
|
||||
emit(nodes[start + i]);
|
||||
}
|
||||
if (trailingComma) {
|
||||
write(",");
|
||||
}
|
||||
if (multiLine) {
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[]) {
|
||||
if (nodes) {
|
||||
emitList(nodes, 0, nodes.length, /*multiline*/ false, /*trailingComma*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
function emitMultiLineList(nodes: Node[]) {
|
||||
if (nodes) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (i) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
emit(nodes[i]);
|
||||
}
|
||||
emitList(nodes, 0, nodes.length, /*multiline*/ true, /*trailingComma*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2055,17 +2078,8 @@ module ts {
|
||||
// "abc" + (1 << 2) + ""
|
||||
var needsParens = templateSpan.expression.kind !== SyntaxKind.ParenthesizedExpression
|
||||
&& comparePrecedenceToBinaryPlus(templateSpan.expression) !== Comparison.GreaterThan;
|
||||
|
||||
write(" + ");
|
||||
|
||||
if (needsParens) {
|
||||
write("(");
|
||||
}
|
||||
emit(templateSpan.expression);
|
||||
if (needsParens) {
|
||||
write(")");
|
||||
}
|
||||
|
||||
emitParenthesized(templateSpan.expression, needsParens);
|
||||
// Only emit if the literal is non-empty.
|
||||
// The binary '+' operator is left-associative, so the first string concatenation
|
||||
// with the head will force the result up to this point to be a string.
|
||||
@@ -2235,59 +2249,118 @@ module ts {
|
||||
|
||||
function emitObjectBindingPattern(node: BindingPattern) {
|
||||
write("{ ");
|
||||
emitCommaList(node.elements);
|
||||
emitTrailingCommaIfPresent(node.elements);
|
||||
var elements = node.elements;
|
||||
emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma);
|
||||
write(" }");
|
||||
}
|
||||
|
||||
function emitArrayBindingPattern(node: BindingPattern) {
|
||||
write("[");
|
||||
emitCommaList(node.elements);
|
||||
emitTrailingCommaIfPresent(node.elements);
|
||||
var elements = node.elements;
|
||||
emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma);
|
||||
write("]");
|
||||
}
|
||||
|
||||
function emitArrayLiteral(node: ArrayLiteralExpression) {
|
||||
if (node.flags & NodeFlags.MultiLine) {
|
||||
write("[");
|
||||
increaseIndent();
|
||||
emitMultiLineList(node.elements);
|
||||
emitTrailingCommaIfPresent(node.elements);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("]");
|
||||
function emitBindingElement(node: BindingElement) {
|
||||
if (node.propertyName) {
|
||||
emit(node.propertyName);
|
||||
write(": ");
|
||||
}
|
||||
if (node.dotDotDotToken) {
|
||||
write("...");
|
||||
}
|
||||
if (isBindingPattern(node.name)) {
|
||||
emit(node.name);
|
||||
}
|
||||
else {
|
||||
emitModuleMemberName(node);
|
||||
}
|
||||
emitOptional(" = ", node.initializer);
|
||||
}
|
||||
|
||||
function emitSpreadElementExpression(node: SpreadElementExpression) {
|
||||
write("...");
|
||||
emit((<SpreadElementExpression>node).expression);
|
||||
}
|
||||
|
||||
function needsParenthesisForPropertyAccess(node: Expression) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
// This list is not exhaustive and only includes those cases that are relevant
|
||||
// to the check in emitArrayLiteral. More cases can be added as needed.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function emitArrayLiteral(node: ArrayLiteralExpression) {
|
||||
var elements = node.elements;
|
||||
var length = elements.length;
|
||||
if (length === 0) {
|
||||
write("[]");
|
||||
return;
|
||||
}
|
||||
if (compilerOptions.target >= ScriptTarget.ES6) {
|
||||
write("[");
|
||||
emitCommaList(node.elements);
|
||||
emitTrailingCommaIfPresent(node.elements);
|
||||
emitList(elements, 0, elements.length, /*multiLine*/(node.flags & NodeFlags.MultiLine) !== 0,
|
||||
/*trailingComma*/ elements.hasTrailingComma);
|
||||
write("]");
|
||||
return;
|
||||
}
|
||||
var pos = 0;
|
||||
var group = 0;
|
||||
while (pos < length) {
|
||||
// Emit using the pattern <group0>.concat(<group1>, <group2>, ...)
|
||||
if (group === 1) {
|
||||
write(".concat(");
|
||||
}
|
||||
else if (group > 1) {
|
||||
write(", ");
|
||||
}
|
||||
var e = elements[pos];
|
||||
if (e.kind === SyntaxKind.SpreadElementExpression) {
|
||||
e = (<SpreadElementExpression>e).expression;
|
||||
emitParenthesized(e, /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccess(e));
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
var i = pos;
|
||||
while (i < length && elements[i].kind !== SyntaxKind.SpreadElementExpression) {
|
||||
i++;
|
||||
}
|
||||
write("[");
|
||||
emitList(elements, pos, i - pos, /*multiLine*/ (node.flags & NodeFlags.MultiLine) !== 0,
|
||||
/*trailingComma*/ elements.hasTrailingComma);
|
||||
write("]");
|
||||
pos = i;
|
||||
}
|
||||
group++;
|
||||
}
|
||||
if (group > 1) {
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
|
||||
function emitObjectLiteral(node: ObjectLiteralExpression) {
|
||||
if (!node.properties.length) {
|
||||
write("{}");
|
||||
}
|
||||
else if (node.flags & NodeFlags.MultiLine) {
|
||||
write("{");
|
||||
increaseIndent();
|
||||
emitMultiLineList(node.properties);
|
||||
if (compilerOptions.target >= ScriptTarget.ES5) {
|
||||
emitTrailingCommaIfPresent(node.properties);
|
||||
write("{");
|
||||
var properties = node.properties;
|
||||
if (properties.length) {
|
||||
var multiLine = (node.flags & NodeFlags.MultiLine) !== 0;
|
||||
if (!multiLine) {
|
||||
write(" ");
|
||||
}
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("}");
|
||||
}
|
||||
else {
|
||||
write("{ ");
|
||||
emitCommaList(node.properties);
|
||||
if (compilerOptions.target >= ScriptTarget.ES5) {
|
||||
emitTrailingCommaIfPresent(node.properties);
|
||||
emitList(properties, 0, properties.length, /*multiLine*/ multiLine,
|
||||
/*trailingComma*/ properties.hasTrailingComma && compilerOptions.target >= ScriptTarget.ES5);
|
||||
if (!multiLine) {
|
||||
write(" ");
|
||||
}
|
||||
write(" }");
|
||||
}
|
||||
write("}");
|
||||
}
|
||||
|
||||
function emitComputedPropertyName(node: ComputedPropertyName) {
|
||||
@@ -2502,7 +2575,8 @@ module ts {
|
||||
|
||||
|
||||
function emitBinaryExpression(node: BinaryExpression) {
|
||||
if (node.operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
if (compilerOptions.target < ScriptTarget.ES6 && node.operator === SyntaxKind.EqualsToken &&
|
||||
(node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
emitDestructuring(node);
|
||||
}
|
||||
else {
|
||||
@@ -2554,11 +2628,8 @@ module ts {
|
||||
}
|
||||
|
||||
function emitExpressionStatement(node: ExpressionStatement) {
|
||||
var isArrowExpression = node.expression.kind === SyntaxKind.ArrowFunction;
|
||||
emitLeadingComments(node);
|
||||
if (isArrowExpression) write("(");
|
||||
emit(node.expression);
|
||||
if (isArrowExpression) write(")");
|
||||
emitParenthesized(node.expression, /*parenthesized*/ node.expression.kind === SyntaxKind.ArrowFunction);
|
||||
write(";");
|
||||
emitTrailingComments(node);
|
||||
}
|
||||
@@ -2899,7 +2970,16 @@ module ts {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var e = elements[i];
|
||||
if (e.kind !== SyntaxKind.OmittedExpression) {
|
||||
emitDestructuringAssignment(e, createElementAccess(value, createNumericLiteral(i)));
|
||||
if (e.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
emitDestructuringAssignment(e, createElementAccess(value, createNumericLiteral(i)));
|
||||
}
|
||||
else {
|
||||
if (i === elements.length - 1) {
|
||||
value = ensureIdentifier(value);
|
||||
emitAssignment(<Identifier>(<SpreadElementExpression>e).expression, value);
|
||||
write(".slice(" + i + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2965,8 +3045,17 @@ module ts {
|
||||
emitBindingElement(element, createPropertyAccess(value, propName));
|
||||
}
|
||||
else if (element.kind !== SyntaxKind.OmittedExpression) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccess(value, createNumericLiteral(i)));
|
||||
if (!element.dotDotDotToken) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccess(value, createNumericLiteral(i)));
|
||||
}
|
||||
else {
|
||||
if (i === elements.length - 1) {
|
||||
value = ensureIdentifier(value);
|
||||
emitAssignment(<Identifier>element.name, value);
|
||||
write(".slice(" + i + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2979,7 +3068,13 @@ module ts {
|
||||
function emitVariableDeclaration(node: VariableDeclaration) {
|
||||
emitLeadingComments(node);
|
||||
if (isBindingPattern(node.name)) {
|
||||
emitDestructuring(node);
|
||||
if (compilerOptions.target < ScriptTarget.ES6) {
|
||||
emitDestructuring(node);
|
||||
}
|
||||
else {
|
||||
emit(node.name);
|
||||
emitOptional(" = ", node.initializer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitModuleMemberName(node);
|
||||
@@ -3008,57 +3103,61 @@ module ts {
|
||||
|
||||
function emitParameter(node: ParameterDeclaration) {
|
||||
emitLeadingComments(node);
|
||||
if (isBindingPattern(node.name)) {
|
||||
var name = createTempVariable(node);
|
||||
if (!tempParameters) {
|
||||
tempParameters = [];
|
||||
if (compilerOptions.target < ScriptTarget.ES6) {
|
||||
if (isBindingPattern(node.name)) {
|
||||
var name = createTempVariable(node);
|
||||
if (!tempParameters) {
|
||||
tempParameters = [];
|
||||
}
|
||||
tempParameters.push(name);
|
||||
emit(name);
|
||||
}
|
||||
else {
|
||||
emit(node.name);
|
||||
}
|
||||
tempParameters.push(name);
|
||||
emit(name);
|
||||
}
|
||||
else {
|
||||
if (node.dotDotDotToken) {
|
||||
write("...");
|
||||
}
|
||||
emit(node.name);
|
||||
emitOptional(" = ", node.initializer);
|
||||
}
|
||||
// TODO(andersh): Enable ES6 code generation below
|
||||
//if (node.propertyName) {
|
||||
// emit(node.propertyName);
|
||||
// write(": ");
|
||||
//}
|
||||
//emit(node.name);
|
||||
//emitOptional(" = ", node.initializer);
|
||||
emitTrailingComments(node);
|
||||
}
|
||||
|
||||
function emitDefaultValueAssignments(node: FunctionLikeDeclaration) {
|
||||
var tempIndex = 0;
|
||||
forEach(node.parameters, p => {
|
||||
if (isBindingPattern(p.name)) {
|
||||
writeLine();
|
||||
write("var ");
|
||||
emitDestructuring(p, tempParameters[tempIndex]);
|
||||
write(";");
|
||||
tempIndex++;
|
||||
}
|
||||
else if (p.initializer) {
|
||||
writeLine();
|
||||
emitStart(p);
|
||||
write("if (");
|
||||
emitNode(p.name);
|
||||
write(" === void 0)");
|
||||
emitEnd(p);
|
||||
write(" { ");
|
||||
emitStart(p);
|
||||
emitNode(p.name);
|
||||
write(" = ");
|
||||
emitNode(p.initializer);
|
||||
emitEnd(p);
|
||||
write("; }");
|
||||
}
|
||||
});
|
||||
if (compilerOptions.target < ScriptTarget.ES6) {
|
||||
var tempIndex = 0;
|
||||
forEach(node.parameters, p => {
|
||||
if (isBindingPattern(p.name)) {
|
||||
writeLine();
|
||||
write("var ");
|
||||
emitDestructuring(p, tempParameters[tempIndex]);
|
||||
write(";");
|
||||
tempIndex++;
|
||||
}
|
||||
else if (p.initializer) {
|
||||
writeLine();
|
||||
emitStart(p);
|
||||
write("if (");
|
||||
emitNode(p.name);
|
||||
write(" === void 0)");
|
||||
emitEnd(p);
|
||||
write(" { ");
|
||||
emitStart(p);
|
||||
emitNode(p.name);
|
||||
write(" = ");
|
||||
emitNode(p.initializer);
|
||||
emitEnd(p);
|
||||
write("; }");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function emitRestParameter(node: FunctionLikeDeclaration) {
|
||||
if (hasRestParameters(node)) {
|
||||
if (compilerOptions.target < ScriptTarget.ES6 && hasRestParameters(node)) {
|
||||
var restIndex = node.parameters.length - 1;
|
||||
var restParam = node.parameters[restIndex];
|
||||
var tempName = createTempVariable(node, /*forLoopVariable*/ true).text;
|
||||
@@ -3136,7 +3235,9 @@ module ts {
|
||||
increaseIndent();
|
||||
write("(");
|
||||
if (node) {
|
||||
emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
|
||||
var parameters = node.parameters;
|
||||
var omitCount = compilerOptions.target < ScriptTarget.ES6 && hasRestParameters(node) ? 1 : 0;
|
||||
emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false);
|
||||
}
|
||||
write(")");
|
||||
decreaseIndent();
|
||||
@@ -3723,17 +3824,18 @@ module ts {
|
||||
increaseIndent();
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
var exportName = resolver.getExportAssignmentName(node);
|
||||
if (exportName) {
|
||||
writeLine();
|
||||
var exportAssignement = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignement);
|
||||
var exportAssignment = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignment);
|
||||
write("return ");
|
||||
emitStart(exportAssignement.exportName);
|
||||
emitStart(exportAssignment.exportName);
|
||||
write(exportName);
|
||||
emitEnd(exportAssignement.exportName);
|
||||
emitEnd(exportAssignment.exportName);
|
||||
write(";");
|
||||
emitEnd(exportAssignement);
|
||||
emitEnd(exportAssignment);
|
||||
}
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
@@ -3743,17 +3845,18 @@ module ts {
|
||||
function emitCommonJSModule(node: SourceFile, startIndex: number) {
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
var exportName = resolver.getExportAssignmentName(node);
|
||||
if (exportName) {
|
||||
writeLine();
|
||||
var exportAssignement = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignement);
|
||||
var exportAssignment = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignment);
|
||||
write("module.exports = ");
|
||||
emitStart(exportAssignement.exportName);
|
||||
emitStart(exportAssignment.exportName);
|
||||
write(exportName);
|
||||
emitEnd(exportAssignement.exportName);
|
||||
emitEnd(exportAssignment.exportName);
|
||||
write(";");
|
||||
emitEnd(exportAssignement);
|
||||
emitEnd(exportAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3809,6 +3912,7 @@ module ts {
|
||||
else {
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
}
|
||||
|
||||
emitLeadingComments(node.endOfFileToken);
|
||||
@@ -3861,6 +3965,8 @@ module ts {
|
||||
return emitObjectBindingPattern(<BindingPattern>node);
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return emitArrayBindingPattern(<BindingPattern>node);
|
||||
case SyntaxKind.BindingElement:
|
||||
return emitBindingElement(<BindingElement>node);
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return emitArrayLiteral(<ArrayLiteralExpression>node);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
@@ -3903,6 +4009,8 @@ module ts {
|
||||
return emitBinaryExpression(<BinaryExpression>node);
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return emitConditionalExpression(<ConditionalExpression>node);
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
return emitSpreadElementExpression(<SpreadElementExpression>node);
|
||||
case SyntaxKind.OmittedExpression:
|
||||
return;
|
||||
case SyntaxKind.Block:
|
||||
|
||||
@@ -151,6 +151,8 @@ module ts {
|
||||
return child((<ConditionalExpression>node).condition) ||
|
||||
child((<ConditionalExpression>node).whenTrue) ||
|
||||
child((<ConditionalExpression>node).whenFalse);
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
return child((<SpreadElementExpression>node).expression);
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.TryBlock:
|
||||
case SyntaxKind.FinallyBlock:
|
||||
@@ -1005,13 +1007,13 @@ module ts {
|
||||
case ParsingContext.VariableDeclarations:
|
||||
return isIdentifierOrPattern();
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
return token === SyntaxKind.CommaToken || isIdentifierOrPattern();
|
||||
return token === SyntaxKind.CommaToken || token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern();
|
||||
case ParsingContext.TypeParameters:
|
||||
return isIdentifier();
|
||||
case ParsingContext.ArgumentExpressions:
|
||||
return token === SyntaxKind.CommaToken || isStartOfExpression();
|
||||
case ParsingContext.ArrayLiteralMembers:
|
||||
return token === SyntaxKind.CommaToken || isStartOfExpression();
|
||||
return token === SyntaxKind.CommaToken || token === SyntaxKind.DotDotDotToken || isStartOfExpression();
|
||||
case ParsingContext.Parameters:
|
||||
return isStartOfParameter();
|
||||
case ParsingContext.TypeArguments:
|
||||
@@ -2777,8 +2779,15 @@ module ts {
|
||||
: parseAssignmentExpressionOrHigher();
|
||||
}
|
||||
|
||||
function parseSpreadElement(): Expression {
|
||||
var node = <SpreadElementExpression>createNode(SyntaxKind.SpreadElementExpression);
|
||||
parseExpected(SyntaxKind.DotDotDotToken);
|
||||
node.expression = parseAssignmentExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseArrayLiteralElement(): Expression {
|
||||
return parseAssignmentExpressionOrOmittedExpression();
|
||||
return token === SyntaxKind.DotDotDotToken ? parseSpreadElement() : parseAssignmentExpressionOrOmittedExpression();
|
||||
}
|
||||
|
||||
function parseArgumentExpression(): Expression {
|
||||
@@ -3281,8 +3290,8 @@ module ts {
|
||||
if (token === SyntaxKind.CommaToken) {
|
||||
return <BindingElement>createNode(SyntaxKind.OmittedExpression);
|
||||
}
|
||||
|
||||
var node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
node.name = parseIdentifierOrPattern();
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
@@ -3290,7 +3299,6 @@ module ts {
|
||||
|
||||
function parseObjectBindingElement(): BindingElement {
|
||||
var node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
|
||||
// TODO(andersh): Handle computed properties
|
||||
var id = parsePropertyName();
|
||||
if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {
|
||||
@@ -3301,7 +3309,6 @@ module ts {
|
||||
node.propertyName = <Identifier>id;
|
||||
node.name = parseIdentifierOrPattern();
|
||||
}
|
||||
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -196,6 +196,7 @@ module ts {
|
||||
ConditionalExpression,
|
||||
TemplateExpression,
|
||||
YieldExpression,
|
||||
SpreadElementExpression,
|
||||
OmittedExpression,
|
||||
// Misc
|
||||
TemplateSpan,
|
||||
@@ -659,7 +660,11 @@ module ts {
|
||||
export interface ArrayLiteralExpression extends PrimaryExpression {
|
||||
elements: NodeArray<Expression>;
|
||||
}
|
||||
|
||||
|
||||
export interface SpreadElementExpression extends Expression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
// An ObjectLiteralExpression is the declaration node for an anonymous symbol.
|
||||
export interface ObjectLiteralExpression extends PrimaryExpression, Declaration {
|
||||
properties: NodeArray<ObjectLiteralElement>;
|
||||
|
||||
@@ -415,6 +415,7 @@ module ts {
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.TemplateExpression:
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.OmittedExpression:
|
||||
|
||||
@@ -133,7 +133,7 @@ module FourSlash {
|
||||
testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot]
|
||||
|
||||
function convertGlobalOptionsToCompilerOptions(globalOptions: { [idx: string]: string }): ts.CompilerOptions {
|
||||
var settings: ts.CompilerOptions = {};
|
||||
var settings: ts.CompilerOptions = { target: ts.ScriptTarget.ES5 };
|
||||
// Convert all property in globalOptions into ts.CompilationSettings
|
||||
for (var prop in globalOptions) {
|
||||
if (globalOptions.hasOwnProperty(prop)) {
|
||||
@@ -2590,4 +2590,4 @@ module FourSlash {
|
||||
fileName: fileName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
tests/baselines/reference/arrayLiteralSpread.js
Normal file
46
tests/baselines/reference/arrayLiteralSpread.js
Normal file
@@ -0,0 +1,46 @@
|
||||
//// [arrayLiteralSpread.ts]
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
var a1 = [...a];
|
||||
var a2 = [1, ...a];
|
||||
var a3 = [1, 2, ...a];
|
||||
var a4 = [...a, 1];
|
||||
var a5 = [...a, 1, 2];
|
||||
var a6 = [1, 2, ...a, 1, 2];
|
||||
var a7 = [1, ...a, 2, ...a];
|
||||
var a8 = [...a, ...a, ...a];
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
var b = ["hello", ...a, true];
|
||||
var b: (string | number | boolean)[];
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var a = [...[...[...[...[...[]]]]]];
|
||||
var b = [...[...[...[...[...[5]]]]]];
|
||||
}
|
||||
|
||||
|
||||
//// [arrayLiteralSpread.js]
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
var a1 = a;
|
||||
var a2 = [1].concat(a);
|
||||
var a3 = [1, 2].concat(a);
|
||||
var a4 = a.concat([1]);
|
||||
var a5 = a.concat([1, 2]);
|
||||
var a6 = [1, 2].concat(a, [1, 2]);
|
||||
var a7 = [1].concat(a, [2], a);
|
||||
var a8 = a.concat(a, a);
|
||||
}
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
var b = ["hello"].concat(a, [true]);
|
||||
var b;
|
||||
}
|
||||
function f2() {
|
||||
var a = [];
|
||||
var b = [5];
|
||||
}
|
||||
90
tests/baselines/reference/arrayLiteralSpread.types
Normal file
90
tests/baselines/reference/arrayLiteralSpread.types
Normal file
@@ -0,0 +1,90 @@
|
||||
=== tests/cases/conformance/es6/spread/arrayLiteralSpread.ts ===
|
||||
function f0() {
|
||||
>f0 : () => void
|
||||
|
||||
var a = [1, 2, 3];
|
||||
>a : number[]
|
||||
>[1, 2, 3] : number[]
|
||||
|
||||
var a1 = [...a];
|
||||
>a1 : number[]
|
||||
>[...a] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a2 = [1, ...a];
|
||||
>a2 : number[]
|
||||
>[1, ...a] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a3 = [1, 2, ...a];
|
||||
>a3 : number[]
|
||||
>[1, 2, ...a] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a4 = [...a, 1];
|
||||
>a4 : number[]
|
||||
>[...a, 1] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a5 = [...a, 1, 2];
|
||||
>a5 : number[]
|
||||
>[...a, 1, 2] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a6 = [1, 2, ...a, 1, 2];
|
||||
>a6 : number[]
|
||||
>[1, 2, ...a, 1, 2] : number[]
|
||||
>a : number[]
|
||||
|
||||
var a7 = [1, ...a, 2, ...a];
|
||||
>a7 : number[]
|
||||
>[1, ...a, 2, ...a] : number[]
|
||||
>a : number[]
|
||||
>a : number[]
|
||||
|
||||
var a8 = [...a, ...a, ...a];
|
||||
>a8 : number[]
|
||||
>[...a, ...a, ...a] : number[]
|
||||
>a : number[]
|
||||
>a : number[]
|
||||
>a : number[]
|
||||
}
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
var a = [1, 2, 3];
|
||||
>a : number[]
|
||||
>[1, 2, 3] : number[]
|
||||
|
||||
var b = ["hello", ...a, true];
|
||||
>b : (string | number | boolean)[]
|
||||
>["hello", ...a, true] : (string | number | boolean)[]
|
||||
>a : number[]
|
||||
|
||||
var b: (string | number | boolean)[];
|
||||
>b : (string | number | boolean)[]
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : () => void
|
||||
|
||||
var a = [...[...[...[...[...[]]]]]];
|
||||
>a : any[]
|
||||
>[...[...[...[...[...[]]]]]] : undefined[]
|
||||
>[...[...[...[...[]]]]] : undefined[]
|
||||
>[...[...[...[]]]] : undefined[]
|
||||
>[...[...[]]] : undefined[]
|
||||
>[...[]] : undefined[]
|
||||
>[] : undefined[]
|
||||
|
||||
var b = [...[...[...[...[...[5]]]]]];
|
||||
>b : number[]
|
||||
>[...[...[...[...[...[5]]]]]] : number[]
|
||||
>[...[...[...[...[5]]]]] : number[]
|
||||
>[...[...[...[5]]]] : number[]
|
||||
>[...[...[5]]] : number[]
|
||||
>[...[5]] : number[]
|
||||
>[5] : number[]
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ tests/cases/conformance/es6/destructuring/declarationsAndAssignments.ts(138,9):
|
||||
f17({ c: true });
|
||||
f17(f15());
|
||||
|
||||
function g4() {
|
||||
function f18() {
|
||||
var a: number;
|
||||
var b: string;
|
||||
var aa: number[];
|
||||
@@ -191,7 +191,7 @@ tests/cases/conformance/es6/destructuring/declarationsAndAssignments.ts(138,9):
|
||||
[a = 1, b = "abc"] = [2, "def"];
|
||||
}
|
||||
|
||||
function g5() {
|
||||
function f19() {
|
||||
var a, b;
|
||||
[a, b] = [1, 2];
|
||||
[a, b] = [b, a];
|
||||
@@ -199,4 +199,34 @@ tests/cases/conformance/es6/destructuring/declarationsAndAssignments.ts(138,9):
|
||||
[[a, b] = [1, 2]] = [[2, 3]];
|
||||
var x = ([a, b] = [1, 2]);
|
||||
}
|
||||
|
||||
function f20() {
|
||||
var a: number[];
|
||||
var x: number;
|
||||
var y: number;
|
||||
var z: number;
|
||||
var [...a] = [1, 2, 3];
|
||||
var [x, ...a] = [1, 2, 3];
|
||||
var [x, y, ...a] = [1, 2, 3];
|
||||
var [x, y, z, ...a] = [1, 2, 3];
|
||||
[...a] = [1, 2, 3];
|
||||
[x, ...a] = [1, 2, 3];
|
||||
[x, y, ...a] = [1, 2, 3];
|
||||
[x, y, z, ...a] = [1, 2, 3];
|
||||
}
|
||||
|
||||
function f21() {
|
||||
var a: (number | string | boolean)[];
|
||||
var x: number | string | boolean;
|
||||
var y: number | string | boolean;
|
||||
var z: number | string | boolean;
|
||||
var [...a] = [1, "hello", true];
|
||||
var [x, ...a] = [1, "hello", true];
|
||||
var [x, y, ...a] = [1, "hello", true];
|
||||
var [x, y, z, ...a] = [1, "hello", true];
|
||||
[...a] = [1, "hello", true];
|
||||
[x, ...a] = [1, "hello", true];
|
||||
[x, y, ...a] = [1, "hello", true];
|
||||
[x, y, z, ...a] = [1, "hello", true];
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ f17({ a: "hello" });
|
||||
f17({ c: true });
|
||||
f17(f15());
|
||||
|
||||
function g4() {
|
||||
function f18() {
|
||||
var a: number;
|
||||
var b: string;
|
||||
var aa: number[];
|
||||
@@ -140,7 +140,7 @@ function g4() {
|
||||
[a = 1, b = "abc"] = [2, "def"];
|
||||
}
|
||||
|
||||
function g5() {
|
||||
function f19() {
|
||||
var a, b;
|
||||
[a, b] = [1, 2];
|
||||
[a, b] = [b, a];
|
||||
@@ -148,6 +148,36 @@ function g5() {
|
||||
[[a, b] = [1, 2]] = [[2, 3]];
|
||||
var x = ([a, b] = [1, 2]);
|
||||
}
|
||||
|
||||
function f20() {
|
||||
var a: number[];
|
||||
var x: number;
|
||||
var y: number;
|
||||
var z: number;
|
||||
var [...a] = [1, 2, 3];
|
||||
var [x, ...a] = [1, 2, 3];
|
||||
var [x, y, ...a] = [1, 2, 3];
|
||||
var [x, y, z, ...a] = [1, 2, 3];
|
||||
[...a] = [1, 2, 3];
|
||||
[x, ...a] = [1, 2, 3];
|
||||
[x, y, ...a] = [1, 2, 3];
|
||||
[x, y, z, ...a] = [1, 2, 3];
|
||||
}
|
||||
|
||||
function f21() {
|
||||
var a: (number | string | boolean)[];
|
||||
var x: number | string | boolean;
|
||||
var y: number | string | boolean;
|
||||
var z: number | string | boolean;
|
||||
var [...a] = [1, "hello", true];
|
||||
var [x, ...a] = [1, "hello", true];
|
||||
var [x, y, ...a] = [1, "hello", true];
|
||||
var [x, y, z, ...a] = [1, "hello", true];
|
||||
[...a] = [1, "hello", true];
|
||||
[x, ...a] = [1, "hello", true];
|
||||
[x, y, ...a] = [1, "hello", true];
|
||||
[x, y, z, ...a] = [1, "hello", true];
|
||||
}
|
||||
|
||||
|
||||
//// [declarationsAndAssignments.js]
|
||||
@@ -266,7 +296,7 @@ f17({});
|
||||
f17({ a: "hello" });
|
||||
f17({ c: true });
|
||||
f17(f15());
|
||||
function g4() {
|
||||
function f18() {
|
||||
var a;
|
||||
var b;
|
||||
var aa;
|
||||
@@ -277,7 +307,7 @@ function g4() {
|
||||
_e = [2, "def"], _f = _e[0], a = _f === void 0 ? 1 : _f, _g = _e[1], b = _g === void 0 ? "abc" : _g;
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
}
|
||||
function g5() {
|
||||
function f19() {
|
||||
var a, b;
|
||||
_a = [1, 2], a = _a[0], b = _a[1];
|
||||
_b = [b, a], a = _b[0], b = _b[1];
|
||||
@@ -286,3 +316,33 @@ function g5() {
|
||||
var x = (_f = [1, 2], a = _f[0], b = _f[1], _f);
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
}
|
||||
function f20() {
|
||||
var a;
|
||||
var x;
|
||||
var y;
|
||||
var z;
|
||||
var _a = [1, 2, 3], a = _a.slice(0);
|
||||
var _b = [1, 2, 3], x = _b[0], a = _b.slice(1);
|
||||
var _c = [1, 2, 3], x = _c[0], y = _c[1], a = _c.slice(2);
|
||||
var _d = [1, 2, 3], x = _d[0], y = _d[1], z = _d[2], a = _d.slice(3);
|
||||
_e = [1, 2, 3], a = _e.slice(0);
|
||||
_f = [1, 2, 3], x = _f[0], a = _f.slice(1);
|
||||
_g = [1, 2, 3], x = _g[0], y = _g[1], a = _g.slice(2);
|
||||
_h = [1, 2, 3], x = _h[0], y = _h[1], z = _h[2], a = _h.slice(3);
|
||||
var _e, _f, _g, _h;
|
||||
}
|
||||
function f21() {
|
||||
var a;
|
||||
var x;
|
||||
var y;
|
||||
var z;
|
||||
var _a = [1, "hello", true], a = _a.slice(0);
|
||||
var _b = [1, "hello", true], x = _b[0], a = _b.slice(1);
|
||||
var _c = [1, "hello", true], x = _c[0], y = _c[1], a = _c.slice(2);
|
||||
var _d = [1, "hello", true], x = _d[0], y = _d[1], z = _d[2], a = _d.slice(3);
|
||||
_e = [1, "hello", true], a = _e.slice(0);
|
||||
_f = [1, "hello", true], x = _f[0], a = _f.slice(1);
|
||||
_g = [1, "hello", true], x = _g[0], y = _g[1], a = _g.slice(2);
|
||||
_h = [1, "hello", true], x = _h[0], y = _h[1], z = _h[2], a = _h.slice(3);
|
||||
var _e, _f, _g, _h;
|
||||
}
|
||||
|
||||
12
tests/baselines/reference/restElementMustBeLast.errors.txt
Normal file
12
tests/baselines/reference/restElementMustBeLast.errors.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts(1,9): error TS2462: A rest element must be last in an array destructuring pattern
|
||||
tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts(2,2): error TS2462: A rest element must be last in an array destructuring pattern
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts (2 errors) ====
|
||||
var [...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
~
|
||||
!!! error TS2462: A rest element must be last in an array destructuring pattern
|
||||
[...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
~~~~
|
||||
!!! error TS2462: A rest element must be last in an array destructuring pattern
|
||||
|
||||
9
tests/baselines/reference/restElementMustBeLast.js
Normal file
9
tests/baselines/reference/restElementMustBeLast.js
Normal file
@@ -0,0 +1,9 @@
|
||||
//// [restElementMustBeLast.ts]
|
||||
var [...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
[...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
|
||||
|
||||
//// [restElementMustBeLast.js]
|
||||
var _a = [1, 2, 3], x = _a[1]; // Error, rest must be last element
|
||||
_b = [1, 2, 3], x = _b[1]; // Error, rest must be last element
|
||||
var _b;
|
||||
@@ -0,0 +1,9 @@
|
||||
tests/cases/conformance/es6/destructuring/restElementWithInitializer1.ts(2,11): error TS1185: A rest element cannot have an initializer.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/restElementWithInitializer1.ts (1 errors) ====
|
||||
var a: number[];
|
||||
var [...x = a] = a; // Error, rest element cannot have initializer
|
||||
~
|
||||
!!! error TS1185: A rest element cannot have an initializer.
|
||||
|
||||
8
tests/baselines/reference/restElementWithInitializer1.js
Normal file
8
tests/baselines/reference/restElementWithInitializer1.js
Normal file
@@ -0,0 +1,8 @@
|
||||
//// [restElementWithInitializer1.ts]
|
||||
var a: number[];
|
||||
var [...x = a] = a; // Error, rest element cannot have initializer
|
||||
|
||||
|
||||
//// [restElementWithInitializer1.js]
|
||||
var a;
|
||||
var x = a.slice(0); // Error, rest element cannot have initializer
|
||||
@@ -0,0 +1,10 @@
|
||||
tests/cases/conformance/es6/destructuring/restElementWithInitializer2.ts(3,5): error TS2364: Invalid left-hand side of assignment expression.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/restElementWithInitializer2.ts (1 errors) ====
|
||||
var a: number[];
|
||||
var x: number[];
|
||||
[...x = a] = a; // Error, rest element cannot have initializer
|
||||
~~~~~
|
||||
!!! error TS2364: Invalid left-hand side of assignment expression.
|
||||
|
||||
10
tests/baselines/reference/restElementWithInitializer2.js
Normal file
10
tests/baselines/reference/restElementWithInitializer2.js
Normal file
@@ -0,0 +1,10 @@
|
||||
//// [restElementWithInitializer2.ts]
|
||||
var a: number[];
|
||||
var x: number[];
|
||||
[...x = a] = a; // Error, rest element cannot have initializer
|
||||
|
||||
|
||||
//// [restElementWithInitializer2.js]
|
||||
var a;
|
||||
var x;
|
||||
x = a = a.slice(0); // Error, rest element cannot have initializer
|
||||
@@ -23,11 +23,7 @@ var z = foo `${1}${2}${3}`; // any (with error)
|
||||
|
||||
|
||||
//// [taggedTemplateStringsWithOverloadResolution1_ES6.js]
|
||||
function foo() {
|
||||
var stuff = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
stuff[_i - 0] = arguments[_i];
|
||||
}
|
||||
function foo(...stuff) {
|
||||
return undefined;
|
||||
}
|
||||
var a = foo([]); // number
|
||||
|
||||
@@ -18,20 +18,12 @@ var c = foo2 `${1}`; // number
|
||||
var d = foo2([], 1); // number
|
||||
|
||||
//// [taggedTemplateStringsWithOverloadResolution2_ES6.js]
|
||||
function foo1() {
|
||||
var stuff = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
stuff[_i - 0] = arguments[_i];
|
||||
}
|
||||
function foo1(...stuff) {
|
||||
return undefined;
|
||||
}
|
||||
var a = foo1 `${1}`; // string
|
||||
var b = foo1([], 1); // number
|
||||
function foo2() {
|
||||
var stuff = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
stuff[_i - 0] = arguments[_i];
|
||||
}
|
||||
function foo2(...stuff) {
|
||||
return undefined;
|
||||
}
|
||||
var c = foo2 `${1}`; // number
|
||||
|
||||
@@ -128,7 +128,7 @@ f17({ a: "hello" });
|
||||
f17({ c: true });
|
||||
f17(f15());
|
||||
|
||||
function g4() {
|
||||
function f18() {
|
||||
var a: number;
|
||||
var b: string;
|
||||
var aa: number[];
|
||||
@@ -139,7 +139,7 @@ function g4() {
|
||||
[a = 1, b = "abc"] = [2, "def"];
|
||||
}
|
||||
|
||||
function g5() {
|
||||
function f19() {
|
||||
var a, b;
|
||||
[a, b] = [1, 2];
|
||||
[a, b] = [b, a];
|
||||
@@ -147,3 +147,33 @@ function g5() {
|
||||
[[a, b] = [1, 2]] = [[2, 3]];
|
||||
var x = ([a, b] = [1, 2]);
|
||||
}
|
||||
|
||||
function f20() {
|
||||
var a: number[];
|
||||
var x: number;
|
||||
var y: number;
|
||||
var z: number;
|
||||
var [...a] = [1, 2, 3];
|
||||
var [x, ...a] = [1, 2, 3];
|
||||
var [x, y, ...a] = [1, 2, 3];
|
||||
var [x, y, z, ...a] = [1, 2, 3];
|
||||
[...a] = [1, 2, 3];
|
||||
[x, ...a] = [1, 2, 3];
|
||||
[x, y, ...a] = [1, 2, 3];
|
||||
[x, y, z, ...a] = [1, 2, 3];
|
||||
}
|
||||
|
||||
function f21() {
|
||||
var a: (number | string | boolean)[];
|
||||
var x: number | string | boolean;
|
||||
var y: number | string | boolean;
|
||||
var z: number | string | boolean;
|
||||
var [...a] = [1, "hello", true];
|
||||
var [x, ...a] = [1, "hello", true];
|
||||
var [x, y, ...a] = [1, "hello", true];
|
||||
var [x, y, z, ...a] = [1, "hello", true];
|
||||
[...a] = [1, "hello", true];
|
||||
[x, ...a] = [1, "hello", true];
|
||||
[x, y, ...a] = [1, "hello", true];
|
||||
[x, y, z, ...a] = [1, "hello", true];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
var [...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
[...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
@@ -0,0 +1,2 @@
|
||||
var a: number[];
|
||||
var [...x = a] = a; // Error, rest element cannot have initializer
|
||||
@@ -0,0 +1,3 @@
|
||||
var a: number[];
|
||||
var x: number[];
|
||||
[...x = a] = a; // Error, rest element cannot have initializer
|
||||
22
tests/cases/conformance/es6/spread/arrayLiteralSpread.ts
Normal file
22
tests/cases/conformance/es6/spread/arrayLiteralSpread.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
var a1 = [...a];
|
||||
var a2 = [1, ...a];
|
||||
var a3 = [1, 2, ...a];
|
||||
var a4 = [...a, 1];
|
||||
var a5 = [...a, 1, 2];
|
||||
var a6 = [1, 2, ...a, 1, 2];
|
||||
var a7 = [1, ...a, 2, ...a];
|
||||
var a8 = [...a, ...a, ...a];
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
var b = ["hello", ...a, true];
|
||||
var b: (string | number | boolean)[];
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var a = [...[...[...[...[...[]]]]]];
|
||||
var b = [...[...[...[...[...[5]]]]]];
|
||||
}
|
||||
Reference in New Issue
Block a user