Repository navigation
fix: templates with an expression and with(…); Java action javadoc and EXTRA CODE round trip (#1683, #1700, #1702) - #1736
Merged
Conversation
…urce text (#1683) `log info node 'P' $Msg with ({1} = 'x');` logged the literal text `$Msg`, and `send email (… Subject: $Subj with ({1} = '42') …)` sent the subject `$Subj`. `show message` and `validation feedback` stored the same statement as '{1}' with the expression and then the stated parameters, so 'x' became a {2} no placeholder reads and the message showed its own unfilled {1}. check, exec and mx check (0 errors, 11.13.0) passed all four. Cause: a message template is a text with {n} placeholders; an expression has none for `with (…)` to fill, and Mendix cannot store an expression as a template's text. addLogMessageAction and emailTemplate (mdl/executor/cmd_microflows_builder_calls.go) fell back to fb.exprToString(message) as the template text when parameters were stated; addShowMessageAction / addValidationFeedbackAction appended them after the expression's {1}. Nothing in check refused the shape. Fix: one decision, messageTemplateRefusals (mdl/executor/message_templates.go), refuses an expression followed by `with (…)` (or the deprecated `objects [...]`) on all four statements — the shape MDL-REST05 and MDL-JA02 refuse for REST calls and Java action arguments. The builders call it (exec, for microflows, nanoflows, rules and alter fragments alike), and check reports it as MDL-TEMPLATE01 from the microflow, nanoflow, alter-fragment and rule validators. Sibling on the same branch: a multi-line string-literal email Body with parameters arrives as a SourceExpr and stored its source, quotes included, as the template; it is now stored as the literal's value. Verification: message_templates_test.go covers check and exec on every statement with controls (a string template, an expression without `with (…)`), every flow kind, and the multi-line body; reverting the production change fails all refused cases and the body case. On a blank 11.13.0 app the baseline wrote the four flows (describe printed '$Msg' / '$Subj'; mx check 0 errors); the fix refuses them at check and at exec --no-check, nothing written. The controls build at mx check 0 errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oc (#1700) mxbuild writes a Java action's documentation as a javadoc block above `public class`. The file mxcli wrote never had it: a new action got none, and `create or modify java action` removed the one a build had written, so the next build put it back and every rewrite left a pair of unrelated VCS diffs. The model itself was intact. Mirror of mendixlabs#1653. Cause: GenerateSource (sdk/javaactions/source.go) took no documentation, and neither did backend.JavaBackend.WriteJavaSourceFile or its executor caller, although the executor had the documentation at hand. Fix: GenerateSource and WriteJavaSourceFile take the documentation; the executor passes ja.Documentation, the one the model ends up with, so a rewrite without a doc comment keeps the block. classJavadoc writes the block as measured on mxbuild 11.13.0 with documentation set straight in the model: `\r\n`, `\r` and `\n` each end a ` * ` line (so leading/trailing breaks give empty lines), whitespace is kept, whitespace-only documentation still gets a block, and a backslash is doubled unless `u`/`U` and four hex digits follow it. mxbuild refuses `*/` in the documentation as a model error. Mock, mcp and modelsdk stubs regenerated. Verification: 14 goldens from an mxbuild deploy build (testdata/mxbuild/JA_Doc*.java.golden, two of them generated from no file) are reproduced byte for byte; executor tests check the stated and the carried documentation reach the writer. Reverting the generator and the executor argument fails all of them except the no-documentation control. Real 11.13.0 app, 15 actions: after `create or modify` over mxbuild's files, 13 of 15 are byte-identical to mxbuild's with the fix (the other two differ only in the user-code padding mxcli has always written) against 1 of 15 with the baseline; the next mxbuild build rewrote 0 of 15 files after the fix and 14 of 15 after the baseline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1702) Studio Pro keeps three parts of a Java action's .java file when it regenerates it: the import list, the USER CODE and the EXTRA CODE section. MDL could author the first two (an import line in the body is hoisted to the import list) but had no clause for the third, and `describe java action` printed only the body. `create or modify` kept a hand-written helper in place, but executing the describe output on another project wrote a body calling a helper that no longer existed, and the build failed. Mirror of mendixlabs#1658. Cause: createJavaActionStatement ended at `AS $$ … $$` (the AST's ExtraCode field was never set), and describeJavaAction read only the USER CODE section. Fix: create or modify java action ModJ.JA_Twice(N: Integer not null) returns Integer as $$ import java.util.Objects; return twice(N); $$ extra code $$ private static long twice(long n) { return Objects.requireNonNull(n) * 2L; } $$; `extra code $$ … $$` (new EXTRA/CODE keywords, both still names) states the section, kept as written apart from its blank edge lines; an import line in it goes to the import list too. Omitted on `create or modify`, the stored section is kept, as an omitted EXPOSED AS keeps the toolbox entry; `extra code $$ $$` clears it, so WriteJavaSourceFile/RetainSections take the section as a *string (nil keeps). describe prints the section and, at the top of the body, the shortest leading part of the stored import list that regenerates it (javaactions.StatedImports) — nothing for mxbuild's own list. Verification: visitor, sdk and executor tests, including describe → exec of the report's file rebuilding it byte for byte and the omitted-clause control handing the writer nil; stubbing the visitor, describe and RetainSections changes fails them. Real 11.13.0 app with the report's steps: the baseline replay on a fresh project lost the import and helper and mxbuild failed with `cannot find symbol`; the fix's replay is byte-identical to the source file, builds, and the build leaves it unchanged. `create or modify` without the clause leaves the file unchanged. 07-java-action-examples.mdl passes exec + mx check with the new example. 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 #1683. Closes #1700 (mirror of mendixlabs#1653). Closes #1702 (mirror of mendixlabs#1658).
Three issues, one commit each.
#1683 —
log/send emailstored an expression followed bywith (…)as its source textlog info node 'P' $Msg with ({1} = 'x');logged the literal$Msg;Subject: $Subj with ({1} = '42')sent$Subj— check, exec and mx check all passed. Cause (cmd_microflows_builder_calls.go):addLogMessageActionandemailTemplatestoredfb.exprToString(message)as the template text.show messageandvalidation feedbackhad the same shape broken differently — they stored'{1}'with$Msgas its parameter and appended the stated ones, so'x'became a{2}nothing reads and the message showed its own unfilled{1}.Fix: one shared decision,
messageTemplateRefusals(newmessage_templates.go), rule MDL-TEMPLATE01: an expression followed bywith (…)(or the deprecatedobjects [...]) is refused on log, send email (subject, body, HtmlBody), show message and validation feedback — all four builders call it (exec refuses), and check reports it from the microflow, nanoflow, alter-fragment and rule validators. An expression has no{n}forwithto fill; the same rule as MDL-REST05 (#1669) and MDL-JA02 (#1692). Sibling fixed: a multi-line emailBody:string literal with parameters stored its source, quotes included, as the template; it now stores the literal's value. Kept inside the template paths (PR #1731 touches the call builders/grammar).Verified:
message_templates_test.go(check and exec on every statement and flow kind, controls, the multi-line body; reverted: every refused case and the body case fail). 11.13.0: before, all four flows written and mx check 0 errors; after, check andexec --no-checkrefuse with nothing written; the control forms build at 0 errors.#1700 — the generated
.javafile lacked the class javadocCause:
sdk/javaactions/source.goGenerateSourcetook no documentation. Fix:GenerateSource/WriteJavaSourceFiletake it; the executor passes the action's carried documentation, socreate or modifywithout a doc comment keeps the block. The format was measured against mxbuild 11.13.0:\r\n,\rand\neach end a*line; whitespace kept (whitespace-only documentation still gets a block); a backslash is doubled unlessu/U+ four hex digits follow (the upstream proposal missed this); mxbuild rejects*/in documentation as a model error, which an MDL doc comment cannot produce.Verified: 14 goldens from a real mxbuild deploy build (
sdk/javaactions/testdata/mxbuild/JA_Doc*.java.golden, CRLF preserved) reproduced byte for byte; reverted, all but the no-documentation control fail. Real app, 15 actionscreate or modifyd over mxbuild's files: 13/15 byte-identical (baseline 1/15; the other 2 differ only in mxcli's long-standing user-code blank-line padding), and the next mxbuild build rewrote 0/15 files (baseline 14/15).#1702 — no EXTRA CODE clause, so describe → exec lost hand-written helpers
Cause: the grammar ended
create java actionatAS $$ … $$(the AST already had an unsetExtraCode), and describe read only the USER CODE section. New clause:extra code $$ … $$sets the EXTRA CODE section (blank lines at either end trimmed; an import line inside it moves to the import list, as in the body); omitted keeps the stored section (likeEXPOSED AS);extra code $$ $$clears it. Describe prints it, plus the shortest leading part of the import list that regenerates the stored list in order.EXTRAandCODEare new keywords, both in the keyword rule (a test showsCodestill works as an attribute name).Verified: visitor/sdk/executor tests — describe → exec rebuilds the report's file byte for byte; leaving the clause out hands the writer nil (keep). Reverted: all fail. Real app: baseline replay lost the import and the helper and mxbuild failed
cannot find symbol; fixed replay is byte-identical, builds, and the build leaves it unchanged. Doctype example in07-java-action-examples.mdlpasses-tags integrationexec + mx check (0 errors).All
Full
go test ./...(incl. the conformance gate),go vet, gofmt; CI's doc checks pass locally. Repros:log-email-1683-expression-with-params.fail.mdl, the #1700 andjava-action-1702-extra-code-roundtrip.mdlbug-tests. Findings recorded. Docs:mxcli syntax(logging, send-email, validation, java-action.create),MDL_QUICK_REFERENCE.md, write-microflows pitfalls §16, java-actions skill, docs-sitecreate-java-action.mdand error appendix.Noticed, not fixed
WriteJavaScriptSourceFilehas no extra-code parameter).stripJavaCodeBlocklooks for"\nAS $$"but describe prints lowercaseas $$.$$inside Java code ends the dollar string (body and extra code alike); documentation containing// BEGIN USER CODEwould confuse section extraction.🤖 Generated with Claude Code