mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Support parentheses and comma operator with evolving arrays
This commit is contained in:
parent
89826a52ad
commit
e6b588a956
@ -760,7 +760,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createFlowArrayMutation(antecedent: FlowNode, node: Expression): FlowNode {
|
||||
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowArrayMutation>{
|
||||
flags: FlowFlags.ArrayMutation,
|
||||
@ -1151,8 +1151,8 @@ namespace ts {
|
||||
bindAssignmentTargetFlow(node.left);
|
||||
if (node.left.kind === SyntaxKind.ElementAccessExpression) {
|
||||
const elementAccess = <ElementAccessExpression>node.left;
|
||||
if (isNarrowableReference(elementAccess.expression)) {
|
||||
currentFlow = createFlowArrayMutation(currentFlow, elementAccess.expression);
|
||||
if (isNarrowableOperand(elementAccess.expression)) {
|
||||
currentFlow = createFlowArrayMutation(currentFlow, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1217,8 +1217,8 @@ namespace ts {
|
||||
}
|
||||
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
const propertyAccess = <PropertyAccessExpression>node.expression;
|
||||
if (isNarrowableReference(propertyAccess.expression) && propertyAccess.name.text === "push") {
|
||||
currentFlow = createFlowArrayMutation(currentFlow, propertyAccess.expression);
|
||||
if (isNarrowableOperand(propertyAccess.expression) && propertyAccess.name.text === "push") {
|
||||
currentFlow = createFlowArrayMutation(currentFlow, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8424,6 +8424,14 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function getReferenceParent(node: Node): Node {
|
||||
const parent = node.parent;
|
||||
return parent.kind === SyntaxKind.ParenthesizedExpression ||
|
||||
parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken && (<BinaryExpression>parent).left === node ||
|
||||
parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.CommaToken && (<BinaryExpression>parent).right === node ?
|
||||
getReferenceParent(parent) : parent;
|
||||
}
|
||||
|
||||
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
|
||||
if (clause.kind === SyntaxKind.CaseClause) {
|
||||
const caseType = getRegularTypeOfLiteralType(checkExpression((<CaseClause>clause).expression));
|
||||
@ -8556,15 +8564,16 @@ namespace ts {
|
||||
|
||||
// Return true if the given node is 'x' in an 'x.push(value)' operation.
|
||||
function isPushCallTarget(node: Node) {
|
||||
return node.parent.kind === SyntaxKind.PropertyAccessExpression &&
|
||||
(<PropertyAccessExpression>node.parent).name.text === "push" &&
|
||||
node.parent.parent.kind === SyntaxKind.CallExpression;
|
||||
const parent = getReferenceParent(node);
|
||||
return parent.kind === SyntaxKind.PropertyAccessExpression &&
|
||||
(<PropertyAccessExpression>parent).name.text === "push" &&
|
||||
parent.parent.kind === SyntaxKind.CallExpression;
|
||||
}
|
||||
|
||||
// Return true if the given node is 'x' in an 'x[n] = value' operation, where 'n' is an
|
||||
// expression of type any, undefined, or a number-like type.
|
||||
function isElementAssignmentTarget(node: Node) {
|
||||
const parent = node.parent;
|
||||
const parent = getReferenceParent(node);
|
||||
return parent.kind === SyntaxKind.ElementAccessExpression &&
|
||||
(<ElementAccessExpression>parent).expression === node &&
|
||||
parent.parent.kind === SyntaxKind.BinaryExpression &&
|
||||
@ -8696,19 +8705,24 @@ namespace ts {
|
||||
|
||||
function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType {
|
||||
const node = flow.node;
|
||||
if (isMatchingReference(reference, node)) {
|
||||
const expr = node.kind === SyntaxKind.CallExpression ?
|
||||
(<PropertyAccessExpression>(<CallExpression>node).expression).expression :
|
||||
(<ElementAccessExpression>(<BinaryExpression>node).left).expression;
|
||||
if (isMatchingReference(reference, getReferenceCandidate(expr))) {
|
||||
const flowType = getTypeAtFlowNode(flow.antecedent);
|
||||
const type = getTypeFromFlowType(flowType);
|
||||
if (isEvolvingArrayType(type)) {
|
||||
const parent = node.parent;
|
||||
let evolvedType = <AnonymousType>type;
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
for (const arg of (<CallExpression>parent.parent).arguments) {
|
||||
if (node.kind === SyntaxKind.CallExpression) {
|
||||
for (const arg of (<CallExpression>node).arguments) {
|
||||
evolvedType = addEvolvingArrayElementType(evolvedType, arg);
|
||||
}
|
||||
}
|
||||
else if (isTypeAnyOrAllConstituentTypesHaveKind(checkExpression((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike)) {
|
||||
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>parent.parent).right);
|
||||
else {
|
||||
const indexType = checkExpression((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
|
||||
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) {
|
||||
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>node).right);
|
||||
}
|
||||
}
|
||||
return evolvedType === type ? flowType : createFlowType(evolvedType, isIncomplete(flowType));
|
||||
}
|
||||
|
||||
@ -1955,7 +1955,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'.
|
||||
export interface FlowArrayMutation extends FlowNode {
|
||||
node: Expression;
|
||||
node: CallExpression | BinaryExpression;
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user