feat(mdl): SHOW / DESCRIBE BUILDING BLOCKS (read-only discovery) - #16
Merged
Conversation
Add read-only discovery for Mendix Building Blocks (Pages$BuildingBlock), mirroring the SHOW/DESCRIBE SNIPPET path. Building Blocks are the native "reusable widget composition" library; this surfaces them so a project's existing blocks can be discovered and inspected (the READ prerequisite for the Atlas design-system recipe work — INSTANTIATE/AUTHOR remain separate). - SHOW BUILDING BLOCKS [in module] — lists Qualified Name, Module, Name, Display Name, Platform, Category. - DESCRIBE BUILDING BLOCK Module.Name — informational output (doc block + metadata comments + widget tree). Read-only: not a re-executable CREATE, since Building Blocks can't be authored via MDL. Data layer: the storage $Type is Pages$BuildingBlock (per the generated metamodel), not Forms$BuildingBlock as the reader previously assumed — so ListBuildingBlocks now does a dual-type lookup (Pages$ first, Forms$ fallback), fixing a latent empty-result bug. parseBuildingBlock reads DisplayName / Platform / TemplateCategory scalars. The widget tree is read from the raw unit (GetRawUnit) as a top-level Widgets[] array — the same shape and reader logic as a Studio-Pro snippet — not from the typed parser. Grammar: new BUILDING / BLOCK / BLOCKS lexer tokens (added to the keyword rule so they remain usable as identifiers), plus showStatement / describeStatement alternatives. Wired through AST, visitor, executor dispatch, and the CLI describe registration (both $Type strings). Backend interface/impls unchanged (ListBuildingBlocks + GetRawUnit already existed everywhere). Tests: executor mock tests (list, module filter, describe-not-found) + a check-parseable doctype example. Docs: MDL_QUICK_REFERENCE + a syntax feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Surface Building Blocks in the SQLite catalog so they are queryable via `select ... from CATALOG.building_blocks` and listed by SHOW CATALOG TABLES. - New building_blocks_data table + full-snapshot view (tables.go), registered in Catalog.Tables() as CATALOG.BUILDING_BLOCKS. - buildBuildingBlocks() populates it (Id, Name, QualifiedName, Module, Folder, Description, DisplayName, Platform, Category, WidgetCount). WidgetCount is read from the raw unit's top-level Widgets array (full mode only). - ListBuildingBlocks added to the CatalogReader interface (*mpr.Reader already implements it). Deliberately NOT wired into widgets_data / the refs projection: a Building Block is a read-only copy-template (deep-copied onto pages with no live link), so it has no meaningful cross-reference edges — only a widget count. The SELECT path needs no grammar change (catalogTableName already accepts IDENTIFIER). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This was referenced Jul 24, 2026
Merged
ako
pushed a commit
that referenced
this pull request
Jul 28, 2026
Ledger finding #16: year() and month() were in the built-in function whitelist, so `mxcli check --references` passed, but Mendix has no such functions and the build then failed with CE0117. Remove both so the error is caught at check time; the correct approach is date formatting/parsing (parseInteger(formatDateTime($d,'yyyy'))). Flagged the sibling extraction names (dayOfYear/hour/minute/…) as unverified-and-likely-invalid in a comment rather than removing them blind — they need a Studio Pro build to confirm, and rejecting a valid function is worse than the current state. Test: TestFuncReturnKind_NoYearMonth. 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
…ibute-keyword hint (TraceOps #11/#12/#16) Three MDL ergonomics improvements, each verified against mxbuild 11.12.1 (`mx check` → 0 errors): #11 — a single-quoted string literal may now span multiple lines. STRING_LITERAL excluded `\r\n`, so a newline terminated the token ("missing END at …"). Dropped the newline exclusion; mxbuild accepts a multi-line String value. (A missing close-quote now spans lines — the standard multi-line-string trade-off.) #12 — a bare MDL keyword (`body`, `content`, `search`, `as`, …) may be used unquoted as a WIDGET name, matching attribute and placeholder names. The widgetV3 rule accepted only IDENTIFIER | QUOTED_IDENTIFIER; it now also accepts `keyword`, and the visitor reads `wCtx.Keyword()` so the name is preserved (previously the parse failed, or an accepted keyword name came out empty → CE7247 "name cannot be empty"). #16 — `alter entity … add <name>: <type>` without the `attribute` keyword gave an opaque "no viable alternative at input 'add<Name>'". enhanceErrorMessage now appends an actionable hint with the correct `add attribute <name>: <type>` form when the offending line is `add <word>:` and `<word>` isn't a real clause keyword (attribute/column/index/event/value/…); gated to the primary error. `make grammar` regenerates the parser (generated files are not committed). Tests TestMultiLineStringLiteral, TestKeywordWidgetName, TestAlterEntityMissingAttributeKeywordHint; repro mdl-examples/bug-tests/traceops-11-12-16-strings-names.mdl. 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.
Adds read-only discovery for Mendix Building Blocks (
Pages$BuildingBlock) — the native "reusable widget composition" library. This is the READ prerequisite for the Atlas design-system recipe work (seePROPOSAL_atlas_design_system.md); INSTANTIATE (USE BUILDING BLOCK) and AUTHOR (CREATE BUILDING BLOCK) remain separate follow-ups.Mirrors the existing
SHOW/DESCRIBE SNIPPETpath layer-for-layer.Commands
SHOW BUILDING BLOCKS [in <module>]— lists Qualified Name, Module, Name, Display Name, Platform, Category.DESCRIBE BUILDING BLOCK Module.Name— informational output: doc block (if any) + metadata comment lines + the widget tree. Read-only — deliberately not a re-executablecreate(Building Blocks can't be authored via MDL), analogous toDESCRIBE LAYOUT.select … from CATALOG.building_blocks— SQL querying over blocks; also listed bySHOW CATALOG TABLES.Notable: a latent reader bug fixed
The storage
$TypeisPages$BuildingBlock(per the generated metamodel), butListBuildingBlockspreviously queried onlyForms$BuildingBlock— so it returned empty on real projects. It now does a dual-type lookup (Pages$first,Forms$fallback), mirroring howListSnippetsfalls back. The widget tree is read from the raw unit (GetRawUnit) as a top-levelWidgets[]array — the same shape and reader logic as a Studio-Pro snippet — not from the typed parser.Wiring (all layers)
sdk/pages/pages.go(struct fields),sdk/mpr/parser_misc.go(scalar parse + correct$Type),sdk/mpr/reader_types.go(dual-type lookup).BUILDING/BLOCK/BLOCKSlexer tokens +showStatement/describeStatementalternatives. Added to thekeywordrule so they remain usable as identifiers (verified:create entity Sales.Block (Building: string)still parses). The catalog SELECT needs no grammar change (catalogTableNamealready acceptsIDENTIFIER).mdl/executor/cmd_building_blocks.go(list + read-only describe + raw widget reader), CLI describe registration for both$Typestrings.building_blocks_datatable + view (mdl/catalog/tables.go),buildBuildingBlocks()builder (builder_pages.go), registered inCatalog.Tables(), andListBuildingBlocksadded to theCatalogReaderinterface (*mpr.Readeralready implements it). Deliberately not wired intowidgets_data/the refs projection — a Building Block is a read-only copy-template (deep-copied, no live link), so it has no meaningful cross-reference edges, only aWidgetCount.PageBackendinterface/impls unchanged (ListBuildingBlocks+GetRawUnitalready existed everywhere).Tests & docs
building_blocksadded to the core-tables query test +CATALOG.BUILDING_BLOCKSto the Tables()-coverage test;mdl/catalogsuite green.mdl-examples/doctype-tests/36-building-block-examples.mdl.MDL_QUICK_REFERENCE.md+ asyntaxfeature entry.make grammar+go build ./...+go vet+gofmtclean;mdl/...andsdk/...suites green (incl. the grammar keyword-coverage test, which caught the missing keyword-rule entries — now fixed).Validation note
Resolved the
$Typeand widget-shape questions from the authoritative in-repo metamodel rather than a live dump (a blankmxcli newapp has no building blocks anyway). Real-project / Studio-Pro confirmation of the dual-type lookup and widget walk is the natural next validation step.🤖 Generated with Claude Code
https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4