Skip to content

fix(format): guard against null members in FormatJvmModelInferrer.inferConstants#1474

Draft
joaodinissf wants to merge 1 commit into
dsldevkit:masterfrom
joaodinissf:fix/format-inferconstants-null-leak
Draft

fix(format): guard against null members in FormatJvmModelInferrer.inferConstants#1474
joaodinissf wants to merge 1 commit into
dsldevkit:masterfrom
joaodinissf:fix/format-inferconstants-null-leak

Conversation

@joaodinissf

Copy link
Copy Markdown
Collaborator

The bug

FormatJvmModelInferrer.inferConstants adds createConstant(format, c) to the inferred JVM model unconditionally:

for (final Constant c : FormatGeneratorUtil.getAllConstants(format)) {
  it.getMembers().add(createConstant(format, c));   // createConstant can return null
}

createConstant returns null for a value-less constant (its if (stringValue) … else if (intValue) … return null fall-through — reachable for a constant in an incomplete/error state during editing). Adding that null to the JvmMember EList throws IllegalArgumentException: The 'no null' constraint is violated.

Root cause — a migration regression

The original Xtend was members += allConstants.map[createConstant], which compiles to JvmTypesBuilder.operator_add, and operator_add silently skips null elements. The Xtend→Java migration translated += to a bare loop-add, which does not skip nulls — so the null-skip semantics were lost. The sibling inferRules in the same file kept the null-skip, making this an inconsistent one-off.

The fix

Guard the add (equivalent to operator_add's null-skip / an IterableExtensions.filterNull):

final JvmMember member = createConstant(format, c);
if (member != null) {
  it.getMembers().add(member);
}

Verification

  • New FormatJvmModelInferrerTest pins the behaviour: a value-less Constant must not yield a null member or throw.
  • A/B proven through the full test harness: the test fails on the pre-fix code (IllegalArgumentException: The 'no null' constraint is violated) and passes with the guard. Full local gate: BUILD SUCCESS, 359 tests / 0 failures, all static analysis clean.

Found by an archaeology audit of the merged Xtend→Java migrations. The skill rule that prevents this class of defect is added in a separate PR (#1473, rules/10 §10.5operator_add skips nulls).

🤖 Generated with Claude Code

…erConstants

inferConstants added createConstant(format, c) to the JVM model unconditionally.
createConstant returns null for a value-less constant (its switch fall-through), so
a null JvmMember reached it.getMembers().add(...) — which the EMF EList rejects with
IllegalArgumentException: The 'no null' constraint is violated (or leaks a null member
downstream). Regression class: the original Xtend `members += allConstants.map[createConstant]`
compiled to JvmTypesBuilder.operator_add, which silently skips nulls; the Xtend-to-Java
migration translated it to a bare loop-add that does not.

Guard the add (equivalent to operator_add's null-skip). Add FormatJvmModelInferrerTest
pinning the behaviour: a value-less constant must not produce a null member or throw.
A/B verified — the test fails on the pre-fix code (no null constraint violated) and passes
with the guard.

Found by an archaeology audit of the merged Xtend→Java migrations; the skill rule that
prevents this class is added separately (rules/10 §10.5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant