Merge pull request #8566 from Microsoft/controlFlowDeleteOperator

Include delete operator in control flow analysis
This commit is contained in:
Anders Hejlsberg
2016-05-11 20:52:15 -07:00
6 changed files with 215 additions and 0 deletions

View File

@@ -580,6 +580,9 @@ namespace ts {
case SyntaxKind.BinaryExpression:
bindBinaryExpressionFlow(<BinaryExpression>node);
break;
case SyntaxKind.DeleteExpression:
bindDeleteExpressionFlow(<DeleteExpression>node);
break;
case SyntaxKind.ConditionalExpression:
bindConditionalExpressionFlow(<ConditionalExpression>node);
break;
@@ -1055,6 +1058,13 @@ namespace ts {
}
}
function bindDeleteExpressionFlow(node: DeleteExpression) {
forEachChild(node, bind);
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
bindAssignmentTargetFlow(node.expression);
}
}
function bindConditionalExpressionFlow(node: ConditionalExpression) {
const trueLabel = createBranchLabel();
const falseLabel = createBranchLabel();

View File

@@ -7563,6 +7563,8 @@ namespace ts {
return checkRightHandSideOfForOf((<ForOfStatement>parent).expression) || unknownType;
case SyntaxKind.BinaryExpression:
return getAssignedTypeOfBinaryExpression(<BinaryExpression>parent);
case SyntaxKind.DeleteExpression:
return undefinedType;
case SyntaxKind.ArrayLiteralExpression:
return getAssignedTypeOfArrayLiteralElement(<ArrayLiteralExpression>parent, node);
case SyntaxKind.SpreadElementExpression:

View File

@@ -0,0 +1,36 @@
//// [controlFlowDeleteOperator.ts]
function f() {
let x: { a?: number | string, b: number | string } = { b: 1 };
x.a;
x.b;
x.a = 1;
x.b = 1;
x.a;
x.b;
delete x.a;
delete x.b;
x.a;
x.b;
x;
delete x; // No effect
x;
}
//// [controlFlowDeleteOperator.js]
function f() {
var x = { b: 1 };
x.a;
x.b;
x.a = 1;
x.b = 1;
x.a;
x.b;
delete x.a;
delete x.b;
x.a;
x.b;
x;
delete x; // No effect
x;
}

View File

@@ -0,0 +1,70 @@
=== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts ===
function f() {
>f : Symbol(f, Decl(controlFlowDeleteOperator.ts, 0, 0))
let x: { a?: number | string, b: number | string } = { b: 1 };
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 58))
x.a;
>x.a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
x.b;
>x.b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
x.a = 1;
>x.a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
x.b = 1;
>x.b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
x.a;
>x.a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
x.b;
>x.b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
delete x.a;
>x.a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
delete x.b;
>x.b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
x.a;
>x.a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>a : Symbol(a, Decl(controlFlowDeleteOperator.ts, 2, 12))
x.b;
>x.b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
>b : Symbol(b, Decl(controlFlowDeleteOperator.ts, 2, 33))
x;
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
delete x; // No effect
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
x;
>x : Symbol(x, Decl(controlFlowDeleteOperator.ts, 2, 7))
}

View File

@@ -0,0 +1,79 @@
=== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts ===
function f() {
>f : () => void
let x: { a?: number | string, b: number | string } = { b: 1 };
>x : { a?: number | string | undefined; b: number | string; }
>a : number | string | undefined
>b : number | string
>{ b: 1 } : { b: number; }
>b : number
>1 : number
x.a;
>x.a : number | string | undefined
>x : { a?: number | string | undefined; b: number | string; }
>a : number | string | undefined
x.b;
>x.b : number | string
>x : { a?: number | string | undefined; b: number | string; }
>b : number | string
x.a = 1;
>x.a = 1 : number
>x.a : number | string | undefined
>x : { a?: number | string | undefined; b: number | string; }
>a : number | string | undefined
>1 : number
x.b = 1;
>x.b = 1 : number
>x.b : number | string
>x : { a?: number | string | undefined; b: number | string; }
>b : number | string
>1 : number
x.a;
>x.a : number
>x : { a?: number | string | undefined; b: number | string; }
>a : number
x.b;
>x.b : number
>x : { a?: number | string | undefined; b: number | string; }
>b : number
delete x.a;
>delete x.a : boolean
>x.a : number
>x : { a?: number | string | undefined; b: number | string; }
>a : number
delete x.b;
>delete x.b : boolean
>x.b : number
>x : { a?: number | string | undefined; b: number | string; }
>b : number
x.a;
>x.a : undefined
>x : { a?: number | string | undefined; b: number | string; }
>a : undefined
x.b;
>x.b : number | string
>x : { a?: number | string | undefined; b: number | string; }
>b : number | string
x;
>x : { a?: number | string | undefined; b: number | string; }
delete x; // No effect
>delete x : boolean
>x : { a?: number | string | undefined; b: number | string; }
x;
>x : { a?: number | string | undefined; b: number | string; }
}

View File

@@ -0,0 +1,18 @@
// @strictNullChecks: true
function f() {
let x: { a?: number | string, b: number | string } = { b: 1 };
x.a;
x.b;
x.a = 1;
x.b = 1;
x.a;
x.b;
delete x.a;
delete x.b;
x.a;
x.b;
x;
delete x; // No effect
x;
}