Bind RHS of comma expressions too (#47049)

This commit is contained in:
Jake Bailey 2022-01-18 11:46:09 -08:00 committed by GitHub
parent 16e96f62d7
commit e2c00331d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 163 additions and 9 deletions

View File

@ -1365,7 +1365,7 @@ namespace ts {
}
function maybeBindExpressionFlowIfCall(node: Expression) {
// A top level or LHS of comma expression call expression with a dotted function name and at least one argument
// A top level or comma expression call expression with a dotted function name and at least one argument
// is potentially an assertion and is therefore included in the control flow.
if (node.kind === SyntaxKind.CallExpression) {
const call = node as CallExpression;
@ -1550,24 +1550,29 @@ namespace ts {
return state;
}
function onLeft(left: Expression, state: WorkArea, _node: BinaryExpression) {
function onLeft(left: Expression, state: WorkArea, node: BinaryExpression) {
if (!state.skip) {
return maybeBind(left);
const maybeBound = maybeBind(left);
if (node.operatorToken.kind === SyntaxKind.CommaToken) {
maybeBindExpressionFlowIfCall(left);
}
return maybeBound;
}
}
function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, node: BinaryExpression) {
function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, _node: BinaryExpression) {
if (!state.skip) {
if (operatorToken.kind === SyntaxKind.CommaToken) {
maybeBindExpressionFlowIfCall(node.left);
}
bind(operatorToken);
}
}
function onRight(right: Expression, state: WorkArea, _node: BinaryExpression) {
function onRight(right: Expression, state: WorkArea, node: BinaryExpression) {
if (!state.skip) {
return maybeBind(right);
const maybeBound = maybeBind(right);
if (node.operatorToken.kind === SyntaxKind.CommaToken) {
maybeBindExpressionFlowIfCall(right);
}
return maybeBound;
}
}

View File

@ -0,0 +1,30 @@
//// [controlFlowCommaExpressionAssertionMultiple.ts]
function Narrow<T>(value: any): asserts value is T {}
function func(foo: any, bar: any) {
Narrow<number>(foo), Narrow<string>(bar);
foo;
bar;
}
function func2(foo: any, bar: any, baz: any) {
Narrow<number>(foo), Narrow<string>(bar), Narrow<boolean>(baz);
foo;
bar;
baz;
}
//// [controlFlowCommaExpressionAssertionMultiple.js]
function Narrow(value) { }
function func(foo, bar) {
Narrow(foo), Narrow(bar);
foo;
bar;
}
function func2(foo, bar, baz) {
Narrow(foo), Narrow(bar), Narrow(baz);
foo;
bar;
baz;
}

View File

@ -0,0 +1,50 @@
=== tests/cases/compiler/controlFlowCommaExpressionAssertionMultiple.ts ===
function Narrow<T>(value: any): asserts value is T {}
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>T : Symbol(T, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 16))
>value : Symbol(value, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 19))
>value : Symbol(value, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 19))
>T : Symbol(T, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 16))
function func(foo: any, bar: any) {
>func : Symbol(func, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 53))
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 14))
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 23))
Narrow<number>(foo), Narrow<string>(bar);
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 14))
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 23))
foo;
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 14))
bar;
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 2, 23))
}
function func2(foo: any, bar: any, baz: any) {
>func2 : Symbol(func2, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 6, 1))
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 15))
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 24))
>baz : Symbol(baz, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 34))
Narrow<number>(foo), Narrow<string>(bar), Narrow<boolean>(baz);
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 15))
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 24))
>Narrow : Symbol(Narrow, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 0, 0))
>baz : Symbol(baz, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 34))
foo;
>foo : Symbol(foo, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 15))
bar;
>bar : Symbol(bar, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 24))
baz;
>baz : Symbol(baz, Decl(controlFlowCommaExpressionAssertionMultiple.ts, 8, 34))
}

View File

@ -0,0 +1,55 @@
=== tests/cases/compiler/controlFlowCommaExpressionAssertionMultiple.ts ===
function Narrow<T>(value: any): asserts value is T {}
>Narrow : <T>(value: any) => asserts value is T
>value : any
function func(foo: any, bar: any) {
>func : (foo: any, bar: any) => void
>foo : any
>bar : any
Narrow<number>(foo), Narrow<string>(bar);
>Narrow<number>(foo), Narrow<string>(bar) : void
>Narrow<number>(foo) : void
>Narrow : <T>(value: any) => asserts value is T
>foo : any
>Narrow<string>(bar) : void
>Narrow : <T>(value: any) => asserts value is T
>bar : any
foo;
>foo : number
bar;
>bar : string
}
function func2(foo: any, bar: any, baz: any) {
>func2 : (foo: any, bar: any, baz: any) => void
>foo : any
>bar : any
>baz : any
Narrow<number>(foo), Narrow<string>(bar), Narrow<boolean>(baz);
>Narrow<number>(foo), Narrow<string>(bar), Narrow<boolean>(baz) : void
>Narrow<number>(foo), Narrow<string>(bar) : void
>Narrow<number>(foo) : void
>Narrow : <T>(value: any) => asserts value is T
>foo : any
>Narrow<string>(bar) : void
>Narrow : <T>(value: any) => asserts value is T
>bar : any
>Narrow<boolean>(baz) : void
>Narrow : <T>(value: any) => asserts value is T
>baz : any
foo;
>foo : number
bar;
>bar : string
baz;
>baz : boolean
}

View File

@ -0,0 +1,14 @@
function Narrow<T>(value: any): asserts value is T {}
function func(foo: any, bar: any) {
Narrow<number>(foo), Narrow<string>(bar);
foo;
bar;
}
function func2(foo: any, bar: any, baz: any) {
Narrow<number>(foo), Narrow<string>(bar), Narrow<boolean>(baz);
foo;
bar;
baz;
}