Skip to content

fix(mdl): refuse throw, float/currency/date and the parenthesised association; warn on unstored index names and enum-value docs - #724

Merged
ako merged 2 commits into
mainfrom
fix/706-silent-drops
Sep 26, 2026
Merged

ako merged 2 commits into
mainfrom
fix/706-silent-drops

Conversation

@ako

@ako ako commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Closes #706. Plan item 0.3 (the §2 silent drops) of PROPOSAL_mdl_beta_syntax_freeze.md, tracked in #714.

What was wrong

Before this change, each of these got ✓ Syntax OK and Check passed! from mxcli check, and was then lost or stored wrongly:

Form What happened Now
throw 'x'; no listener, so the statement vanished from the microflow error. The message points to raise error; inside an on error handler, or a Java action on the main flow
Amount: float / currency stored as String(unlimited), or Void as a microflow type error: use Decimal
Born: date stored as DateTime error: use DateTime (Mendix has no date-only type)
create association X (from A to B, type: referenceset, storage: table) every option dropped, so it was stored as a Reference with column storage error. The message rewrites the statement in the working form
/** … */ on an enumeration value read into the AST and never written warning MDL-ENUMDOC01
index name (index Idx on (…), add index Idx (…), create index Idx on E (…)) discarded warning MDL-IDX01

Design choices the ADRs did not settle

  • Errors when the model would be wrong, warnings when only text is lost. throw, the types and the association form each write a different model, so they are refused. An enumeration-value doc comment or an index name leaves a correct model and only loses text. Our own examples used enum-value doc comments in 56 places, and create index requires a name. Both therefore warn: through ValidateProgram, exec prints the warnings as well. Making them errors under an mdl 1; header can come later through the deprecation registry.
  • Refused from the parse tree; the grammar is not deleted. ADR-0010 R11 says grammar that can never succeed should be removed. But float, currency, date and throw are also accepted as keywords-as-identifiers. Deleting | FLOAT_TYPE from dataType would let Amount: float parse again as an enumeration reference named float, which is the same silent failure. The alternatives stay as rejection anchors with exact line:col errors. Proposal item 2.3 can delete them once a hint mechanism for removed syntax exists.
  • The type check is global. It runs on EnterDataType/EnterNonListDataType, which covers attributes, microflow parameters and returns, declare, constants and the service rules. It looks only at the direct token, so M.Currency and enumeration(M.Float) still parse (there is a control test for this).
  • Enum-value doc comment hint: use a -- comment, or the enumeration's own /** */.

Test plan (what I ran)

  • Tests written first and seen failing against unfixed code: mdl/visitor/silent_drops_706_test.go and mdl/executor/validate_unstored_text_test.go. Every rejection test has a control next to it (canonical association keeps ReferenceSet/Table, decimal/datetime/M.Currency still parse, the enumeration's own doc comment is stored, anonymous indexes and drop-by-columns do not warn).
  • Revert check for each fix. Disabling ExitThrowStatement, EnterDataType/EnterNonListDataType, the LPAREN branch of the association visitor, the validateIndexNames / validateEnumValueDocs wiring, or the index-name / value-doc capture makes the matching test fail. Restoring the fix makes it pass.
  • End to end: before the fix, mxcli check on a script with all six forms printed "Syntax OK (5 statements) / Check passed!". After the fix it gives four errors with the replacement spelling, and the two text-only forms give warnings.
  • Sweep: ran the old and new binaries' check over every file in git ls-files '*.mdl' and compared exit codes. Five example files depended on the dropped forms. They are fixed in the second commit; the widget demo's association now really is the ReferenceSet it declared.
  • make build, make lint and make check-findings pass. In make test, every package passed except mdl/backend/modelsdk, which hit Go's 10-minute default timeout (load average above 20, with several agents compiling on the same machine). Rerun alone with -timeout 40m it passes (ok … 660.9s). This change does not touch that package.
  • Finding appended to .claude/skills/fix-issue/findings/mdl-visitor.jsonl.
  • Not run in Studio Pro: nothing new is written. Every change is a refusal or a warning, or an example that now uses a form that was already supported.

Follow-ups (not in this PR)

  • ast.TypeDate and its writer, describer and diff branches are now unreachable from the parser and can be deleted.
  • A legacy constant of DataTypes$FloatType describes as type Float, which is now refused on re-exec. It used to become a String silently. If such models exist in the wild, describe should map it to Decimal.
  • The declared name on AutoOwner-style attributes (proposal §2 item 11) is covered by MDL022 and was not changed here.

🤖 Generated with Claude Code

ako and others added 2 commits September 26, 2026 21:07
… text

Five forms passed `check` and were then lost or stored as something else
(#706). Split by what is lost:

Refused in the visitor, with the working spelling in the message, because
the written model would be wrong:
- `throw <expr>` had no listener and vanished from the microflow.
- `float` / `currency` fell through to String (Void in a microflow);
  `date` became DateTime. Checked on EnterDataType/EnterNonListDataType,
  so every place a type is written is covered, and only the direct token:
  `M.Currency` and `enumeration(M.Float)` stay legal.
- `create association X (from A to B, type: …, storage: …)` read none of
  its options; a ReferenceSet was stored as a Reference.

Warned by check, because the model is right and only words are lost:
- MDL-IDX01: an index name (a Mendix index is anonymous).
- MDL-ENUMDOC01: a doc comment on an enumeration value.

The grammar alternatives stay as rejection anchors: the words are also
keywords-as-identifiers, so deleting them would let `Amount: float`
re-parse as an enumeration reference named float.

Closes #706

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… examples

The examples relied on the forms #706 refuses or warns about: enum-value
doc comments become `--` comments, `date` attributes become datetime, and
the widget demo's parenthesised association is written in the working
form — it now really is the ReferenceSet it always said it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ako
ako merged commit a44a97c into main Sep 26, 2026
17 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.

Silent drops: throw, float/currency/date types, parenthesised association options, enum-value docs and index names

1 participant