fix(building-blocks): modelsdk ListBuildingBlocks + exec-safe doctype example - #17
Merged
Merged
Conversation
The doctype integration harness (TestMxCheck_DoctypeScripts) execs each example on both engines, and 36-building-block-examples.mdl failed two ways: - modelsdk: `show building blocks` errored because the modelsdk backend's ListBuildingBlocks was an unimplemented stub. Implement it on *Backend (mprread over genPg.BuildingBlock + scalar metadata), mirroring ListSnippets, so SHOW/DESCRIBE BUILDING BLOCK work on the codec engine too. The widget tree still comes from the shared GetRawUnit, so read-only describe needs no more. - legacy (and modelsdk): the example `describe building block MyModule.LoginForm` errored "building block not found" — a fresh test project ships no building blocks, and DESCRIBE of a missing block correctly errors. Make the example exec-safe: keep the `show building blocks` statements (empty, no error) and show DESCRIBE + the CATALOG.building_blocks query illustratively in comments. Follow-up to the merged building-blocks feature (PR #16). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This was referenced Jul 24, 2026
ako
pushed a commit
that referenced
this pull request
Jul 28, 2026
Ledger findings #17–19: a `set $x = <expr>` value re-serialized from the AST silently corrupted the stored Mendix expression — `mxcli check` passed, `mx check` gave only a generic CE0117: - #17 a division's right operand lost its `$` (`$a / $b` → `$a/b`) - #18 a decimal literal lost its fraction (`2.0` → `2`), breaking Decimal - #19 a small decimal became scientific notation (`0.000001` → `1e-06`) shouldPreserveExpressionSource now keeps the raw source whenever the expression contains a `/` or a decimal literal (a `.` adjacent to a digit), mirroring the existing XPath-where handling — so the exact text survives instead of a lossy AST round-trip. (MDL division is `div`; `/` is the member-access separator, which is what caused the `$`-loss mis-parse — preserving source is the robust fix either way.) Test: TestShouldPreserveExpressionSource_DivisionAndDecimals; repro mdl-examples/bug-tests/ledger-17-19-expression-serialization.mdl. Symptom table updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 28, 2026
…ecimals Corrects the earlier ledger #17-19 fix, which over-broadly preserved raw expression source whenever it saw a '/'. In MDL '/' is the member-access separator (`$obj/Attr`), not division (that is `div`), so preserving on '/' source-froze every association-navigation path and regressed TestAssociationNavParsing. - shouldPreserveExpressionSource: drop the '/' trigger; keep the decimal-literal trigger (findings #18/#19 — `2.0`->`2`, `0.000001`->`1e-06` are genuine AST-serializer losses that raw-source preservation fixes). - New MDL045: walk the microflow expression tree for a BinaryExpr with operator '/' (`$Dec / 2`, `(...) / $x`) and reject with an actionable "use div" message, instead of silently writing an invalid expression that fails the build (CE0117). The bare `$a / $b` form degrades to a member path and is caught by `check --references`. Tests: TestShouldPreserveExpressionSource_Decimals (renamed), TestValidateMicroflow_SlashDivision. Repros: ledger-17-19 (passes) + ledger-17-slash-division.fail.mdl (MDL045). Skill + symptom-table updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 28, 2026
Re-test of PR #52 by the ledger project surfaced three gaps: - #17 (MDL045): the variable/variable division form `$Dec / $Dec2` was not caught — it parses as a member-access path, so the BinaryExpr walk missed it. The visitor now narrowly preserves source when a `/` is immediately followed by `$` (a real association path never has `$` after `/`, so legit navigation is untouched), and MDL045 flags a source-preserved AttributePathExpr whose `/ $` source matches (`exprIsSlashDollarDivision`). The `$` guard on the RHS is the reliable division-vs-navigation discriminator the tester suggested. - #25 (MDL047): the check only saw microflow `retrieve` constraints, so an association `= empty` in a page/widget datasource where-clause slipped through. Now `validateDatasourceXPathAssociationEmpty` inspects `DataSourceV3.Where` on every widget, sharing the detection via `xpathAssociationEmptyMatches`. - #27 (MDL-WIDGET15): the advisory false-positived on heading+subtitle pairs. Only `Text`/unset RenderMode is inline; H1–H6/Paragraph are block-level and do not concatenate. `inlineDynamicText` now excludes block modes, so a heading breaks the run. Tests updated (variable/variable division, page-datasource MDL047, heading exclusion). Repros: ledger-17-slash-division.fail.mdl (+ var/var form), new ledger-25-page-datasource-assoc-empty.fail.mdl. Symptom table refreshed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
MDL045 flagged `$a / $b` division only when it was the entire set-value expression. When the division was embedded in a larger expression — `$a / $b + 1`, `round($a / $b)`, `$a / $b * 100` — the `$a / $b` part degrades to a member-path AttributePathExpr nested under a BinaryExpr or FunctionCallExpr, and the check silently missed it (mxcli check passed but mx check fails with CE0117). Only the bare form and a chained `$a / $b / $c` were caught. Root cause: exprIsSlashDollarDivision matched only when the source-preserved SourceExpr *directly* wrapped an AttributePathExpr, so a division nested one level down slipped through. Fix: replace it with exprHasSlashDollarDivision, which walks the whole expression tree for any SourceExpr and scans its raw source for a `/ $` (slash before a variable) using a string-literal-aware scanner. A real member/association path never writes `/$`, and the scanner skips `/$` inside quoted literals (e.g. 'path/$x') to avoid false positives. The division is now caught wherever it appears — in additions, multiplications, function arguments, return values, and if-conditions. Tests: TestValidateMicroflow_SlashDivision extended with embedded cases and the string-literal guard; ledger-17-slash-division.fail.mdl exercises the embedded forms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
…ute values (FINDINGS #17) An aggregate (sum/count/average/…) or unknown function used inside a `create` or `change` attribute value fails the build with CE0117, but `mxcli check` only inspected return/if/declare/set expressions — the same MDL044 check never reached attribute-assignment values, so `RowTotal = formatDecimal(sum($cells), '0.00')` passed check and failed MxBuild with a message that didn't even mention `sum`. Wired checkExprFunctions (MDL044) into the CreateObjectStmt and ChangeObjectStmt cases of the microflow body walk. Verified: `sum()` in a create attribute now reports MDL044 with the "assign the aggregate to a variable first" hint; legit functions (formatDecimal/trim) pass; full executor suite green. Test cases added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 30, 2026
…ze (TraceOps #9/#10/#17) Three page-builder defects found by the TraceOps project, each verified against mxbuild 11.12.1 (`mx check` → 0 errors after the fix): #9 — `dynamictext x (Content: '')` persisted as `Content: '{1}'` with no parameters (an orphaned placeholder) → CE0720 "Place holder index 1 is greater than 0". buildDynamicTextV3 unconditionally defaulted empty content to `{1}`. Now empty content with no params is a literal empty template; `{1}` is only synthesized when a parameter exists. #10 — `dynamictext s (Content: '$318')` was treated as a variable reference and became an unbound `{1}` param → CE0402/CE1613 ("attribute '$318' no longer exists"). A `$` starts a variable ONLY when followed by a letter/underscore (new isDynamicTextVariableRef / dynamicTextVariableRe); `$318` stays literal. #17 — `listview (… PageSize: 200)` always paged at 20: the property parsed into the AST but was ignored on write (buildListViewV3 hardcoded 20) and never read or emitted by describe. Now the write honors GetIntProp("PageSize"), the describe parse reads it, and the listview formatter emits a non-default value so it round-trips. Tests: TestBuildDynamicTextV3_{EmptyContent,DollarDigitLiteral,VariableStillBinds}, TestIsDynamicTextVariableRef, TestBuildListViewV3_PageSize. Repro mdl-examples/bug-tests/traceops-9-10-17-dynamictext-listview.mdl. Symptom rows added to fix-issue.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
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.
Fixes the CI failure after PR #16 merged:
TestMxCheck_DoctypeScripts/36-building-block-examples.mdlfailed on both engines.mx checkpassed (0 errors) — it was theexecstep in the doctype integration harness.Two root causes, both fixed
1. modelsdk:
ListBuildingBlocks not implemented yetThe modelsdk backend's
ListBuildingBlockswas an unimplemented stub, soshow building blockserrored on the codec engine. Implemented it on*Backend—mprread.ListUnitsWithContainer[*genPg.BuildingBlock]+ scalar metadata (Name, Documentation, DisplayName, Platform, TemplateCategory) — mirroringListSnippets. The widget tree still comes from the sharedGetRawUnit, so read-only DESCRIBE needs nothing more. Both engines now list building blocks.2. legacy (and modelsdk):
building block not found: MyModule.LoginFormThe example
described a specific block that doesn't exist in a freshly-created test project — and DESCRIBE of a missing block correctly errors. Made the example exec-safe: it keeps theshow building blocksstatements (empty result, no error) and showsDESCRIBE BUILDING BLOCK …+ theselect … from CATALOG.building_blocksquery illustratively in comments (they need a project that actually contains building blocks).Verification
go build ./...,gofmt, andgo vetclean.mdl/backend/modelsdk+mdl/executorsuites green; example passesmxcli check.show building blockson legacy and modelsdk) are now both error-free; the failingdescribe-of-a-missing-block is gone.Follow-up to #16 (the merged building-blocks READ feature).
🤖 Generated with Claude Code
https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Generated by Claude Code