AI-generated audit finding — this issue was opened from an automated security/correctness audit. It has not been triaged by a human yet; verify the reasoning, reproducibility, and severity before acting on it.
Medium: valid service type shapes are mishandled — CONFIRMED
Affected code:
Verification:
Confirmed on three distinct axes:
- Records —
[Service] on public partial record class Foo never triggers the generator because the syntax predicate only matches ClassDeclarationSyntax, not RecordDeclarationSyntax. No diagnostic, no generated file — silent failure.
- Generics —
classSymbol.Name is "Foo" for Foo<T>; the emitted partial class Foo { ... } doesn't merge with the user's partial class Foo<T> and the build fails with a type-not-partial error, pointing nowhere useful.
- Multi-level nesting —
class Outer { class Middle { [Service] class Leaf { } } } emits partial class Middle { partial class Leaf { ... } } without Outer, which the compiler rejects because the generated source declares Middle at the global/namespace scope rather than inside Outer.
Impact:
- Supported-looking service declarations silently fail to generate (records).
- Nested and generic services break compilation with malformed generated code.
- Failure points don't lead the developer back to the root cause.
Recommendation:
- Expand the syntax predicate to
TypeDeclarationSyntax (or specifically ClassDeclarationSyntax or RecordDeclarationSyntax) and widen the cast accordingly.
- Capture the full type syntax for the service class (
class Foo<T> where T : …) and for each enclosing container, including generic parameters and constraints.
- Iterate on
parentNode in a loop so every enclosing type is captured.
- Add regression tests for record classes, multi-level nesting, and generic service types.
Status: Valid, Medium severity.
Source report: src-IceRpc.ServiceGenerator-audit-2026-04-14.md (finding valid service type shapes are mishandled — **CONFIRMED**)
Severity (auditor-assigned): Medium
Medium: valid service type shapes are mishandled — CONFIRMED
Affected code:
node is ClassDeclarationSyntax; the cast(ClassDeclarationSyntax)context.TargetNodereinforces the same assumptionServiceClassis constructed fromclassSymbol.Name(bare name, no generic arity) andclassDeclaration.Keyword.ValueTextparentNode = parentNode.Parent;at line 112 is the last statement of theif; there is no loop)Enclosinglinked list shape is correct; the parser just doesn't populate beyond one levelpartial {keyword} {name}header from the data the parser suppliedVerification:
Confirmed on three distinct axes:
[Service]onpublic partial record class Foonever triggers the generator because the syntax predicate only matchesClassDeclarationSyntax, notRecordDeclarationSyntax. No diagnostic, no generated file — silent failure.classSymbol.Nameis"Foo"forFoo<T>; the emittedpartial class Foo { ... }doesn't merge with the user'spartial class Foo<T>and the build fails with a type-not-partial error, pointing nowhere useful.class Outer { class Middle { [Service] class Leaf { } } }emitspartial class Middle { partial class Leaf { ... } }withoutOuter, which the compiler rejects because the generated source declaresMiddleat the global/namespace scope rather than insideOuter.Impact:
Recommendation:
TypeDeclarationSyntax(or specificallyClassDeclarationSyntax or RecordDeclarationSyntax) and widen the cast accordingly.class Foo<T> where T : …) and for each enclosing container, including generic parameters and constraints.parentNodein a loop so every enclosing type is captured.Status: Valid, Medium severity.
Source report: src-IceRpc.ServiceGenerator-audit-2026-04-14.md (finding
valid service type shapes are mishandled — **CONFIRMED**)Severity (auditor-assigned): Medium