Skip to content

fix(visitor): store text expressions with their whitespace - #692

Merged
ako merged 2 commits into
mainfrom
claude/nice-einstein-a74lz4
Sep 25, 2026
Merged

ako merged 2 commits into
mainfrom
claude/nice-einstein-a74lz4

Conversation

@ako

@ako ako commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Found while resolving §5.1 of docs/11-proposals/PROPOSAL_first_class_expressions.md (mendixlabs#750).

The bug

Four places stored an expression as text via ANTLR's ctx.GetText(), which joins the tokens without the whitespace between them.

  • What survives: literals, + and a lone $currentObject. So the common cases looked right, and no test caught it.
  • What breaks: a keyword operator fuses with its neighbours. The fused text was written into the model.

Measured by decoding the units on a copy of ako/TestApp (Mendix 11.14.0). check -p --references passed on all of it:

MDL stored before stored now
action: microflow GT.ACT(Flag: true and false) trueandfalse true and false
action: microflow GT.ACT(Mode: if true then 'a' else 'b') iftruethen'a'else'b' if true then 'a' else 'b'
send rest request … with ($OrderId = if $x then $id else 'none') if$xthen$idelse'none' if $x then $id else 'none'

contentparams values and a dynamic execute database query were affected the same way.

The fix

Evidence

  • Tests first: mdl/visitor/visitor_expression_source_text_test.go covers each site plus a comment case. Before the fix it failed with $aand$b, if$xthen'a'else'b' and if$xthen1else2. The single-token control $currentObject passed throughout.
  • Same run, fixed binary: the TestApp script now stores the values in the "stored now" column, and describe prints them readably.
  • Records: regression MDL mdl-examples/bug-tests/expression-text-keyword-operators.mdl, a finding in findings/mdl-visitor.jsonl, and a changelog entry under Fixed.

Found, not fixed here

  • describe microflow drops a send rest request's with (…) parameters. The binding is stored, but a round trip loses it. It's a separate describe gap.
  • not $a does not parse as an expression. It's a grammar gap.

Checks

make build, make test, make lint, make check-mdl and make check-findings pass after merging current main. mx check was not run, because there is no mxbuild in this environment. I'd expect CE0117 on the fused expressions it replaces.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P65SqmwwvbWdJVRwhYiMQw


Generated by Claude Code

Four places stored an expression as TEXT via ANTLR's ctx.GetText(),
which joins the tokens without the whitespace between them. Literals,
`+` and a lone $currentObject survive that, so the common cases looked
right; a keyword operator fuses with its neighbours, and the fused text
was written into the model:

  action: microflow GT.ACT(Flag: true and false)   -> "trueandfalse"
  action: microflow GT.ACT(Mode: if true then 'a' else 'b')
                                                   -> "iftruethen'a'else'b'"
  send rest request ... with ($OrderId = if $x then $id else 'none')
                                                   -> "if$xthen$idelse'none'"

Measured by decoding the units on a copy of ako/TestApp (11.14.0);
check -p --references passed on all of it. Also affected: contentparams
values and a dynamic `execute database query`.

expressionSourceText takes the author's text - whitespace kept, MDL
comments stripped - the same extraction the microflow expression sites
moved to for the comment-leak fix, which missed these four because they
live in page and REST code. ruleSourceText (the OData and widget
expression slots) now shares it, so a comment inside those expressions
is stripped too.

Tests failed first with the fused values (`$aand$b`,
`if$xthen'a'else'b'`, `if$xthen1else2`); the single-token control
`$currentObject` passed throughout. After the fix the same TestApp run
stores "true and false", "if true then 'a' else 'b'" and
"if $x then $id else 'none'".

Found while resolving PROPOSAL_first_class_expressions.md §5.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P65SqmwwvbWdJVRwhYiMQw
@ako
ako merged commit a2c0d00 into main Sep 25, 2026
15 checks passed
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.

2 participants