Support 'unshift' and fix typo

This commit is contained in:
Anders Hejlsberg 2016-10-13 09:43:55 -07:00
parent 38278ee078
commit 1dedca73d1
4 changed files with 16 additions and 10 deletions

View File

@ -1217,7 +1217,7 @@ namespace ts {
}
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
const propertyAccess = <PropertyAccessExpression>node.expression;
if (isNarrowableOperand(propertyAccess.expression) && propertyAccess.name.text === "push") {
if (isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) {
currentFlow = createFlowArrayMutation(currentFlow, node);
}
}

View File

@ -8405,8 +8405,10 @@ namespace ts {
}
function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) {
return node.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>node).initializer && isEmptyArrayLiteral((<VariableDeclaration>node).initializer) ||
node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression && isEmptyArrayLiteral((<BinaryExpression>node.parent).right);
return node.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>node).initializer &&
isEmptyArrayLiteral((<VariableDeclaration>node).initializer) ||
node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression &&
isEmptyArrayLiteral((<BinaryExpression>node.parent).right);
}
function getReferenceCandidate(node: Expression): Expression {
@ -8562,12 +8564,12 @@ namespace ts {
getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction);
}
// Return true if the given node is 'x' in an 'x.push(value)' operation.
function isPushCallTarget(node: Node) {
// Return true if the given node is 'x' in an 'x.push(value)' or 'x.unshift(value)' operation.
function isPushOrUnshiftCallTarget(node: Node) {
const parent = getReferenceRoot(node).parent;
return parent.kind === SyntaxKind.PropertyAccessExpression &&
(<PropertyAccessExpression>parent).name.text === "push" &&
parent.parent.kind === SyntaxKind.CallExpression;
parent.parent.kind === SyntaxKind.CallExpression &&
isPushOrUnshiftIdentifier((<PropertyAccessExpression>parent).name);
}
// Return true if the given node is 'x' in an 'x[n] = value' operation, where 'n' is an
@ -8596,9 +8598,9 @@ namespace ts {
const evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode));
visitedFlowCount = visitedFlowStart;
// When the reference is 'x' in an 'x.push(value)' or 'x[n] = value' operation, we give type
// 'any[]' to 'x' instead of using the type determed by control flow analysis such that new
// 'any[]' to 'x' instead of using the type determined by control flow analysis such that new
// element types are not considered errors.
const isEvolvingArrayInferenceTarget = isEvolvingArrayType(evolvedType) && (isPushCallTarget(reference) || isElementAssignmentTarget(reference));
const isEvolvingArrayInferenceTarget = isEvolvingArrayType(evolvedType) && (isPushOrUnshiftCallTarget(reference) || isElementAssignmentTarget(reference));
const resultType = isEvolvingArrayInferenceTarget ? anyArrayType : finalizeEvolvingArrayType(evolvedType);
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
return declaredType;

View File

@ -1953,7 +1953,7 @@ namespace ts {
}
// FlowArrayMutation represents a node potentially mutates an array, i.e. an
// operation of the form 'x.push(value)' or 'x[n] = value'.
// operation of the form 'x.push(value)', 'x.unshift(value)' or 'x[n] = value'.
export interface FlowArrayMutation extends FlowNode {
node: CallExpression | BinaryExpression;
antecedent: FlowNode;

View File

@ -1895,6 +1895,10 @@ namespace ts {
return node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "Symbol";
}
export function isPushOrUnshiftIdentifier(node: Identifier) {
return node.text === "push" || node.text === "unshift";
}
export function isModifierKind(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.AbstractKeyword: