Repository navigation
fix: a constant in an XPath constraint — parse it, refuse it (CE0161), stop losing it (#1685) - #1739
Merged
Merged
Conversation
…s it on re-render (#1685) `retrieve $Items from Shop.Item where [Total > @Shop.C_Limit];` failed with "mismatched input 'Shop' expecting ']'", which reads as a gap in MDL. Three silent losses sat behind it: a data source written `where Total > @Shop.C_Limit` stored `[Total > ]`; describe of a stored constraint holding a constant, on an entity with an enumeration attribute, printed `where Total > @;`; and a long one written in the quoted form was laid out and stored as `[Total > @]`. Cause: the XPath grammar had no constant. `@` was admitted by the negated xpathWord set as a one-word name, so the strict parse failed at the module name, and ParseXPathConstraint (error listeners off) recovered past it and returned ok with an attribute called "@" — every re-render of that parse (enum enrichment, FormatXPathConstraint, check's member walk) dropped the constant. The page-side xpathExprToString had no ConstantRefExpr case and rendered "" for the expression-grammar form. The issue expected the constant to be stored and built. Measured, mxbuild rejects it: on 11.13.0, each case alone in a fresh app, CE0161 "Error(s) in XPath constraint." for an Integer, String and Boolean constant in a retrieve, in a list view's database source, in an access rule (production security — with security off mx check validates no access rule, a garbage `[Total >]` passes) and in a user task's targeting; an unknown constant is the same CE0161, not CE1613. The retrieve is CE0161 on 11.15.0 too. The control, `declare $Limit Integer = @Shop.C_Limit;` then `[Total > $Limit]`, is clean. Fix: `@Module.Name` is an xpathValueExpr (xpathConstantRef — a value, not a path step) and AT is out of xpathWord; the visitor builds ast.ConstantRefExpr and the page renderer prints it, so every slot stores the constraint as written and describe prints it back. `mxcli check` (ValidateProgram, so exec too; no project needed) refuses a constant in any XPath slot as MDL-XPATH03 with the variable workaround; an excluded flow warns. walkXPathConstraints gains a sibling that names the slot. Verification: visitor, check and executor tests; the PedApp test writes the constraint into a retrieve, a list view and an access rule, describes all three back, re-executes the descriptions with no file changed, and renames the constant through them ("Updated 3 reference(s)"). Reverting the grammar fails every test with the reported parse error and `[Total > @]`; reverting only the renderer case gives `[Total > ]`; stubbing the check fails the refusal tests. Real 11.13.0 app: baseline describe printed `where Total > @;` for both retrieves, fixed describe prints the constraints and describe -> exec reports 5 documents in sync; `rename constant` updated 5 references in 4 documents, and mx check is the same five CE0161 before and after the rename with the variable control clean. TestMxCheck_DoctypeScripts passes for the microflow, nanoflow, page, security, xpath, workflow and offline-sync scripts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Closes #1685. Investigated #1297 (mirror of mendixlabs#1281): already fixed on main by cd93d84 — evidence below, no change.
#1685 — a constant in an XPath constraint: a parse error, and silently lost on re-render
The issue's expected outcome was wrong. It asked for
@Module.Constantto be stored as a working XPath value. Measured withmx check, Mendix rejects a constant in an XPath constraint in every slot (CE0161): Integer, String and Boolean constants in a retrieve; a list view database source; an access rule (measured under Production security — with security Off mx check validates no access rule at all); a user task's targeting. An unknown constant is the same CE0161, not CE1613 (XPath never resolves the name). 11.15.0 agrees. Control:declare $Limit Integer = @Shop.C_Limit;then[Total > $Limit]builds clean. So this PR makes the form parse, and refuses it with the workaround — rather than a parse error atShop, or a silent loss.What failed on main:
mismatched input 'Shop' expecting ']'.where Total > @Shop.C_Limitstored[Total > ]; a stored[Total > @Shop.C_Limit]described aswhere Total > @;; a long quoted constraint under--no-checkstored[Total > @]. Cause: the lenient re-parse (ParseXPathConstraint) returned ok with an attribute named@, and the page renderer had no constant case.Fix:
MDLPage.g4):xpathConstantRef : AT xpathQualifiedNameas an alternative ofxpathValueExpr— a value, never a path step;ATremoved fromxpathWord, so[Name = @]is now a syntax error. No existing XPath form changed meaning (visitor, xpathrefs, executor, conformance, linter, catalog, syntax packages pass).buildXPathConstantRef(nil-safe on a recovered parse); page renderer caseConstantRefExpr.validate_xpath_constants.go, inValidateProgram): plaincheckandexecrefuse a constant in an XPath slot without a project, naming the slot (walkXPathSlots) and the variable workaround; an excluded flow gets a warning.Verified: visitor and validator tests, and a PedApp end-to-end test writing the constraint (via the executor, past the refusal) into a retrieve, a list view and an access rule, describing all three back, re-executing with no file changed, then
rename constant— "Updated 3 reference(s)" (the rename-through-XPath test #1673 could not have). Reverted: grammar → the parse error and[Total > @]; renderer only →[Total > ]; check stubbed → every refusal test fails. Real 11.13 app: check and exec refuse with MDL-XPATH03;--no-checkstores every slot verbatim; describe now prints the constraints and describe → exec is "5 documents already in sync";rename constant"Updated 5 reference(s) in 4 document(s)" (mx check is the same 5× CE0161 before and after, as the measurement says).TestMxCheck_DoctypeScripts02, 02b, 03, 08, 16-xpath, 24, navigation-offline-sync pass.#1297 — two predicates on one XPath step: already fixed on main
Fixed by cd93d84 ("accept consecutive predicates on one XPath step", bug-test
1281-consecutive-xpath-step-predicates.mdl); the upstream reporter confirmed it fixed in v0.26.0. With the baseline binary (aa97a0a) on a fresh 11.13 app,checkpasses and these all exec and describe identically: the issue's two shapes (path continues after the step / ends on it), a page data source, an access rule, three predicates on a step, a nested two-predicate step, insidenot(), sibling groups; describe → exec "5 documents in sync"; mx check 0 errors including under Production security. Only the removed quoted grant formwhere '[…]'still fails, unrelated to predicates.All
Full
go test ./...,go vet, gofmt; CI's doc checks pass locally. Bug-testsxpath-1685-constant-in-constraint.fail.mdl,xpath-1685-constant-through-variable.mdl; doctype section in16-xpath-examples.mdl; finding recorded; xpath-constraints skill,MDL_QUICK_REFERENCE.md,mxcli syntax xpath, docs-siteactivity-types.md. Not verified: Studio Pro's UI; offline sync constraints (refused by the same rule, not measured).Noticed, not fixed
TestMxCheck_DoctypeScriptstolerates CE0161 globally (roundtrip_doctype_test.go~417, "XPath serializer limitation") — the corpus cannot catch a CE0161 regression.doctype-tests/navigation-offline-sync.mdlis CE0161 at PhoneOffline on main too (hidden by that allowance; likelycontains(Name, 'ab')in a sync constraint).doctype-tests/16-xpath-examples.mdlhas a stale TODO saying nested predicates are unsupported.CATALOG.REFSedge (moot now that it is refused).🤖 Generated with Claude Code