intent: render a posts set constant for its target column's Java type, and print a remedy that survives YAML (#7287) - #7312
Merged
Conversation
…, and print a remedy that survives YAML (#7287) Three neighbours of the #7246 refusal, all of them the same defect class it set out to close - a `posts: set:` value that reaches javac as something it cannot compile. 1. The remedy the refusal printed did not work. It named `"Receipt.Store"`, which YAML unquotes back into the very dotted path being refused, so an author who followed it got the identical refusal. It now names the one spelling that survives YAML, `'"Receipt.Store"'`, and says why the single quotes are there. PostSetSupport.QUOTED carried the same misunderstanding in its javadoc. 2. A numeric constant was rendered bare regardless of the target column. Every intent numeric-with-scale type is a BigDecimal in the generated entity and `long` is a Long, so `Quantity: -3.5` emitted `row.Quantity = -3.5;` and `Sequence: 2` emitted `row.Sequence = 2;` - compile errors of the whole generated module. PostSetSupport.targetType now reads the column's type off the target entity (a field by its own spelling, a to-one relation by its target's key) and expression() renders to it: `new java.math.BigDecimal("-3.5")`, `2L`, `2`, and `"2"` into a text column. A constant the column cannot hold at all - a text into a decimal, a fraction into a long, a number into a boolean, any constant into a date - is refused at parse by typeMismatch(), naming the column and the reason. 3. The escape loop had a fourth copy. PostSetSupport.escape was byte-for-byte JavaLiterals.escape, and GlueIntentGenerator.javaLiteral was a third, weaker vocabulary (a backslash-then-quote pass that a newline still closes). JavaLiterals is now public and both call it. Verified: engine-intent (1212) and ide-template (143) unit suites green; GluePostsTest drives the quoted remedy THROUGH IntentParser.parse and asserts the typed rendering off a parsed model; IntentEngineIT asserts the emitted `row.Factor = new java.math.BigDecimal("-1.5");` / `row.Sequence = 7L;`; and IntentPostsAtomicityIT now sets a decimal and a long constant, so its generate-publish-compile-post run is the proof they compile - both ITs green. Fixes #7287 Co-Authored-By: Claude Opus 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.
Follow-up to #7246 / PR #7268: the refusal was right, three of its neighbours were not - all of them the same defect class it set out to close, a
posts: set:value that reachesjavacas something it cannot compile.1. The remedy the refusal printed did not work
validatePostSetsanswered a dotted path withquote it ("Receipt.Store") to mean that text. YAML strips one level of quoting before the parser sees the scalar, so an author who followed that remedy handed the parser the same bare dotted path and got the identical refusal. The spelling that actually reachesPostSetSupport.QUOTEDis'"Receipt.Store"'- single quotes wrapping the literal double quotes - which is what the refusal now prints (PostSetSupport.quotedSpelling), with a clause saying why the single quotes are there.QUOTED's own javadoc carried the same misunderstanding and is corrected.The escape hatch also had no test through the YAML layer.
GluePostsTest.theQuotedRemedySurvivesYamlnow takes the remedy out of the refusal message, feeds it back throughIntentParser.parse, and asserts the rendered"Receipt.Store"string literal.2. A numeric constant was rendered bare regardless of the target column
Every intent numeric-with-scale type is a
java.math.BigDecimalin the generated entity andlongis aLong, soQuantity: -3.5emittedrow.Quantity = -3.5;andSequence: 2emittedrow.Sequence = 2;- compile errors of the whole generated module. Only integer FKs happened to work.PostSetSupport.targetTypenow reads the column's type off the target entity - a field by its own spelling (PascalCased on both sides, as the generated assignment is), a to-one relation by its target's key type - andexpressionrenders to it:decimal/double-3.5new java.math.BigDecimal("-3.5")long22Linteger/ relation FK22string2,true"2","true"22(as before)A constant the column cannot hold in any spelling - a text into a decimal, a fraction into a whole-number column, a number into a boolean, any constant into a date/time - is refused at parse by
typeMismatch, naming the column and the reason, rather than shipped as a literal of the wrong type. A copy (item.<Field>/source.<Field>/null) is not type-checked: the two columns' types are the author's business. No module in the fleet authorsposts:today, so nothing in the field is affected by the new refusals.3. A fourth copy of the same escape loop
PostSetSupport.escapewas byte-for-byteJavaLiterals.escape(ide-template, package-private), andGlueIntentGenerator.javaLiteralwas a third, weaker vocabulary for the same job - a backslash-then-quote pass that survives a quote but not a newline, which closes the literal too.JavaLiteralsis now public (engine-intent already depends on ide-template), both call sites use it, and its javadoc says it is THE escape so a fifth copy does not appear. Pattern noted in #7241.Verified
mvn -pl components/engine/engine-intent,components/ide/ide-template test: 1212 and 143 green.GluePostsTest(8 cases): the typed rendering perTargetType, the type read off a parsed model, the four type refusals, and the quoted remedy driven throughIntentParser.parse.IntentEngineIT#posts_writes_every_row_of_one_source_event_in_one_transaction: the fixture sets a decimal, a long, an integer and a text constant; the generated post must carryrow.Factor = new java.math.BigDecimal("-1.5");,row.Sequence = 7L;,row.Direction = 2;,row.Ledger = "issued";. Green.IntentPostsAtomicityIT: its fixture now sets a decimal (-1.5) and a long (7) constant, so the whole generate → publish → compile → post → read-back run is the proof they compile - the bare literals would have produced no handler and no rows. Green.Not verified: no other IT or template branch renders
posts: set:(grep), and no.intentin the module fleet authorsposts:at all, so there is nothing else to regenerate.Fixes #7287
🤖 Generated with Claude Code