Skip to content

Commit 5afbf6a

Browse files
committed
fix: preserve enum split nested continuation cases
Symptom: an enum split branch containing a nested empty-then decision could round-trip to an MPR whose outgoing decision flow lacked the boolean case value, causing Mendix mx check CE0079/CE0773 even when the described MDL was stable. Root cause: addEnumSplit consumed flowBuilder.nextConnectionPoint from the nested decision but dropped flowBuilder.nextFlowCase before wiring the branch continuation to the shared enum merge. Fix: carry the pending case value through enum branch continuation wiring and reapply it when connecting to the next statement or enum merge. Tests: add a builder regression for a nested empty-then enum branch that must keep CaseValue=true on the continuation flow.
1 parent fd36ff9 commit 5afbf6a

2 files changed

Lines changed: 72 additions & 2 deletions

File tree

mdl/executor/cmd_microflows_builder_actions.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ func (fb *flowBuilder) addEnumSplit(s *ast.EnumSplitStmt) model.ID {
342342
fb.endsWithReturn = false
343343

344344
lastID := model.ID("")
345+
pendingCase := ""
345346
for _, stmt := range br.body {
346347
actID := fb.addStatement(stmt)
347348
if actID == "" {
@@ -354,11 +355,18 @@ func (fb *flowBuilder) addEnumSplit(s *ast.EnumSplitStmt) model.ID {
354355
if lastID == "" {
355356
fb.addEnumSplitFlows(splitID, actID, br.values)
356357
} else {
357-
fb.flows = append(fb.flows, newHorizontalFlow(lastID, actID))
358+
if pendingCase != "" {
359+
fb.flows = append(fb.flows, newHorizontalFlowWithCase(lastID, actID, pendingCase))
360+
pendingCase = ""
361+
} else {
362+
fb.flows = append(fb.flows, newHorizontalFlow(lastID, actID))
363+
}
358364
}
359365
if fb.nextConnectionPoint != "" {
360366
lastID = fb.nextConnectionPoint
361367
fb.nextConnectionPoint = ""
368+
pendingCase = fb.nextFlowCase
369+
fb.nextFlowCase = ""
362370
} else {
363371
lastID = actID
364372
}
@@ -371,7 +379,11 @@ func (fb *flowBuilder) addEnumSplit(s *ast.EnumSplitStmt) model.ID {
371379
if lastID == "" {
372380
fb.addEnumSplitFlows(splitID, merge.ID, br.values)
373381
} else {
374-
fb.flows = append(fb.flows, newHorizontalFlow(lastID, merge.ID))
382+
if pendingCase != "" {
383+
fb.flows = append(fb.flows, newHorizontalFlowWithCase(lastID, merge.ID, pendingCase))
384+
} else {
385+
fb.flows = append(fb.flows, newHorizontalFlow(lastID, merge.ID))
386+
}
375387
}
376388
}
377389

mdl/executor/cmd_microflows_builder_enum_split_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"testing"
77

88
"github.com/mendixlabs/mxcli/mdl/ast"
9+
"github.com/mendixlabs/mxcli/model"
910
"github.com/mendixlabs/mxcli/sdk/microflows"
1011
)
1112

@@ -61,3 +62,60 @@ func TestEnumSplitBuilderCreatesEnumerationCaseFlows(t *testing.T) {
6162
t.Fatalf("enum case flows = %v, want [Open Pending]", cases)
6263
}
6364
}
65+
66+
func TestEnumSplitNestedEmptyThenBranchKeepsContinuationCase(t *testing.T) {
67+
fb := &flowBuilder{
68+
spacing: HorizontalSpacing,
69+
declaredVars: map[string]string{"MemberProvided": "Boolean"},
70+
measurer: &layoutMeasurer{},
71+
}
72+
73+
oc := fb.buildFlowGraph([]ast.MicroflowStatement{
74+
&ast.EnumSplitStmt{
75+
Variable: "SubjectType",
76+
Cases: []ast.EnumSplitCase{
77+
{
78+
Value: "member",
79+
Body: []ast.MicroflowStatement{
80+
&ast.IfStmt{
81+
Condition: &ast.VariableExpr{Name: "MemberProvided"},
82+
ElseBody: []ast.MicroflowStatement{&ast.ReturnStmt{}},
83+
},
84+
},
85+
},
86+
{
87+
Value: "unknown",
88+
Body: []ast.MicroflowStatement{&ast.ReturnStmt{}},
89+
},
90+
},
91+
},
92+
&ast.LogStmt{Level: ast.LogInfo, Message: &ast.LiteralExpr{Kind: ast.LiteralString, Value: "shared tail"}},
93+
}, nil)
94+
95+
objects := map[model.ID]microflows.MicroflowObject{}
96+
var nestedSplitID model.ID
97+
for _, obj := range oc.Objects {
98+
objects[obj.GetID()] = obj
99+
split, ok := obj.(*microflows.ExclusiveSplit)
100+
if !ok {
101+
continue
102+
}
103+
if condition, ok := split.SplitCondition.(*microflows.ExpressionSplitCondition); ok && condition.Expression == "$MemberProvided" {
104+
nestedSplitID = split.ID
105+
}
106+
}
107+
if nestedSplitID == "" {
108+
t.Fatal("expected nested decision split")
109+
}
110+
for _, flow := range oc.Flows {
111+
if flow.OriginID != nestedSplitID {
112+
continue
113+
}
114+
if value, ok := enumCaseValue(flow); ok && value == "true" {
115+
if _, ok := objects[flow.DestinationID].(*microflows.ExclusiveMerge); ok {
116+
return
117+
}
118+
}
119+
}
120+
t.Fatal("nested empty-then enum branch must carry CaseValue=true to the enum merge")
121+
}

0 commit comments

Comments
 (0)