Skip to content

Commit 7e0bf0e

Browse files
committed
fix: track add-to-list expression inputs
Symptom: expression-valued add-to-list statements were parsed and written correctly, but validator and builder graph walkers only inspected the legacy Item field. Root cause: the new Value expression path was not wired into referenced-variable and object-input collection, so variables used only inside add expressions could be missed. Fix: walk AddToListStmt.Value when present, keep the legacy Item fallback for synthetic callers, and rename the doctype example to .mdl so CI executes it. Tests: added builder, validator, and visitor assertions; ran mxcli check for the doctype fixture plus make build and make test.
1 parent 7e68b33 commit 7e0bf0e

6 files changed

Lines changed: 74 additions & 2 deletions

File tree

mdl-examples/doctype-tests/add_expression_to_list.test.mdl renamed to mdl-examples/doctype-tests/add_expression_to_list.mdl

File renamed without changes.

mdl/executor/cmd_microflows_builder_add_to_list_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ func TestAddToListBuilderKeepsSimpleVariableFallback(t *testing.T) {
4040
}
4141
}
4242

43+
func TestCollectObjectInputVariablesSeesAddExpressionValue(t *testing.T) {
44+
inputs := collectObjectInputVariables([]ast.MicroflowStatement{
45+
&ast.AddToListStmt{
46+
Value: &ast.FunctionCallExpr{
47+
Name: "head",
48+
Arguments: []ast.Expression{
49+
&ast.VariableExpr{Name: "SourceItems"},
50+
},
51+
},
52+
List: "Items",
53+
},
54+
})
55+
56+
if !inputs["SourceItems"] {
57+
t.Fatalf("SourceItems was not collected from add expression: %#v", inputs)
58+
}
59+
}
60+
4361
func lastChangeListAction(t *testing.T, fb *flowBuilder) *microflows.ChangeListAction {
4462
t.Helper()
4563

mdl/executor/cmd_microflows_builder_graph.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,11 @@ func collectObjectInputVariables(stmts []ast.MicroflowStatement) map[string]bool
309309
case *ast.AggregateListStmt:
310310
walkExpr(s.Expression)
311311
case *ast.AddToListStmt:
312-
if s.Item != "" {
312+
if s.Value != nil {
313+
for _, ref := range exprVarRefs(s.Value) {
314+
inputs[ref] = true
315+
}
316+
} else if s.Item != "" {
313317
inputs[s.Item] = true
314318
}
315319
case *ast.CallMicroflowStmt:

mdl/executor/validate_microflow.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,12 @@ func referencedVars(stmt ast.MicroflowStatement) []string {
481481
case *ast.DeleteObjectStmt:
482482
refs = append(refs, s.Variable)
483483
case *ast.AddToListStmt:
484-
refs = append(refs, s.Item, s.List)
484+
if s.Value != nil {
485+
refs = append(refs, exprVarRefs(s.Value)...)
486+
} else {
487+
refs = append(refs, s.Item)
488+
}
489+
refs = append(refs, s.List)
485490
case *ast.RemoveFromListStmt:
486491
refs = append(refs, s.Item, s.List)
487492
case *ast.LogStmt:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package executor
4+
5+
import (
6+
"strings"
7+
"testing"
8+
9+
"github.com/mendixlabs/mxcli/mdl/ast"
10+
"github.com/mendixlabs/mxcli/mdl/visitor"
11+
)
12+
13+
func TestValidateMicroflowReferencesAddExpressionValue(t *testing.T) {
14+
input := `create microflow Synthetic.MF_AddExpressionScope ()
15+
returns Boolean
16+
begin
17+
declare $Items List of Synthetic.Item = empty;
18+
if true then
19+
declare $SourceItems List of Synthetic.Item = empty;
20+
end if;
21+
add head($SourceItems) to $Items;
22+
return true;
23+
end;`
24+
25+
prog, errs := visitor.Build(input)
26+
if len(errs) > 0 {
27+
t.Fatalf("Parse error: %v", errs[0])
28+
}
29+
stmt := prog.Statements[0].(*ast.CreateMicroflowStmt)
30+
31+
violations := ValidateMicroflow(stmt)
32+
for _, violation := range violations {
33+
if violation.RuleID == "MDL005" && strings.Contains(violation.Message, "$SourceItems") {
34+
return
35+
}
36+
}
37+
t.Fatalf("Expected MDL005 for add expression source variable, got %#v", violations)
38+
}

mdl/visitor/visitor_add_to_list_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,11 @@ END;`
6767
if addStmt.Item != "Order" {
6868
t.Fatalf("Item = %q, want Order", addStmt.Item)
6969
}
70+
varExpr, ok := addStmt.Value.(*ast.VariableExpr)
71+
if !ok {
72+
t.Fatalf("Value = %T, want VariableExpr", addStmt.Value)
73+
}
74+
if varExpr.Name != "Order" {
75+
t.Fatalf("Value.Name = %q, want Order", varExpr.Name)
76+
}
7077
}

0 commit comments

Comments
 (0)