From eaf2ed4e4ee86846816349311575ddd7c64b0247 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 27 Apr 2026 15:57:10 +0200 Subject: [PATCH] Dedup partial service-class declarations in the generator ForAttributeWithMetadataName emits one ClassDeclarationSyntax per attribute application. If a user puts [Service] on more than one partial part of the same class, the parser previously processed every syntax node and the generator called AddSource twice with the same hint name, which Roslyn rejects with an opaque generator-threw ArgumentException at build time. Track classes by their resolved INamedTypeSymbol and skip ones we've already processed. The user's intent is unambiguous (the parts together are one class), so silent dedup is the natural behavior; no diagnostic is needed. --- src/IceRpc.ServiceGenerator/Internal/Parser.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/IceRpc.ServiceGenerator/Internal/Parser.cs b/src/IceRpc.ServiceGenerator/Internal/Parser.cs index 210825f19..6755660f1 100644 --- a/src/IceRpc.ServiceGenerator/Internal/Parser.cs +++ b/src/IceRpc.ServiceGenerator/Internal/Parser.cs @@ -43,6 +43,10 @@ internal IReadOnlyList GetServiceDefinitions(IEnumerable(); + // Multiple partial declarations of the same class with [Service] applied to more than one part each yield + // their own ClassDeclarationSyntax from ForAttributeWithMetadataName. Process each class symbol once so we + // don't AddSource the same hint name twice. + var seenClassSymbols = new HashSet(SymbolEqualityComparer.Default); // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive) foreach (IGrouping group in classes.GroupBy(x => x.SyntaxTree)) { @@ -53,7 +57,7 @@ internal IReadOnlyList GetServiceDefinitions(IEnumerable