Skip to content

fix: store a quoted Editable expression as a conditional editability, and refuse what cannot be stored - #1568

Open
stagknee wants to merge 2 commits into
mendixlabs:mainfrom
stagknee:fix/quoted-editable-expression
Open

stagknee wants to merge 2 commits into
mendixlabs:mainfrom
stagknee:fix/quoted-editable-expression

Conversation

@stagknee

Copy link
Copy Markdown
Contributor

Closes #1567.

What it fixes

Editable: '$currentObject/Locked = false' on an input widget passed check and exec, and was stored as Editable: Always with no condition, so a field meant to be locked stayed editable. The quoted Visible: next to it was kept. Editable: false on an input widget was dropped the same way, because the builder read the value only as a string.

How

One rule now covers both keys: a string that isn't a plain value of the property is its condition.

  • StaticEditability (sdk/pages) is the Editable counterpart of StaticVisibleExpression:

    • Always, Never and Conditional (any case) map to the enum;
    • true/false map to Always/Never;
    • any other string is the condition.

    The page builder (applyConditionalSettings) and the pluggable-widget path use it. A list view and a grid column keep their plain boolean Editable (MDL-WIDGET20 falsely warns that Editable is dropped on listview and column — it is written ako/mxcli#510).

  • Check parity. A quoted condition now gets the same checks as the bare one: MDL-WIDGET13 (association step), MDL-BUTTON02, MDL-WIDGET20 and MDL-WIDGET41. MDL-WIDGET31 treats editable: false as Never.

  • New refusal (MDL-WIDGET19, error). Check now refuses an Editable: value that exec can't store, where before it was silently ignored. The message names the accepted spellings. It covers:

    • a lone word such as 'Neever' or ReadOnly;
    • quoted text that doesn't parse as an expression;
    • Conditional with no condition.

    This is a behaviour change: a script that relied on one of these being ignored now fails check. The docs had shown Editable: ReadOnly as valid, so they are corrected to Never.

  • alter page … set (Editable: '<expr>') still refuses a non-enum string with its existing message, before anything is written. replace and insert rebuild through the builder and are fixed.

  • Docs: pages.md, widget-types.md, alter-page.md, create-page.md and mxcli syntax page.

  • Also included: a CHANGELOG entry (Fixed), a finding in findings/mdl-executor/, and the regression scripts mdl-examples/bug-tests/1567-quoted-editable-expression.mdl and a .fail.mdl negative companion.

Evidence

  • Control run: with the tests in place and the production code at main, 11 test functions fail, each for the intended reason. For example, the quoted widget is stored ("Always", ""), Editable: false is stored Always, and MDL-WIDGET19 is silent on Neever. All pass with the fix. The controls pass both ways: enum words, Visible unchanged, and list-view/column booleans.

  • Real run (Mendix 11.12.5 scratch app), stored values:

    Widget v0.26.0 this branch
    checkbox, Editable: '$currentObject/Locked = false' Always / no condition Conditional / $currentObject/Locked = false
    textbox, same Always / no condition Conditional / same
    textbox, Editable: false Always Never
    checkbox, Editable: 'Never' Never Never
    checkbox, unquoted expression Conditional / expr unchanged
    • The stored widget BSON for the quoted spelling is the same as for the unquoted one, with ids stripped.
    • Re-running the describe output reports Unchanged page, and mx check reports 0 errors.
    • alter page … replace/insert and create snippet store the same condition.
  • check over all 891 mdl-examples scripts: the main binary and this branch give identical pass/fail results, apart from the new .fail.mdl, which fails check as designed.

  • Windows: go test ./mdl/executor/ ./sdk/pages/... shows the same 28 pre-existing failures as main (the sorted lists are identical). go vet and gofmt are clean.

  • Linux (golang:1.26.6-bookworm, ANTLR 4.13.2): make grammar build test check-mdl check-findings check-conformance check-migration-reference lint-go all pass.

Not in this PR

  • A data view stores its static editability from its own ReadOnly flag, which the builder never sets from Editable:. dataview (Editable: Never), false and true are all stored as Editability Always, on main and here. Only the condition is carried. That's a separate silent drop in the same family, and I can file it.
  • A quoted Visible: still gets no syntax check, MDL-WIDGET13 or MDL-BUTTON02. This PR only brings Editable up to Visible.

🤖 Generated with Claude Code

stagknee and others added 2 commits October 17, 2026 09:00
…itability

`Editable: '$currentObject/Locked = false'` on an input widget passed check,
exec said "Created page", and the widget was stored `Editable: Always` with no
ConditionalEditabilitySettings, so a field meant to be locked stayed editable.
`Visible: '<expr>'` was stored as a conditional visibility: its consumer
(pages.StaticVisibleExpression) returns any other string as the condition, while
Editable's (pages.CanonicalEditability) knew only Always|Never|Conditional and
the builder skipped every other string without a word.

New pages.StaticEditability is the Editable counterpart: an enum word, a
boolean (false is Never, true is Always) or, for any other string, the
condition. A list view's and a grid column's Editable stays their own plain
bool. check now refuses what still cannot be stored (a misspelt word, a
quoted text that is not an expression, `Conditional` with no condition) as
MDL-WIDGET19 naming the accepted spellings, and a quoted condition gets the
checks the bare one gets (MDL-WIDGET13, MDL-BUTTON02, MDL-WIDGET41,
MDL-WIDGET20). describe prints the stored condition bare, so describe -> exec is
stable. ALTER PAGE set (Editable: '<expr>') keeps its loud refusal.

Control: same script on the pre-fix binary stores Always/null for the quoted
widgets; with the fix they are byte-equal (ids stripped) to the bare spelling
and mx check reports 0 errors on Mendix 11.12.5.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…r pluggable and data view

Follow-up to the quoted Editable expression fix. MDL-WIDGET31 still tested the
raw string for "Never", so an input marked `editable: false` (now Never) in a
read-only list view kept earning the warning that tells it to mark itself
Never; it reads the same resolved value as the builder now.

Tests added for the shapes a review asked about: a pluggable widget that
declares Editability is refused the same unstorable values by MDL-WIDGET19, and
a data view carries the quoted condition exactly as the bare one (its static
Never/Always is stored from its own ReadOnly flag, which this change does not
touch). CHANGELOG, finding record updated to match.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

AI Code Review

Critical Issues

None found.

Moderate Issues

None found.

Minor Issues

None found.

What Looks Good

  • Issue Resolution: The PR correctly fixes the core problem where quoted Editable: expressions and boolean values were being dropped/stored incorrectly. The solution introduces a unified StaticEditability function that handles enum words, booleans, and condition expressions consistently with Visible: handling.

  • Full-Stack Consistency: Changes are properly layered through the pipeline:

    • Grammar: No changes needed (existing slot reused)
    • AST: No changes needed (existing property structure)
    • Visitor: Added ParsesAsExpression helper for validation
    • Executor: Updated page builder (applyConditionalSettings) and validation logic
    • Documentation: All relevant docs updated (pages.md, widget-types.md, etc.)
    • DESCRIBE roundtrip: Verified via new test (TestQuotedEditableExpression_DescribeRoundTrip)
  • Test Coverage: Excellent test additions including:

    • New comprehensive test file (widget_editable_quoted_expression_test.go -

Automated review via OpenRouter (Nemotron Super 120B) — workflow source

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A quoted Editable: '<expression>' on an input widget is silently dropped: the field stays editable

1 participant