R8: page actions as words, one spelling per keyword, lowercase keywords (#752) - #773
Merged
Merged
Conversation
…vision (#768) `/` shares a precedence level with `*`, `div` and `mod`, so `$a/X * $b/Y` parsed as `(($a/X) * $b) / Y` and was stored as `$a/X * $b / Y` (and, in a list filter, `$b / $currentObject/Y`). When a `/ Member` step cannot attach to the whole left side, attach it to the last operand of the preceding multiplicative expression. Mendix has no `/` division. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… ({n} = e)) (#751)
Every call site binds an argument as `Param = expression`: call
microflow/nanoflow/java/javascript/external action, web service, execute
database query, send rest request, show page, and page/button actions and
flow data sources. A workflow's call microflow / call workflow takes its
arguments right after the callee as bare expressions. show message and
validation feedback take `with ({1} = e)`.
The old spellings stay as registered deprecated aliases with fmt --upgrade
rewrites computed from the parse tree:
MDL-DEPR006 $Param = e
MDL-DEPR007 Param: e
MDL-DEPR008 workflow `with (Param = '<expr>')` (same meaning: the
string's content is the expression)
MDL-DEPR009 objects [..] / parameters [..]
describe writes the canonical forms, and now also writes a validation
feedback's template arguments, which it dropped. A stored workflow
expression that does not read back as itself when bare keeps the string
form in describe.
Skills, docs-site, the quick reference and `mxcli syntax` are migrated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Page actions use the words a microflow uses: show page, save changes, cancel changes, close page, create object, delete, open link, sign out, complete task, call microflow, call nanoflow. A rule's message is `error message '…'` everywhere, an association's delete behaviour is `on delete …`, the many-to-many type is ReferenceSet and a REST call that ignores its response `returns nothing`. describe writes these. Every old spelling keeps parsing with the same meaning and is a registered deprecated alias with an fmt --upgrade rewrite: MDL-DEPR020 (snake-case page actions, a flow call without `call`, a menu item's sign_out), MDL-DEPR021 (error / feedback / error_message), MDL-DEPR022 (delete_behavior), MDL-DEPR023 (reference_set) and MDL-DEPR024 (returns none). `delete_object close_page`, which describe printed but the grammar refused, now parses. Refs #752 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
formatter.Format upper-cased every word on a keyword list, names included: Issue64.User became Issue64.USER and an attribute Title became TITLE, so fmt changed what 374 of the example scripts build. It now lowercases only the tokens the parse tree shows are keywords, and keeps a property key, a name, a CamelCase or digit-bearing value, a data type and an annotation as written. Text the model stores as written (expressions, XPath, OQL, catalog and SQL queries, template parameters, multi-line literals) keeps its case and its layout. TestFormatterKeepsMeaning replaces TestFormatterChangesMeaning: every example script formats to one that builds the same statements. describe writes lowercase keywords where it did not: an enumeration's `folder`, a workflow's `default ->` outcome and a published REST operation's method. alter settings keeps the section lowercase in the AST, so its keyword case no longer changes what a script builds. TestPedApp/TestAppDescribeUsesCanonicalSpellings pin describe to the R8 spellings and lowercase keywords. Refs #752 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (R8) Skills, docs-site, mxcli syntax and the quick reference write the R8 spellings: page actions as words, `call microflow`, `error message`, `on delete`, ReferenceSet, `returns nothing`. The catalog's `show_page` reference kind is a data value and is left alone. Refs #752 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in/end while under mdl 1 (#754) R2 (ADR-0010): braces hold declarative children, imperative flow is `begin … end <keyword>`. The custom error handler was the only brace block inside a microflow: - grammar: `on error [without rollback] begin … end error` is canonical; the brace form stays as an alias marked MDL-DEPR540, which builds the identical handler and has a structural fmt --upgrade rewrite (`{` -> begin, `}` -> end error), nested handlers included. - describe microflow/nanoflow, the commented-out handler fallback, handle targets and the generated `mxcli test` flows emit the canonical form. - `while` without `begin` or ending in a bare `end` is a new rejection gated on `mdl 1` (MDL-V1-WHILE); under mdl 0 it keeps parsing, warns, and `fmt --upgrade --header` inserts the missing words. - The PedApp describe check now also refuses any deprecated spelling in describe output (control: with the old emitter it reports MDL-DEPR540 on the Studio Pro-authored handlers). - mdl-examples, skills, docs-site, quick reference and `mxcli syntax` migrated to the canonical spellings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… phrases read as nouns (#751) The E001 hint's Right example, the control-bar selection suggestion, the microflow help text and the vega-charts skill pack still wrote an argument as `$Param = e` / `Param: e`, the spellings MDL-DEPR006/007 now warn on. The four new registry Structural texts were verb phrases, so check printed "Rewrite the drop the `$` ...". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MDL-WIDGET28's suggestion, the under-specified keyword hints, the open link / show page argument errors, the fragment action-parameter error and the named action slot error still told the author to write SAVE_CHANGES, SHOW_PAGE, OPEN_LINK, MICROFLOW M.F, ... -- the spellings #752 deprecates. They now name the words. `complete task` without an outcome gets the same named hint as `complete_task`. The page.action syntax entry no longer claims `Action: OPEN LINK` without a URL is MDL-WIDGET28: the word form is a syntax error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # .claude/skills/mendix/write-microflows/SKILL.md # CHANGELOG.md # mdl/deprecation/deprecation.go
# Conflicts: # .claude/skills/mendix/cheatsheet-errors/SKILL.md # .claude/skills/mendix/create-page/reference/widgets.md # .claude/skills/mendix/overview-pages/SKILL.md # .claude/skills/mendix/write-microflows/SKILL.md # CHANGELOG.md # cmd/mxcli/syntax/features_page.go # docs-site/src/appendixes/quick-reference.md # docs-site/src/language/data-binding.md # docs-site/src/language/widget-types.md # docs-site/src/reference/page/create-page.md # docs-site/src/tutorial/create-page.md # docs/01-project/MDL_QUICK_REFERENCE.md # mdl/deprecation/deprecation.go # mdl/executor/cmd_pages_describe_pageparams_test.go
… workflow args after the callee) 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 #752 (R8, phase 3.2 of the beta syntax freeze; tracking #714).
What changes
Page actions are the words a microflow uses —
show page,save changes,cancel changes,close page,create object … then …,delete,open link,sign out,complete task,call microflow M.F,call nanoflow M.F. The same inAction:,OnClick:,OnChange:, named action slots ('createFileAction': …),alter page … set, and a menu item'ssign out. Arguments are untouched (#751 owns them).One spelling per keyword
show_page,save_changes,cancel_changes,close_page,create_object,delete_object,open_link,sign_out,complete_task,microflow M.F,nanoflow M.Ferror message '…'(afternot null/unique/required, in a validation rule, afteron delete restrict,disallow concurrent execution)error '…',feedback '…',error_message,errormessageon delete cascade | restrict | set nulldelete_behavior …in all its spellings (incl. the three spellings each ofdelete_and_referencesetc.), alsoalter association … set delete_behaviorReferenceSetreference_setreturns nothingreturns noneEvery alias is marked in the grammar (
/* @alias MDL-DEPRnnn */), registered with Example/CanonicalExample (the registry test proves both build the same statements), and has anfmt --upgraderewrite that keeps the script's letter case.delete_object close_page, which describe could print but the grammar refused, now parses.Lowercase keywords are canonical; fmt no longer upper-cases names.
formatter.Formatupper-cased every word on a keyword list, names included (Issue64.User→Issue64.USER, attributeTitle→TITLE) and changed what 374 example scripts build. It now lowercases only tokens the parse tree shows are keywords (visitor.FormatSpans), keeping property keys (a keyword followed by:/=), names (anything reached throughkeyword/identifierOrKeyword/qualifiedName), CamelCase or digit-bearing values (ButtonStyle: Success,RenderMode: H2), data types and annotations. Text stored verbatim (expressions, XPath, OQL, catalog/SQL queries, template params, multi-line literals) keeps case and layout. describe now writes lowercasefolder, workflowdefault ->, and published-RESTget/post.Design choices the ADRs did not settle
r8Entries) so the merges do not collide. A gap in the numbering means nothing.save changes,cancel changes,sign out,complete task) are one lexer token admitting both spellings (WS+or_), likenot null; the underscore identifies the alias. Actions whose words are already tokens (show page,close page,create object,open link,call microflow) are token sequences inactionExprV3— a lexer-levelshow pagewould have brokenshow pages(longest match).returns nothingwins overreturns none: it is what describe already emitted (asNothing, now lowercase) and what the docs use.reference set): it is the Mendix type name describe writes, a value likeReference, not a keyword phrase.fmtcase rule: a CamelCase word is left as written, because that is how Mendix writes names and enumeration values; an all-caps or all-lowercase word is a keyword. This makesfmt(describe(x))a fixed point on PedApp and TestApp.ELSEIFis only a reserved token — no statement accepts it, so there is no second spelling to deprecate.NOT_NULLis a token name; its only spelling isnot null.ALLOW_CREATE_CHANGE_LOCALLY's optional underscores are what let the property keyAllowCreateChangeLocally:lex; theset allow_create_change_locally = …form belongs to R3/R4: one argument-binding form (Param = expr) and alter set ( Key: value ) everywhere (3.1) #751'salter … set ( Key: value ).alter settingsnow stores the section lowercase in the AST (the executor already lowercased it), so keyword case no longer changes the AST.Test plan (what I ran)
make build,make lint(Go + TS) — pass.go test ./mdl/visitor/ ./mdl/executor/ ./mdl/upgrade/ ./mdl/formatter/ ./mdl/grammar/ ./mdl/deprecation/ ./mdl/langver/ ./cmd/mxcli/...— pass.go test -tags integration ./mdl/roundtrip/(PedApp + TestApp round trip, allowlists, execute-both upgrade property test, describe: end every statement with ';', never print '/' (#744) #745 terminator test) — pass; no allowlist entries added.TestR8OldSpellingsAreAliases/TestR8PageActionWordsBuildTheirAction(visitor: 30 old/canonical pairs build identical statements, only the old records its code, each with a fix),TestUpgrade_R8Spellings(exact rewrites, case kept, idempotent),TestFormatterKeepsMeaning(replacesTestFormatterChangesMeaning: every mdl-examples script formats to one that builds the same statements, idempotently),TestPedAppDescribeUsesCanonicalSpellings/TestTestAppDescribeUsesCanonicalSpellings(integration: describe emits no R8 alias and no upper-case keyword).ExitActionExprV3stubbed →TestR8OldSpellingsAreAliasesfails 9 subtests ("recorded nothing").formatter/format.gorestored →TestFormatterKeepsMeaningfails on 374 scripts.folder→FOLDERandsave changes→save_changes→TestPedAppDescribeUsesCanonicalSpellingsfails (9 folder lines, 4 MDL-DEPR020 uses).TestRegistryExamplesRecordTheirCode) failed for all five new codes before the grammar/visitor change.mxcli fmtover a describe dump of every PedApp and TestApp document changes only whitespace;mxcli check/fmt --upgradeon a scratch script with named action slots andSHOW_PAGE.Follow-ups
Action:→OnClick:as the one on-click key (describe still writesAction:; §4 property-key convention).page M.P/microflow M.F→show page/call microflow— waiting on R2: three brackets, three meanings — integration documents, navigation/menus, on error, while (3.4) #754's navigation/menu bracket change to avoid a grammar collision.alter entity … set allow_create_change_locally = …→ R3/R4: one argument-binding form (Param = expr) and alter set ( Key: value ) everywhere (3.1) #751'sset ( AllowCreateChangeLocally: … ).🤖 Generated with Claude Code