Skip to content

Commit 191c20b

Browse files
authored
Fix preceding statements with ternary operator (#1234)
Fixes #1231
1 parent 3bae760 commit 191c20b

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

src/transformation/visitors/conditional.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,30 @@ import { performHoisting, popScope, pushScope, ScopeType } from "../utils/scope"
66
import { transformBlockOrStatement } from "./block";
77
import { canBeFalsy } from "../utils/typescript";
88

9+
type EvaluatedExpression = [precedingStatemens: lua.Statement[], value: lua.Expression];
10+
911
function transformProtectedConditionalExpression(
1012
context: TransformationContext,
11-
expression: ts.ConditionalExpression
13+
expression: ts.ConditionalExpression,
14+
condition: EvaluatedExpression,
15+
whenTrue: EvaluatedExpression,
16+
whenFalse: EvaluatedExpression
1217
): lua.Expression {
1318
const tempVar = context.createTempNameForNode(expression.condition);
1419

15-
const condition = context.transformExpression(expression.condition);
16-
17-
const [trueStatements, val1] = transformInPrecedingStatementScope(context, () =>
18-
context.transformExpression(expression.whenTrue)
20+
const trueStatements = whenTrue[0].concat(
21+
lua.createAssignmentStatement(lua.cloneIdentifier(tempVar), whenTrue[1], expression.whenTrue)
1922
);
20-
trueStatements.push(lua.createAssignmentStatement(lua.cloneIdentifier(tempVar), val1, expression.whenTrue));
2123

22-
const [falseStatements, val2] = transformInPrecedingStatementScope(context, () =>
23-
context.transformExpression(expression.whenFalse)
24+
const falseStatements = whenFalse[0].concat(
25+
lua.createAssignmentStatement(lua.cloneIdentifier(tempVar), whenFalse[1], expression.whenFalse)
2426
);
25-
falseStatements.push(lua.createAssignmentStatement(lua.cloneIdentifier(tempVar), val2, expression.whenFalse));
2627

2728
context.addPrecedingStatements([
2829
lua.createVariableDeclarationStatement(tempVar, undefined, expression.condition),
30+
...condition[0],
2931
lua.createIfStatement(
30-
condition,
32+
condition[1],
3133
lua.createBlock(trueStatements, expression.whenTrue),
3234
lua.createBlock(falseStatements, expression.whenFalse),
3335
expression
@@ -37,17 +39,27 @@ function transformProtectedConditionalExpression(
3739
}
3840

3941
export const transformConditionalExpression: FunctionVisitor<ts.ConditionalExpression> = (expression, context) => {
40-
if (canBeFalsy(context, context.checker.getTypeAtLocation(expression.whenTrue))) {
41-
return transformProtectedConditionalExpression(context, expression);
42+
const condition = transformInPrecedingStatementScope(context, () =>
43+
context.transformExpression(expression.condition)
44+
);
45+
const whenTrue = transformInPrecedingStatementScope(context, () =>
46+
context.transformExpression(expression.whenTrue)
47+
);
48+
const whenFalse = transformInPrecedingStatementScope(context, () =>
49+
context.transformExpression(expression.whenFalse)
50+
);
51+
if (
52+
whenTrue[0].length > 0 ||
53+
whenFalse[0].length > 0 ||
54+
canBeFalsy(context, context.checker.getTypeAtLocation(expression.whenTrue))
55+
) {
56+
return transformProtectedConditionalExpression(context, expression, condition, whenTrue, whenFalse);
4257
}
4358

44-
const condition = context.transformExpression(expression.condition);
45-
const val1 = context.transformExpression(expression.whenTrue);
46-
const val2 = context.transformExpression(expression.whenFalse);
47-
4859
// condition and v1 or v2
49-
const conditionAnd = lua.createBinaryExpression(condition, val1, lua.SyntaxKind.AndOperator);
50-
return lua.createBinaryExpression(conditionAnd, val2, lua.SyntaxKind.OrOperator, expression);
60+
context.addPrecedingStatements(condition[0]);
61+
const conditionAnd = lua.createBinaryExpression(condition[1], whenTrue[1], lua.SyntaxKind.AndOperator);
62+
return lua.createBinaryExpression(conditionAnd, whenFalse[1], lua.SyntaxKind.OrOperator, expression);
5163
};
5264

5365
export function transformIfStatement(statement: ts.IfStatement, context: TransformationContext): lua.IfStatement {

test/unit/conditionals.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,29 @@ test.each([false, true, null])("Ternary conditional with generic whenTrue branch
112112
})
113113
.expectToMatchJsResult();
114114
});
115+
116+
test.each([false, true])("Ternary conditional with preceding statements in true branch (%p)", trueVal => {
117+
// language=TypeScript
118+
util.testFunction`
119+
let i = 0;
120+
const result = ${trueVal} ? i += 1 : i;
121+
return { result, i };
122+
`
123+
.setOptions({
124+
strictNullChecks: true,
125+
})
126+
.expectToMatchJsResult();
127+
});
128+
129+
test.each([false, true])("Ternary conditional with preceding statements in false branch (%p)", trueVal => {
130+
// language=TypeScript
131+
util.testFunction`
132+
let i = 0;
133+
const result = ${trueVal} ? i : i += 2;
134+
return { result, i };
135+
`
136+
.setOptions({
137+
strictNullChecks: true,
138+
})
139+
.expectToMatchJsResult();
140+
});

0 commit comments

Comments
 (0)