Skip to content

Commit b8ee049

Browse files
committed
fix: preserve Java action microflow placeholder parameters
Symptom: Java actions with microflow-typed parameters roundtripped placeholder arguments as basic empty expressions, which Studio Pro reported as stale Java action arguments. Root cause: the SDK/parser/writer did not model Microflows$MicroflowParameterValue, and the builder treated all ellipsis placeholders as BasicCodeActionParameterValue. Fix: add MicroflowParameterValue support end-to-end and emit it for Java action parameters whose definition is MicroflowType, keeping ellipsis as an empty microflow reference. Tests: added builder and parser regressions and ran make test.
1 parent 8aa797e commit b8ee049

9 files changed

Lines changed: 145 additions & 7 deletions

mdl/executor/cmd_microflows_builder_calls.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,13 @@ func (fb *flowBuilder) addCallJavaActionAction(s *ast.CallJavaActionStmt) model.
184184

185185
// Build a map of parameter name -> param type for the Java action
186186
entityTypeParams := make(map[string]bool)
187+
microflowTypeParams := make(map[string]bool)
187188
if jaDef != nil {
188189
for _, p := range jaDef.Parameters {
189190
if _, ok := p.ParameterType.(*javaactions.EntityTypeParameterType); ok {
190191
entityTypeParams[p.Name] = true
192+
} else if _, ok := p.ParameterType.(*javaactions.MicroflowType); ok {
193+
microflowTypeParams[p.Name] = true
191194
}
192195
}
193196
}
@@ -217,16 +220,30 @@ func (fb *flowBuilder) addCallJavaActionAction(s *ast.CallJavaActionStmt) model.
217220
Entity: entityName,
218221
}
219222
} else if isPlaceholderExpression(arg.Value) {
220-
value = &microflows.BasicCodeActionParameterValue{
221-
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
222-
Argument: "",
223+
if microflowTypeParams[arg.Name] {
224+
value = &microflows.MicroflowParameterValue{
225+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
226+
Microflow: "",
227+
}
228+
} else {
229+
value = &microflows.BasicCodeActionParameterValue{
230+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
231+
Argument: "",
232+
}
223233
}
224234
} else {
225235
// Regular parameter: expression-based value
226236
valueExpr := fb.exprToString(arg.Value)
227-
value = &microflows.BasicCodeActionParameterValue{
228-
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
229-
Argument: valueExpr,
237+
if microflowTypeParams[arg.Name] {
238+
value = &microflows.MicroflowParameterValue{
239+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
240+
Microflow: strings.Trim(valueExpr, "'"),
241+
}
242+
} else {
243+
value = &microflows.BasicCodeActionParameterValue{
244+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
245+
Argument: valueExpr,
246+
}
230247
}
231248
}
232249

mdl/executor/cmd_microflows_builder_java_action_test.go

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

88
"github.com/mendixlabs/mxcli/mdl/ast"
9+
"github.com/mendixlabs/mxcli/mdl/backend/mock"
10+
"github.com/mendixlabs/mxcli/model"
11+
"github.com/mendixlabs/mxcli/sdk/javaactions"
912
"github.com/mendixlabs/mxcli/sdk/microflows"
1013
)
1114

@@ -57,3 +60,57 @@ func TestBuildJavaAction_PlaceholderArgumentPreservesEmptyBasicValue(t *testing.
5760
t.Fatalf("boolean argument = %q, want true", value.Argument)
5861
}
5962
}
63+
64+
func TestBuildJavaAction_PlaceholderMicroflowArgumentUsesMicroflowParameterValue(t *testing.T) {
65+
fb := &flowBuilder{
66+
posX: 100,
67+
posY: 100,
68+
spacing: HorizontalSpacing,
69+
backend: &mock.MockBackend{
70+
ReadJavaActionByNameFunc: func(qualifiedName string) (*javaactions.JavaAction, error) {
71+
if qualifiedName != "SampleModule.StartAsync" {
72+
t.Fatalf("java action lookup = %q", qualifiedName)
73+
}
74+
return &javaactions.JavaAction{
75+
Parameters: []*javaactions.JavaActionParameter{
76+
{
77+
Name: "Callback",
78+
ParameterType: &javaactions.MicroflowType{
79+
BaseElement: model.BaseElement{ID: "param-type"},
80+
},
81+
},
82+
},
83+
}, nil
84+
},
85+
},
86+
}
87+
stmt := &ast.CallJavaActionStmt{
88+
ActionName: ast.QualifiedName{Module: "SampleModule", Name: "StartAsync"},
89+
Arguments: []ast.CallArgument{
90+
{Name: "Callback", Value: &ast.SourceExpr{Source: "..."}},
91+
},
92+
}
93+
94+
id := fb.addCallJavaActionAction(stmt)
95+
var activity *microflows.ActionActivity
96+
for _, obj := range fb.objects {
97+
if obj.GetID() == id {
98+
activity, _ = obj.(*microflows.ActionActivity)
99+
break
100+
}
101+
}
102+
if activity == nil {
103+
t.Fatal("expected Java action activity")
104+
}
105+
action, ok := activity.Action.(*microflows.JavaActionCallAction)
106+
if !ok {
107+
t.Fatalf("action = %T, want *JavaActionCallAction", activity.Action)
108+
}
109+
value, ok := action.ParameterMappings[0].Value.(*microflows.MicroflowParameterValue)
110+
if !ok {
111+
t.Fatalf("mapping value = %T, want *MicroflowParameterValue", action.ParameterMappings[0].Value)
112+
}
113+
if value.Microflow != "" {
114+
t.Fatalf("placeholder microflow = %q, want empty string", value.Microflow)
115+
}
116+
}

mdl/executor/cmd_microflows_format_action.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,10 @@ func formatAction(
449449
if v.Argument != "" {
450450
valueStr = v.Argument
451451
}
452+
case *microflows.MicroflowParameterValue:
453+
if v.Microflow != "" {
454+
valueStr = mdlQuote(v.Microflow)
455+
}
452456
case *microflows.EntityTypeCodeActionParameterValue:
453457
if v.Entity != "" {
454458
valueStr = mdlQuote(v.Entity)

sdk/microflows/microflows_actions.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,15 @@ type BasicCodeActionParameterValue struct {
568568

569569
func (BasicCodeActionParameterValue) isCodeActionParameterValue() {}
570570

571+
// MicroflowParameterValue is a microflow reference passed to a Java action
572+
// microflow parameter. An empty Microflow keeps Studio Pro's placeholder value.
573+
type MicroflowParameterValue struct {
574+
model.BaseElement
575+
Microflow string `json:"microflow,omitempty"` // BY_NAME_REFERENCE: qualified microflow name
576+
}
577+
578+
func (MicroflowParameterValue) isCodeActionParameterValue() {}
579+
571580
// EntityTypeCodeActionParameterValue is an entity type passed at a call site for a type parameter.
572581
type EntityTypeCodeActionParameterValue struct {
573582
model.BaseElement

sdk/mpr/parser_javaactions.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ func parseCodeActionParameterType(raw map[string]any) javaactions.CodeActionPara
402402
}
403403
et.Enumeration = extractString(raw["Enumeration"])
404404
return et
405-
case "CodeActions$MicroflowType":
405+
case "CodeActions$MicroflowType", "JavaActions$MicroflowJavaActionParameterType":
406406
return &javaactions.MicroflowType{
407407
BaseElement: model.BaseElement{ID: model.ID(extractBsonID(raw["$ID"]))},
408408
}
@@ -461,6 +461,10 @@ func parseInnerParameterType(raw map[string]any) javaactions.CodeActionParameter
461461
return &javaactions.DateTimeType{
462462
BaseElement: model.BaseElement{ID: model.ID(extractBsonID(raw["$ID"]))},
463463
}
464+
case "CodeActions$MicroflowType", "JavaActions$MicroflowJavaActionParameterType":
465+
return &javaactions.MicroflowType{
466+
BaseElement: model.BaseElement{ID: model.ID(extractBsonID(raw["$ID"]))},
467+
}
464468
case "CodeActions$ConcreteEntityType", "CodeActions$EntityType":
465469
et := &javaactions.EntityType{
466470
BaseElement: model.BaseElement{ID: model.ID(extractBsonID(raw["$ID"]))},

sdk/mpr/parser_javaactions_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package mpr
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/sdk/javaactions"
9+
)
10+
11+
func TestParseCodeActionParameterType_JavaActionMicroflowParameter(t *testing.T) {
12+
value := parseCodeActionParameterType(map[string]any{
13+
"$ID": "type-1",
14+
"$Type": "JavaActions$MicroflowJavaActionParameterType",
15+
})
16+
17+
if _, ok := value.(*javaactions.MicroflowType); !ok {
18+
t.Fatalf("value = %T, want *MicroflowType", value)
19+
}
20+
}

sdk/mpr/parser_microflow_actions.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ func parseCodeActionParameterValue(raw map[string]any) microflows.CodeActionPara
118118
value.ID = model.ID(extractBsonID(raw["$ID"]))
119119
value.Argument = extractString(raw["Argument"])
120120
return value
121+
case "Microflows$MicroflowParameterValue":
122+
value := &microflows.MicroflowParameterValue{}
123+
value.ID = model.ID(extractBsonID(raw["$ID"]))
124+
value.Microflow = extractString(raw["Microflow"])
125+
return value
121126
case "Microflows$EntityTypeCodeActionParameterValue":
122127
value := &microflows.EntityTypeCodeActionParameterValue{}
123128
value.ID = model.ID(extractBsonID(raw["$ID"]))

sdk/mpr/parser_microflow_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,19 @@ func TestParseSequenceFlow_NewCaseValueNoCase(t *testing.T) {
4747
t.Fatalf("expected *NoCase, got %T", flow.CaseValue)
4848
}
4949
}
50+
51+
func TestParseCodeActionParameterValue_MicroflowParameterValue(t *testing.T) {
52+
value := parseCodeActionParameterValue(map[string]any{
53+
"$ID": "value-1",
54+
"$Type": "Microflows$MicroflowParameterValue",
55+
"Microflow": "SampleModule.Callback",
56+
})
57+
58+
got, ok := value.(*microflows.MicroflowParameterValue)
59+
if !ok {
60+
t.Fatalf("value = %T, want *MicroflowParameterValue", value)
61+
}
62+
if got.Microflow != "SampleModule.Callback" {
63+
t.Fatalf("microflow = %q", got.Microflow)
64+
}
65+
}

sdk/mpr/writer_microflow_actions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,12 @@ func serializeCodeActionParameterValue(v microflows.CodeActionParameterValue) bs
10801080
{Key: "$Type", Value: "Microflows$BasicCodeActionParameterValue"},
10811081
{Key: "Argument", Value: value.Argument},
10821082
}
1083+
case *microflows.MicroflowParameterValue:
1084+
return bson.D{
1085+
{Key: "$ID", Value: idToBsonBinary(string(value.ID))},
1086+
{Key: "$Type", Value: "Microflows$MicroflowParameterValue"},
1087+
{Key: "Microflow", Value: value.Microflow},
1088+
}
10831089
case *microflows.EntityTypeCodeActionParameterValue:
10841090
return bson.D{
10851091
{Key: "$ID", Value: idToBsonBinary(string(value.ID))},

0 commit comments

Comments
 (0)