Skip to content

Commit f12269d

Browse files
akoclaude
andcommitted
fix(describe): emit widget-action microflow args as Param: value (#640)
DESCRIBE emitted widget-action microflow/nanoflow arguments as `Param = $value` (IDENTIFIER EQUALS), but microflowArgV3 accepts `IDENTIFIER COLON expr` (`Param: $value`, canonical) or `VARIABLE EQUALS expr` (`$Param = …`) — not IDENTIFIER EQUALS. The emitted form failed to re-parse, breaking the DESCRIBE roundtrip for any widget action passing microflow parameters. Emit the canonical colon form in extractMicroflowParameters / extractNanoflowParameters. Flip the two roundtrip_page_test assertions that encoded the buggy `Param = $value` output. With this, `describe module ... with all` round-trips fully (0 parse errors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d02283e commit f12269d

3 files changed

Lines changed: 11 additions & 6 deletions

File tree

‎.claude/skills/fix-issue.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ to the symptom table below, so the next similar issue costs fewer reads.
3636
| `DESCRIBE` of a page/snippet emits `action: call_microflow X` / `call_nanoflow X` (button/widget actions) that fails to re-parse — breaks the DESCRIBE roundtrip | Action emitters prefixed `call_`; the page-action grammar (`actionExprV3`) accepts `MICROFLOW`/`NANOFLOW` only | `mdl/executor/cmd_pages_describe_output.go` (`extractButtonAction`) + `cmd_pages_describe_pluggable.go` (`extractCustomWidgetPropertyAction`) | Emit `microflow `/`nanoflow ` without the `call_` prefix. Issue #634 |
3737
| `DESCRIBE` of a Java action (or `describe module … with all`) emits a body-less `create java action …;` that fails with `no viable alternative` and cascades into following statements — happens for add-on/Marketplace actions whose `.java` source isn't on disk | Body emitted only when `readJavaActionUserCode` returns non-empty, but the grammar requires `AS DOLLAR_STRING` (body is mandatory) | `mdl/executor/cmd_javaactions.go` → `describeJavaAction` | Always emit the `as $$ … $$;` block; when source can't be read, write a placeholder comment body. Issue #637 |
3838
| `DESCRIBE` of a page emits `column Title (...)` / `column Description (...)` (datagrid columns named after a reserved keyword) that fails with `missing {IDENTIFIER, QUOTED_IDENTIFIER}` — breaks the DESCRIBE roundtrip | #619 added `mdlIdent` (quote-if-reserved) for general widget names but missed datagrid column names | `mdl/executor/cmd_pages_describe_output.go` (`column %s` header, ~line 837) | Wrap the column name: `fmt.Sprintf("column %s", mdlIdent(colName))`. Issue #638 |
39+
| `DESCRIBE` of a page/snippet emits widget-action microflow args as `Param = $value` that fails with `mismatched input '=' expecting ':'` — breaks the DESCRIBE roundtrip | Arg emitters used `=`, but `microflowArgV3` accepts `IDENTIFIER COLON expr` (`Param: $value`) or `VARIABLE EQUALS expr` (`$Param = …`) — not `IDENTIFIER EQUALS` | `mdl/executor/cmd_pages_describe_output.go` → `extractMicroflowParameters` / `extractNanoflowParameters` | Emit the canonical colon form: `paramName+": "+value`. Issue #640 |
3940
| CE3637 "A data view cannot listen to the selection of Gallery 'X', because it is not available here." on a master-detail page generated from MDL | Gallery's `itemSelectionMode` pluggable-widget property was hardcoded to `clear` in the def.json; Mendix requires `toggle` for selection-listeners (DataViews bound via `DataSource: selection X`) to see the gallery's selection | `sdk/widgets/definitions/gallery.def.json` | Change the `itemSelectionMode` mapping from `value: "clear"` to `source: "ItemSelectionMode", default: "clear"` so MDL can write `gallery X (Selection: Single, ItemSelectionMode: toggle)`. The V3 engine's generic mapping path (`widget_engine.go` `resolveMapping` default case → `GetStringProp`) reads the value automatically — no grammar changes needed. Also add `ForceFullObjects: false` to `Forms$ListenTargetSource` serializer in `sdk/mpr/writer_widgets_display.go` |
4041
| DESCRIBE drops `DataSource: selection X` for a DataView bound to a gallery/listview selection (master-detail pages) | `extractDataViewDataSource` only handled `Forms$MicroflowSource` / `Forms$NanoflowSource` / `Forms$DataViewSource` / `Forms$DatabaseSource`; `Forms$ListenTargetSource` fell through to `return nil` | `mdl/executor/cmd_pages_describe_parse.go` (`extractDataViewDataSource`) + `mdl/executor/cmd_pages_describe_output.go` (DataView case) + `mdl/executor/cmd_pages_describe.go` (rawDataSource doc-comment) | Add `case "Forms$ListenTargetSource":` returning `{Type: "selection", Reference: ds["ListenTarget"]}`; add `case "selection":` in the DataView output switch emitting `DataSource: selection <ref>` |
4142
| CE0463 "widget definition changed" on every pluggable widget that contains a caption/template parameter (gallery, datagrid2 captions, dynamictext with ContentParams) on Mendix 11.9 — cascades into CE3637 on master-detail pages | `serializeClientTemplateParameter` emitted `Forms$FormattingInfo` with a `TimeFormat: "HoursMinutes"` field, but the FormattingInfo reflection schema only declares CustomDateFormat / DateFormat / DecimalPrecision / EnumFormat / GroupDigits — the extra field made Studio Pro mark the embedded WidgetType as drifted | `sdk/mpr/writer_widgets.go` `serializeClientTemplateParameter` + `mdl/backend/mpr/widget_builder.go` (mirror copy of the same FormattingInfo block) | Drop the `TimeFormat` entry from both writers. Verify by diffing your BSON against a Studio Pro-saved page's FormattingInfo block — if you see keys outside the reflection schema, that's the trigger |

‎mdl/executor/cmd_pages_describe_output.go‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,9 @@ func extractMicroflowParameters(ctx *ExecContext, settings map[string]any) strin
11631163
}
11641164

11651165
if value != "" {
1166-
params = append(params, paramName+" = "+value)
1166+
// Canonical microflowArgV3 form is `Param: $value` (IDENTIFIER COLON expr);
1167+
// emitting `Param = $value` is IDENTIFIER EQUALS, which doesn't re-parse (#640).
1168+
params = append(params, paramName+": "+value)
11671169
}
11681170
}
11691171

@@ -1224,7 +1226,9 @@ func extractNanoflowParameters(ctx *ExecContext, action map[string]any) string {
12241226
}
12251227

12261228
if value != "" {
1227-
params = append(params, paramName+" = "+value)
1229+
// Canonical microflowArgV3 form is `Param: $value` (IDENTIFIER COLON expr);
1230+
// emitting `Param = $value` is IDENTIFIER EQUALS, which doesn't re-parse (#640).
1231+
params = append(params, paramName+": "+value)
12281232
}
12291233
}
12301234

‎mdl/executor/roundtrip_page_test.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,8 @@ func TestRoundtripPage_MicroflowButtonWithParams(t *testing.T) {
557557
if !strings.Contains(output, mfName) {
558558
t.Errorf("Expected microflow name '%s' in describe output.\nOutput:\n%s", mfName, output)
559559
}
560-
if !strings.Contains(output, "Product = $Product") {
561-
t.Errorf("Expected 'Product = $Product' parameter mapping in describe output.\nOutput:\n%s", output)
560+
if !strings.Contains(output, "Product: $Product") {
561+
t.Errorf("Expected 'Product: $Product' parameter mapping in describe output.\nOutput:\n%s", output)
562562
}
563563

564564
t.Logf("Microflow button with params roundtrip successful:\n%s", output)
@@ -631,8 +631,8 @@ func TestRoundtripPage_MicroflowButtonWithCurrentObject(t *testing.T) {
631631
if !strings.Contains(output, mfName) {
632632
t.Errorf("Expected microflow name '%s' in describe output.\nOutput:\n%s", mfName, output)
633633
}
634-
if !strings.Contains(output, "Target = $currentObject") {
635-
t.Errorf("Expected 'Target = $currentObject' parameter mapping in describe output.\nOutput:\n%s", output)
634+
if !strings.Contains(output, "Target: $currentObject") {
635+
t.Errorf("Expected 'Target: $currentObject' parameter mapping in describe output.\nOutput:\n%s", output)
636636
}
637637

638638
t.Logf("Microflow button with $currentObject roundtrip successful:\n%s", output)

0 commit comments

Comments
 (0)