Repository navigation
Sync ako/mxcli: splices keep stated positions (#1598), ALTER PAGE object-list items (#1453), view-association check (#1611) - #1637
Merged
Merged
Conversation
`create or modify` pairing a new `if` and a restated one against the same
stored decision weighed "the same if but for its condition" exactly like
"the same if with a change in a branch", and lcsStatements breaks a tie
toward the earlier pair. So in
if $Out then …; end if; -- new, no @position
@position(-299, 200)
if $Flag then …; end if; -- restated, branch edited
the new `if $Out` took over the stored decision (its condition set in
place) and the restated `if $Flag` was inserted as a new node at its stated
position, on top of it: two decisions at (-299, 200), both merges at
(186, 200).
The weights are doubled and a changed condition now weighs 1, below every
other partial match, so the restated if pairs with its stored decision and
the new one is an insert. Every other ratio is unchanged.
Part of #1508 case 6 (mendixlabs#1598).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A `create or modify` that inserts statements without @position into a flow whose later statements state theirs made room by moving everything past the gap along. The stored flow then said something other than the script: in #1508 case 6 `if $Flag` went -299 -> 40, its merge 186 -> 525 and the return 530 -> 869, while the calls replaced in its branch — placed at their own stated positions, never shifted — stayed at (-124, 100) and (60, 100), left of their decision. Re-running the script was refused (the @merge no longer matched), and shifting "consistently" cannot fix that: the next run must move the nodes back. Under mdl 1 every point the script states a node at — @position, @merge, @start, a note's position:, a parameter's @position; loop bodies skipped, their coordinates are relative — is pinned on the mutator (MicroflowMutator.Pin), and a make-room shift (an insert, or a replace longer than what it replaces) that would move a pinned node is refused, naming the room it needs and the node in the way, with the two ways out: state @position on the new statements, or leave the positions after them unstated so they can move along. Pinning is by point, so a node a placed fragment puts at its stated position is pinned too. mdl 0 is unchanged (ADR-0011): there the refusal would fall back to the whole-flow rebuild, losing the merges, curves and $IDs the shift keeps — TestFlowModify_InsertIsSpliced, ADR-0012's headerless describe+insert acceptance test, caught exactly that. Fixes #1508 case 6 (mendixlabs#1598). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
versions.md enumerates what `create or modify` refuses under mdl 1 where mdl 0 rebuilds; add the insert that needs room past a node the script places. The review command gains the pattern that #1508 case 6 hit: a new splice refusal changes mdl 0 into a rebuild unless it is gated on the language version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shift moved every top-level node past the cut, and a parameter is a top-level object of the stored object collection: one if/else inserted into NF_Do moved `$Flag` from its derived (200, 53) to (539, 53), a longer replace then to (699, 53), and from then on describe printed a parameter @position no script stated. mxcli's derived parameter row is absolute and right of the start event, so almost every insert's cut falls left of it. A parameter is not on the line the room is made on. Studio Pro authors draw it above the start event — 63 of 71 in PedApp and JTSBootLogboek sit at the start's x, none within 60px of the flow line — and an insert in Studio Pro moves nothing. shifted() now leaves parameters out, and with it pinnedPast, so a stated parameter position no longer blocks a splice it is not in the way of. Fixes #1547. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ters fix: a splice making room leaves the flow's parameters where they are (#1547)
bodyItemSlotKey (content, else the first widget slot) decides where an item's loose children go for CREATE and DESCRIBE. ALTER PAGE is about to need the same answer for a bare item address (`acc1 item@1`), and the page mutator cannot import the executor, so the rule moves to mdl/types beside WidgetSlotKeyword. No behaviour change; the executor name stays as a thin alias. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
alterTarget's two `item` alternatives gain `(DOT itemSlot=identifierOrKeyword)?`. The visitor carries the slot as WidgetRef.Column, the way `grid.controlbar` carries a widget's slot, so every operation and the alter-target resolver receive it as the dotted member they already understand. The slot is taken off the identifiers before the selector is read: `item@1.headercontent` has two identifiers, the shape `item(t1)` was recognised by, and the first version of the test read it as `item(headercontent)@1`. PROPOSAL_alter_object_list_item_address.md step 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
An Accordion group (any CustomWidgets$WidgetObject item) stores no Name,
so `insert into grp1 { … }` never resolved, and an empty group could not
be filled at all (#1326, mendixlabs#1453). Before:
insert into acc1 item@2 { … }
-> acc1 item@2: "acc1" is a CustomWidgets$CustomWidget, not a navigation list
The navigation-list item address now reaches object-list items too:
insert into acc1 item@2 { … } -- the item's body slot
insert into acc1 item('One') { … } -- by its text (headerText)
insert into acc1 item(btnIn) { … } -- the item holding a widget
insert into acc1 item@2.headercontent { … } -- another slot
replace / drop acc1 item@1.content -- swap / empty a slot
drop acc1 item@2 -- remove the item
set (headerText: 'First') on acc1 item@1 -- an item property
- resolveObjectListItem finds the widget's one object list (refusing,
by name, a widget with several), matches by held widget, by
TextTemplate/String text, or by position, and shares @n, the
ambiguity and the miss messages with navigation lists (pickItem).
- The result carries the item schema, so SET reuses the column setter
and `item.slot` reuses the pluggable-slot code from #1462.
- The body slot is types.BodyItemSlotKey, the slot CREATE and DESCRIBE
use.
- BEFORE/AFTER an item, and REPLACE of a whole item with widgets, are
refused with the form that works: adding a new item is not part of
this change, and widgets written into an item list are the #935
unloadable shape.
Control: the new tests fail on main with the refusal above. Fixed, on a
blank 11.13.0 app (Accordion inside a data view) the four statements
apply, describe shows each widget in its slot, the text box binds to
the data view's attribute, and mx check reports 0 errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
…om its target (CE8812, mendixlabs#1611) A view entity's association, derived from an `<alias>.ID as <Name>` OQL column, is one-way for a page. A data source that follows it from the entity it points at passed check --references and exec. One example: `DATABASE FROM $currentObject/M.Stats_Owner/M.Stats` on a page over M.Owner. mx check then failed with CE8812 "Entity 'M.Owner' has no association 'M.Stats_Owner'". MDL-ASSOCDS02 (validate_view_assoc_reverse.go) runs in the attribute-scope walk beside MDL-ASSOCDS01. It follows the association or `database from` path hop by hop from the widget's context entity, and reports the first hop that follows a view association from its TO end. The hint is the query that builds: DATABASE <View> WHERE [<Assoc> = $currentObject]. The association index now carries a view flag, from Source == OqlViewAssociationSource. A script's view associations were known to no checker, so that same remedy was refused as naming "neither an attribute nor an association" when the view entity came from the same script. This was true on a page and in a microflow retrieve, both of which build at 0 errors. scriptContext.recordViewAssociations now registers each view association column the way a CREATE ASSOCIATION is registered. Measured on 11.14.0, one page per shape, with uniquely named widgets: - CE8812 for a list view, data grid, gallery and data view, in the database and in-memory forms, and as a second hop. - 0 errors from the view side, for the constrained query, for a persistent association reversed, and for a microflow association retrieve. - check now reports exactly the six refused shapes, and nothing else. - The bug-test file gives 0 errors from check and from mxbuild. With its data source switched to the reverse: MDL-ASSOCDS02 from check, CE8812 from mxbuild. Control: with checkViewAssocReverse unhooked, the 7 refusal cases fail with no error reported. Before the registration fix, the remedy test failed on both the page and the microflow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT
…n-String literal (CE0117, mendixlabs#1611) `column (Attribute: IsActive) { dropdownfilter ddf (defaultValue: 'true') }` passed check and exec, then mx check failed with CE0117 "Error(s) in expression.". The filter's defaultValue is an Expression property that returns a String. A quoted MDL value on an expression property is the expression's text, so 'true' stored the Boolean expression `true`. The writer follows the convention that describe prints and every expression property relies on. What was missing is a check of the expression against the property's declared return type. MDL-WIDGET49 (validate_widget_expression_return.go) runs beside MDL-WIDGET42. On a String-returning Expression property it refuses a value that is a literal Boolean, Integer or Decimal (exprcheck.InferSourceKind), or a single bare name. The hint gives the String literal: `defaultValue: '''true'''`. The embedded schema now records each Expression property's ReturnType. A value that infers no kind is left alone (an attribute path, a variable, an untyped function), and so is DateTime, which the inference gets wrong. It runs with and without a project. Measured on 11.14.0, one filter per value. CE0117: 'true', 'false', '1' (in a String and in an Integer column), '1.5' and 'abc'. Builds at 0 errors: '''true''', '''abc''', '''tru''', 'empty' and '''a'' + ''b'''. check now reports exactly the six refused values. The bug-test file gives 0 errors from check and from mxbuild as written; with defaultValue 'true', MDL-WIDGET49 from check and CE0117 from mxbuild. Control: with the check unhooked, the 6 refusal cases fail with no error reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT
…es them
Measured on a blank 11.13.0 app, project checked as stored
(`docker check --no-update-widgets`; the normalising default hides all
of these):
1. `insert into acc1 item@1.headercontent { … }` on a group whose
headerRenderMode is 'text' (the default) stored widgets the Accordion
hides: CE0463 at the Accordion. It is now refused, at check and at
exec, naming the property that shows the slot. A SET earlier in the
same statement can be what shows it, so check stands down then and
exec decides on the values after the SET.
2. `set (headerRenderMode: 'custom') on acc1 item@1` hid headerText and
left its template filled: CE0463. CREATE stores a hidden template
null (#1198), so the post-SET reset now nulls it.
3. `set (headerRenderMode: 'text')` on a group made in custom mode
revealed a null template: CE0463, and an empty one is CE4899. The
'Header' text CREATE writes lives in the widget package, not the
stored schema, so such a SET is refused unless it also sets
headerText; `set (headerRenderMode: 'text', headerText: 'Two')`
creates the template (Deps.SerializeClientTemplate, codec-built) and
writes the text.
The reset is ResetHiddenColumnProperties' pass, generalised to items;
templates are handled for items only, since the column case is not
measured. check's dry run now applies an item SET as a whole, as it does
for a column's.
Control: each new test fails before its change with the measured symptom;
on the app, scenarios 1-3 give 1 error before and 0 after (3 by refusal,
the project left unchanged), and set-then-insert gives 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
- alter-page reference and skill: `acc1 item@n` / `item('text')` /
`item(widget)` / `.headercontent`, the hidden-slot refusal and its fix,
and what is not supported (adding a new item).
- mdl-examples/bug-tests/1453-alter-accordion-group-item-address.mdl:
exec on a blank 11.13.0 app puts each widget in its slot and
`docker check --no-update-widgets` reports 0 errors.
- Proposal status -> partial, with what is done and what is not;
proposals index regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
…line budget TestLargeSkillsWereSplit refused the skill at 703 body lines after the item-address paragraph; it is now three lines, with the detail in the alter-page reference. The test-stub methods are gofmt-clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
feat(alter page): address Accordion groups and other object-list items
fix(executor): refuse a page following a view entity's association from its target (CE8812, mendixlabs#1611)
fix(executor): refuse a String-returning widget expression given a non-String literal (CE0117, mendixlabs#1611)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Syncs
ako/mxcli:maininto upstream: 12 commits from fork PRs ako#1569 (which carries ako#1548), ako#1613 and ako#1611.Fixes #1598: cases 1–5 landed in the previous sync, and this adds case 6. Refs #1453 (most of the proposal) and #1611 (part A).
Microflow splices keep what the script places (#1598 case 6)
create or modifyno longer moves a node the script places (mdl 1). Inserting statements without@positionused to make room by shifting everything past the gap.if $Flagwent from -299 to 40, its merge from 186 to 525 and the return from 530 to 869. The calls in its branch stayed at their stated positions, left of their own decision, so a re-run was refused.ifoutweighs a new one whose condition differs. Pairing used to tie "the same if but for its condition" with "the same if with a branch edit", and broke the tie toward the earlier pair.$Flagfrom (200, 53) to (539, 53), and describe then printed a parameter@positionno script had stated.ALTER PAGE: object-list items (#1453)
.slotsuffix:Name, soinsert into grp1 { … }never resolved, and an empty group could not be filled at all.docker check --no-update-widgets, because the default check normalises widgets first and hid all of these:customnulls the hidden header template. Before, the template stayed filled and gave CE0463.textis refused unless the statement also setsheaderText, in which case the template is created.mdl/types.BodyItemSlotKey, which CREATE, describe and ALTER now share. This is a refactor and is its own commit.check: view entity associations (#1611, part A)
check --referencesandexec, then failed mx check with CE8812 "Entity 'M.Owner' has no association 'M.Stats_Owner'".DATABASE M.Stats WHERE [M.Stats_Owner = $currentObject]is no longer falsely refused.defaultValue, is a separate PR.Validation
make build,make test,make lint,make check-mdlandmake check-findingspass.