Symptom
A microflow authored with IF … THEN … ELSIF … THEN … ELSE … END IF loses every ELSIF arm when written to the .mpr. Only the first IF condition/body and the trailing ELSE body reach the model. No error, no warning — mxcli check passes, exec reports success, and mx check on the resulting app is clean, so the data loss is completely silent.
Reproduced on v0.13.0 and v0.14.0, on both engines (modelsdk and legacy), Windows, against a fresh mxcli new 11.11.0 app.
Repro
CREATE MICROFLOW MyFirstModule.TestElsif ($In: Integer)
RETURNS String AS $Out
BEGIN
DECLARE $Out String = 'none';
IF $In = 1 THEN
SET $Out = 'one';
ELSIF $In = 2 THEN
SET $Out = 'two';
ELSE
SET $Out = 'other';
END IF;
RETURN $Out;
END;
mxcli exec probe-elsif.mdl -p App.mpr # "Created microflow" — no error
mxcli -p App.mpr -c "DESCRIBE MICROFLOW MyFirstModule.TestElsif"
Round-trip output — the $In = 2 → 'two' arm is gone:
if $In = 1 then
set $Out = 'one';
else
set $Out = 'other';
end if;
The drop is on write, not a DESCRIBE artifact: DESCRIBE renders what is stored in the .mpr, and with only the visitor (write-side AST build) fixed — the read path untouched — the same DESCRIBE shows every arm present. Before the fix the stored model itself lacked the arm.
Root cause
buildIfStatement in mdl/visitor/visitor_microflow_statements.go reads only exprs[0] / bodies[0] and treats the last body as ELSE. The middle (ELSIF expression THEN microflowBody)* pairs from the grammar rule are never visited:
exprs := ifCtx.AllExpression()
if len(exprs) > 0 { stmt.Condition = buildSourceExpression(exprs[0]) } // only [0]
bodies := ifCtx.AllMicroflowBody()
if len(bodies) > 0 { stmt.ThenBody = buildMicroflowBody(bodies[0]) } // only [0]
if len(bodies) > len(exprs) { stmt.ElseBody = ...bodies[len(bodies)-1] } // last = ELSE
Proposed fix
Mendix has no native elsif construct, so lower each ELSIF arm into a nested IfStmt in the ELSE branch of the arm before it (built innermost-first) — if A then X elsif B then Y else Z becomes if A then X else { if B then Y else Z }, which is the canonical nested-exclusive-split shape and what Studio Pro users build by hand.
Fix + visitor unit tests (elsif chain, elsif-without-else, plain if/else regression guard) + mdl-examples/bug-tests/elsif-arms-dropped.mdl + fix-issue.md symptom row are ready on a branch; I can open the PR immediately on sign-off.
(Found while re-validating mxcli 0.14.0 for our internal Mendix build tooling — we've been carrying a "never emit ELSIF, always nest IF/ELSE" workaround since 0.12.0.)
Symptom
A microflow authored with
IF … THEN … ELSIF … THEN … ELSE … END IFloses every ELSIF arm when written to the.mpr. Only the firstIFcondition/body and the trailingELSEbody reach the model. No error, no warning —mxcli checkpasses,execreports success, andmx checkon the resulting app is clean, so the data loss is completely silent.Reproduced on v0.13.0 and v0.14.0, on both engines (modelsdk and legacy), Windows, against a fresh
mxcli new11.11.0 app.Repro
Round-trip output — the
$In = 2 → 'two'arm is gone:The drop is on write, not a DESCRIBE artifact: DESCRIBE renders what is stored in the
.mpr, and with only the visitor (write-side AST build) fixed — the read path untouched — the same DESCRIBE shows every arm present. Before the fix the stored model itself lacked the arm.Root cause
buildIfStatementinmdl/visitor/visitor_microflow_statements.goreads onlyexprs[0]/bodies[0]and treats the last body as ELSE. The middle(ELSIF expression THEN microflowBody)*pairs from the grammar rule are never visited:Proposed fix
Mendix has no native elsif construct, so lower each ELSIF arm into a nested
IfStmtin the ELSE branch of the arm before it (built innermost-first) —if A then X elsif B then Y else Zbecomesif A then X else { if B then Y else Z }, which is the canonical nested-exclusive-split shape and what Studio Pro users build by hand.Fix + visitor unit tests (elsif chain, elsif-without-else, plain if/else regression guard) +
mdl-examples/bug-tests/elsif-arms-dropped.mdl+ fix-issue.md symptom row are ready on a branch; I can open the PR immediately on sign-off.(Found while re-validating mxcli 0.14.0 for our internal Mendix build tooling — we've been carrying a "never emit ELSIF, always nest IF/ELSE" workaround since 0.12.0.)