Handle generic types in proto message name generation
All checks were successful
Publish NuGets / build (release) Successful in 39s
All checks were successful
Publish NuGets / build (release) Successful in 39s
Generic types like Translation<T> now produce qualified message names (e.g. TranslationOfFaqTranslationQueryItem) to avoid duplicate message definitions in generated .proto files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b372805c4e
commit
6aece5a769
@ -413,17 +413,21 @@ internal class ProtoFileGenerator
|
||||
|
||||
private void GenerateComplexTypeMessage(INamedTypeSymbol? type)
|
||||
{
|
||||
if (type == null || _generatedMessages.Contains(type.Name))
|
||||
if (type == null)
|
||||
return;
|
||||
|
||||
var messageName = ProtoFileTypeMapper.GetProtoMessageName(type);
|
||||
if (_generatedMessages.Contains(messageName))
|
||||
return;
|
||||
|
||||
// Don't generate messages for system types or primitives
|
||||
if (type.ContainingNamespace?.ToString().StartsWith("System") == true)
|
||||
return;
|
||||
|
||||
_generatedMessages.Add(type.Name);
|
||||
_generatedMessages.Add(messageName);
|
||||
|
||||
_messagesBuilder.AppendLine($"// {type.Name} entity");
|
||||
_messagesBuilder.AppendLine($"message {type.Name} {{");
|
||||
_messagesBuilder.AppendLine($"// {messageName} entity");
|
||||
_messagesBuilder.AppendLine($"message {messageName} {{");
|
||||
|
||||
// Collect nested complex types to generate after closing this message
|
||||
var nestedComplexTypes = new List<INamedTypeSymbol>();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Svrnty.CQRS.Grpc.Generators;
|
||||
@ -151,13 +152,27 @@ internal static class ProtoFileTypeMapper
|
||||
// Complex types (classes/records) become message types
|
||||
if (typeSymbol.TypeKind == TypeKind.Class || typeSymbol.TypeKind == TypeKind.Struct)
|
||||
{
|
||||
return typeName; // Reference the message type by name
|
||||
return GetProtoMessageName(typeSymbol); // Reference the message type by name (handles generics)
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return "string"; // Default to string for unknown types
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the proto message name for a type, handling generic types by qualifying
|
||||
/// with type arguments. e.g. Translation<FaqTranslationQueryItem> becomes TranslationOfFaqTranslationQueryItem.
|
||||
/// </summary>
|
||||
public static string GetProtoMessageName(ITypeSymbol typeSymbol)
|
||||
{
|
||||
if (typeSymbol is INamedTypeSymbol namedType && namedType.IsGenericType && namedType.TypeArguments.Length > 0)
|
||||
{
|
||||
var typeArgs = string.Join("And", namedType.TypeArguments.Select(t => GetProtoMessageName(t)));
|
||||
return $"{namedType.Name}Of{typeArgs}";
|
||||
}
|
||||
return typeSymbol.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts C# PascalCase property name to proto snake_case field name.
|
||||
/// Uses simple conversion: add underscore before each uppercase letter (except first).
|
||||
|
||||
Loading…
Reference in New Issue
Block a user