Skip to content

fix(csharp): payload-generator resolves bare @payloadRef in a named package#221

Open
dmealing wants to merge 1 commit into
mainfrom
fix/csharp-payload-generator-bare-payloadref
Open

fix(csharp): payload-generator resolves bare @payloadRef in a named package#221
dmealing wants to merge 1 commit into
mainfrom
fix/csharp-payload-generator-bare-payloadref

Conversation

@dmealing

Copy link
Copy Markdown
Member

Problem

PayloadGenerator/PayloadCodegen.EmitRecord silently emitted an empty payload
file (header comment, no record) for any template.output declared in a named
(non-default) package with a bare @payloadRef. MetaData.Attr() resolves a
bare template attr to its fully-qualified form per ADR-0042, but
PayloadCodegen.FindObject's bare short-name match compared against the raw
(possibly FQN) voName without stripping it first — nested @objectRef fields
already got this treatment via FieldType's CSharpNaming.StripPkg call, but
the top-level payloadRef never did. PayloadGenerator.EmitPayload's output
filename had the same leak (literal "::" in the file name).

Fix

Strip the package qualifier once, at the top of EmitRecord, before it's used
for the FindObject lookup, the emitted-set key, and the record's own type
name; strip it in EmitPayload's file name too. This brings PayloadCodegen
in line with the same StripPkg-before-lookup convention already used by
RoutesGenerator, EntityGenerator, M2MNavigation, OutputParserGenerator,
DbContextGenerator, ReverseFinders, and PackageBindingResolver.

Why the existing test suite didn't catch this

The old PayloadCodegenTests.cs called GeneratePayloadRecords(root, "AuthorBrief")
directly with a hardcoded bare name — it never went through the
template.output → Attr() → FQN resolution step that actually produces the
package-qualified string, so it never exercised the path that broke. The new
PayloadGeneratorTests.cs drives the real end-to-end path (load metadata with
a named package → PayloadGenerator.GenerateEmitPayload
PayloadCodegen.GeneratePayloadRecords) and asserts the generated file
actually contains the record body, not just a header.

Cross-port impact: none

Audited TS, Java, Kotlin, and Python — none have this bug:

  • TS's resolveObjectRef is FQN-exact when the ref contains ::.
  • Java/Kotlin/Python's resolveObjectByShortOrFqn matches either bare or FQN
    form, and all three name the emitted class after the declaring
    template, not the raw payloadRef string, so an FQN could never leak into
    a generated identifier there in the first place.
  • All four ports' own payload-generator unit-test suites use a named
    package as their default test fixture (acme::ai / acme::demo), so
    they've been exercising this exact scenario all along.

Follow-ups filed (not blocking, out of scope for this PR)

Test plan

  • PayloadGeneratorTests.cs — new regression test drives the real
    template.output → Attr() → FQN → EmitRecord path in a named package and
    asserts a full record body (was empty before the fix)
  • Existing PayloadCodegenTests.cs (default-package + cross-package
    @objectRef collision cases) still pass
  • CI (C# compile + conformance) — runs on release tags / manual dispatch
    per this repo's CI policy; not gated on PRs

…ackage

PayloadGenerator/PayloadCodegen.EmitRecord silently emitted an empty
payload file for any template.output declared in a named (non-default)
package with a bare @payloadRef. MetaData.Attr() resolves a bare
template attr to its fully-qualified form per ADR-0042, but
PayloadCodegen.FindObject's bare short-name match compared against the
raw (possibly FQN) voName without stripping it first — nested
@objectref fields already got this treatment via FieldType's
CSharpNaming.StripPkg call, but the top-level payloadRef never did.
PayloadGenerator.EmitPayload's output filename had the same leak
(literal "::" in the file name).

Strip the package qualifier once, at the top of EmitRecord, before it's
used for the FindObject lookup, the emitted set key, and the record's
own type name; strip it in EmitPayload's file name too.

Added PayloadGeneratorTests.cs covering the generator end-to-end (the
existing PayloadCodegenTests only exercised GeneratePayloadRecords
directly with a hardcoded bare voName, never through the
template.output -> Attr() -> FQN path that actually triggers this).
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