@@ -106,6 +106,9 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
106106 }
107107
108108 thenStartX := splitX + SplitWidth + HorizontalSpacing / 2
109+ var noMergeExitID model.ID
110+ var noMergeExitCase string
111+ var noMergeExitAnchor * ast.FlowAnchors
109112
110113 if hasElseBody {
111114 // IF WITH ELSE: TRUE path horizontal (happy path), FALSE path below
@@ -115,6 +118,8 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
115118
116119 var lastThenID model.ID
117120 var prevThenAnchor * ast.FlowAnchors
121+ var pendingThenCase string
122+ var pendingThenAnchor * ast.FlowAnchors
118123 for _ , stmt := range s .ThenBody {
119124 thisAnchor := stmtOwnAnchor (stmt )
120125 actID := fb .addStatement (stmt )
@@ -131,7 +136,17 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
131136 }
132137 fb .flows = append (fb .flows , flow )
133138 } else {
134- flow := newHorizontalFlow (lastThenID , actID )
139+ var flow * microflows.SequenceFlow
140+ if pendingThenCase != "" {
141+ flow = newHorizontalFlowWithCase (lastThenID , actID , pendingThenCase )
142+ if pendingThenAnchor != nil {
143+ prevThenAnchor = pendingThenAnchor
144+ }
145+ pendingThenCase = ""
146+ pendingThenAnchor = nil
147+ } else {
148+ flow = newHorizontalFlow (lastThenID , actID )
149+ }
135150 applyUserAnchors (flow , prevThenAnchor , thisAnchor )
136151 fb .flows = append (fb .flows , flow )
137152 }
@@ -140,6 +155,10 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
140155 if fb .nextConnectionPoint != "" {
141156 lastThenID = fb .nextConnectionPoint
142157 fb .nextConnectionPoint = ""
158+ pendingThenCase = fb .nextFlowCase
159+ fb .nextFlowCase = ""
160+ pendingThenAnchor = fb .nextFlowAnchor
161+ fb .nextFlowAnchor = nil
143162 } else {
144163 lastThenID = actID
145164 }
@@ -151,7 +170,15 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
151170 // nextConnectionPoint/nextFlowCase, so we must not emit a dangling flow here.
152171 if ! thenReturns && needMerge {
153172 if lastThenID != "" {
154- flow := newHorizontalFlow (lastThenID , mergeID )
173+ var flow * microflows.SequenceFlow
174+ if pendingThenCase != "" {
175+ flow = newHorizontalFlowWithCase (lastThenID , mergeID , pendingThenCase )
176+ if pendingThenAnchor != nil {
177+ prevThenAnchor = pendingThenAnchor
178+ }
179+ } else {
180+ flow = newHorizontalFlow (lastThenID , mergeID )
181+ }
155182 applyUserAnchors (flow , prevThenAnchor , nil )
156183 fb .flows = append (fb .flows , flow )
157184 } else {
@@ -170,6 +197,8 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
170197
171198 var lastElseID model.ID
172199 var prevElseAnchor * ast.FlowAnchors
200+ var pendingElseCase string
201+ var pendingElseAnchor * ast.FlowAnchors
173202 for _ , stmt := range s .ElseBody {
174203 thisAnchor := stmtOwnAnchor (stmt )
175204 actID := fb .addStatement (stmt )
@@ -184,7 +213,17 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
184213 }
185214 fb .flows = append (fb .flows , flow )
186215 } else {
187- flow := newHorizontalFlow (lastElseID , actID )
216+ var flow * microflows.SequenceFlow
217+ if pendingElseCase != "" {
218+ flow = newHorizontalFlowWithCase (lastElseID , actID , pendingElseCase )
219+ if pendingElseAnchor != nil {
220+ prevElseAnchor = pendingElseAnchor
221+ }
222+ pendingElseCase = ""
223+ pendingElseAnchor = nil
224+ } else {
225+ flow = newHorizontalFlow (lastElseID , actID )
226+ }
188227 applyUserAnchors (flow , prevElseAnchor , thisAnchor )
189228 fb .flows = append (fb .flows , flow )
190229 }
@@ -193,6 +232,10 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
193232 if fb .nextConnectionPoint != "" {
194233 lastElseID = fb .nextConnectionPoint
195234 fb .nextConnectionPoint = ""
235+ pendingElseCase = fb .nextFlowCase
236+ fb .nextFlowCase = ""
237+ pendingElseAnchor = fb .nextFlowAnchor
238+ fb .nextFlowAnchor = nil
196239 } else {
197240 lastElseID = actID
198241 }
@@ -205,10 +248,50 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
205248 if ! elseReturns && needMerge {
206249 if lastElseID != "" {
207250 flow := newUpwardFlow (lastElseID , mergeID )
251+ if pendingElseCase != "" {
252+ flow .CaseValue = microflows.EnumerationCase {
253+ BaseElement : model.BaseElement {ID : model .ID (types .GenerateID ())},
254+ Value : pendingElseCase ,
255+ }
256+ if pendingElseAnchor != nil {
257+ prevElseAnchor = pendingElseAnchor
258+ }
259+ }
208260 applyUserAnchors (flow , prevElseAnchor , nil )
209261 fb .flows = append (fb .flows , flow )
210262 }
211263 }
264+ if ! needMerge {
265+ if thenReturns && ! elseReturns {
266+ if lastElseID != "" {
267+ noMergeExitID = lastElseID
268+ noMergeExitCase = pendingElseCase
269+ if pendingElseAnchor != nil {
270+ noMergeExitAnchor = pendingElseAnchor
271+ } else {
272+ noMergeExitAnchor = prevElseAnchor
273+ }
274+ } else {
275+ noMergeExitID = splitID
276+ noMergeExitCase = "false"
277+ noMergeExitAnchor = falseBranchAnchor
278+ }
279+ } else if elseReturns && ! thenReturns {
280+ if lastThenID != "" {
281+ noMergeExitID = lastThenID
282+ noMergeExitCase = pendingThenCase
283+ if pendingThenAnchor != nil {
284+ noMergeExitAnchor = pendingThenAnchor
285+ } else {
286+ noMergeExitAnchor = prevThenAnchor
287+ }
288+ } else {
289+ noMergeExitID = splitID
290+ noMergeExitCase = "true"
291+ noMergeExitAnchor = trueBranchAnchor
292+ }
293+ }
294+ }
212295 } else {
213296 // IF WITHOUT ELSE: FALSE path horizontal (happy path), TRUE path below
214297 // This keeps the "do nothing" path straight and the "do something" path below
@@ -230,6 +313,8 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
230313
231314 var lastThenID model.ID
232315 var prevThenAnchor * ast.FlowAnchors
316+ var pendingThenCase string
317+ var pendingThenAnchor * ast.FlowAnchors
233318 for _ , stmt := range s .ThenBody {
234319 thisAnchor := stmtOwnAnchor (stmt )
235320 actID := fb .addStatement (stmt )
@@ -243,7 +328,17 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
243328 }
244329 fb .flows = append (fb .flows , flow )
245330 } else {
246- flow := newHorizontalFlow (lastThenID , actID )
331+ var flow * microflows.SequenceFlow
332+ if pendingThenCase != "" {
333+ flow = newHorizontalFlowWithCase (lastThenID , actID , pendingThenCase )
334+ if pendingThenAnchor != nil {
335+ prevThenAnchor = pendingThenAnchor
336+ }
337+ pendingThenCase = ""
338+ pendingThenAnchor = nil
339+ } else {
340+ flow = newHorizontalFlow (lastThenID , actID )
341+ }
247342 applyUserAnchors (flow , prevThenAnchor , thisAnchor )
248343 fb .flows = append (fb .flows , flow )
249344 }
@@ -252,6 +347,10 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
252347 if fb .nextConnectionPoint != "" {
253348 lastThenID = fb .nextConnectionPoint
254349 fb .nextConnectionPoint = ""
350+ pendingThenCase = fb .nextFlowCase
351+ fb .nextFlowCase = ""
352+ pendingThenAnchor = fb .nextFlowAnchor
353+ fb .nextFlowAnchor = nil
255354 } else {
256355 lastThenID = actID
257356 }
@@ -264,6 +363,15 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
264363 if ! thenReturns && needMerge {
265364 if lastThenID != "" {
266365 flow := newUpwardFlow (lastThenID , mergeID )
366+ if pendingThenCase != "" {
367+ flow .CaseValue = microflows.EnumerationCase {
368+ BaseElement : model.BaseElement {ID : model .ID (types .GenerateID ())},
369+ Value : pendingThenCase ,
370+ }
371+ if pendingThenAnchor != nil {
372+ prevThenAnchor = pendingThenAnchor
373+ }
374+ }
267375 applyUserAnchors (flow , prevThenAnchor , nil )
268376 fb .flows = append (fb .flows , flow )
269377 } else {
@@ -273,6 +381,11 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
273381 fb .flows = append (fb .flows , flow )
274382 }
275383 }
384+ if ! needMerge {
385+ noMergeExitID = splitID
386+ noMergeExitCase = "false"
387+ noMergeExitAnchor = falseBranchAnchor
388+ }
276389 }
277390
278391 // If both branches end with RETURN, the flow terminates here
@@ -300,22 +413,12 @@ func (fb *flowBuilder) addIfStatement(s *ast.IfStmt) model.ID {
300413 fb .posX = max (afterSplit , afterBranch )
301414 }
302415 fb .posY = centerY
303- fb .nextConnectionPoint = splitID
304- // Tell parent to attach the case value on the next flow, and pass the
305- // matching branch anchor so @anchor(true: ..., false: ...) survives to
306- // the deferred splitID→nextActivity flow.
307- if hasElseBody {
308- if thenReturns {
309- fb .nextFlowCase = "false"
310- fb .nextFlowAnchor = falseBranchAnchor
311- } else {
312- fb .nextFlowCase = "true"
313- fb .nextFlowAnchor = trueBranchAnchor
314- }
416+ if noMergeExitID != "" {
417+ fb .nextConnectionPoint = noMergeExitID
418+ fb .nextFlowCase = noMergeExitCase
419+ fb .nextFlowAnchor = noMergeExitAnchor
315420 } else {
316- // IF without ELSE: false is the continuing path
317- fb .nextFlowCase = "false"
318- fb .nextFlowAnchor = falseBranchAnchor
421+ fb .nextConnectionPoint = splitID
319422 }
320423 }
321424
0 commit comments