Skip to content

Commit e464177

Browse files
akoclaude
andcommitted
fix: emit loop body and END LOOP when loop is inside an IF branch (#65)
traverseFlowUntilMerge (used for activities inside IF/ELSE branches) did not handle LoopedActivity — loops fell through to the "regular activity" path which emitted the LOOP header but never called emitLoopBody() or appended END LOOP. Add explicit LoopedActivity handling in traverseFlowUntilMerge, matching the pattern already used in traverseFlow and traverseLoopBody. Add regression test TestRoundtripMicroflow_LoopInsideBranch. Fixes #65 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 715c8cd commit e464177

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

mdl/executor/cmd_microflows_show_helpers.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,27 @@ func (e *Executor) traverseFlowUntilMerge(
348348
return
349349
}
350350

351+
// Handle LoopedActivity inside a branch
352+
if loop, isLoop := obj.(*microflows.LoopedActivity); isLoop {
353+
startLine := len(*lines) + headerLineCount
354+
if stmt != "" {
355+
emitObjectAnnotations(obj, lines, indentStr, annotationsByTarget)
356+
*lines = append(*lines, indentStr+stmt)
357+
}
358+
359+
e.emitLoopBody(loop, flowsByOrigin, entityNames, microflowNames, lines, indent, sourceMap, headerLineCount, annotationsByTarget)
360+
361+
*lines = append(*lines, indentStr+loopEndKeyword(loop)+";")
362+
recordSourceMap(sourceMap, currentID, startLine, len(*lines)+headerLineCount-1)
363+
364+
// Continue after the loop within the branch
365+
flows := flowsByOrigin[currentID]
366+
for _, flow := range flows {
367+
e.traverseFlowUntilMerge(flow.DestinationID, mergeID, activityMap, flowsByOrigin, splitMergeMap, visited, entityNames, microflowNames, lines, indent, sourceMap, headerLineCount, annotationsByTarget)
368+
}
369+
return
370+
}
371+
351372
// Regular activity
352373
startLine := len(*lines) + headerLineCount
353374
normalFlows := findNormalFlows(flowsByOrigin[currentID])

mdl/executor/roundtrip_microflow_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,36 @@ END;`
435435
)
436436
}
437437

438+
// TestRoundtripMicroflow_LoopInsideBranch tests that a LOOP inside an IF branch
439+
// correctly emits loop body activities and END LOOP. Regression test for #65.
440+
func TestRoundtripMicroflow_LoopInsideBranch(t *testing.T) {
441+
env := setupTestEnv(t)
442+
defer env.teardown()
443+
444+
if err := env.executeMDL(`CREATE OR MODIFY PERSISTENT ENTITY RoundtripTest.MfTestItem (Name: String(100));`); err != nil {
445+
t.Fatalf("Failed to create entity: %v", err)
446+
}
447+
448+
mfName := testModule + ".RT_LoopInBranch"
449+
createMDL := `CREATE MICROFLOW ` + mfName + ` ($Flag: Boolean) RETURNS Boolean
450+
BEGIN
451+
IF $Flag THEN
452+
RETRIEVE $Items FROM RoundtripTest.MfTestItem;
453+
LOOP $Item IN $Items BEGIN
454+
LOG INFO NODE 'Test' 'In loop';
455+
END LOOP;
456+
ELSE
457+
LOG INFO NODE 'Test' 'No items';
458+
END IF;
459+
RETURN true;
460+
END;`
461+
462+
assertMicroflowContains(t, env, mfName, createMDL,
463+
[]string{"IF", "RETRIEVE", "LOOP", "LOG INFO", "In loop", "END LOOP", "ELSE", "No items", "END IF", "RETURN"},
464+
nil,
465+
)
466+
}
467+
438468
// TestRoundtripMicroflow_ValidationFeedback tests VALIDATION FEEDBACK statement
439469
// which triggered a crash bug with nil settings.
440470
func TestRoundtripMicroflow_ValidationFeedback(t *testing.T) {

0 commit comments

Comments
 (0)