Recentemente, refatorei um gerador de código-fonte para usar árvores de sintaxe em vez de interpolação de strings. O gerador de código-fonte pega um arquivo JSON e gera uma classe estática com strings públicas. A chave é o nome da propriedade e o valor da propriedade é o valor.
Notei que a saída não tem espaços entre os membros:
public static class TranslationKeys
{
/// <summary>
/// Looks up a localized string using key CurrentLocaleName.
/// </summary>
public const string CurrentLocaleName = "CurrentLocaleName";
/// <summary>
/// Looks up a localized string using key LocalizationCurrentProviderIs.
/// </summary>
public const string LocalizationCurrentProviderIs = "LocalizationCurrentProviderIs";
}
Anteriormente, ao usar um construtor de strings, eu tinha um belo espaço entre os membros:
public static class TranslationKeys
{
/// <summary>
/// Looks up a localized string using key CurrentLocaleName.
/// </summary>
public const string CurrentLocaleName = "CurrentLocaleName";
/// <summary>
/// Looks up a localized string using key LocalizationCurrentProviderIs.
/// </summary>
public const string LocalizationCurrentProviderIs = "LocalizationCurrentProviderIs";
}
Minha fonte é gerada da seguinte forma:
private static string GenerateSource(string generatedNamespace, Dictionary<string, string> keysToGenerate)
{
var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(generatedNamespace))
.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")))
.AddMembers(
SyntaxFactory.ClassDeclaration("TranslationKeys")
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword))
.AddMembers(keysToGenerate.Select(CreateConstantField).ToArray())
);
var compilationUnit = SyntaxFactory.CompilationUnit()
.AddMembers(namespaceDeclaration)
.NormalizeWhitespace("\t");
return compilationUnit.ToFullString();
}
private static MemberDeclarationSyntax CreateConstantField(KeyValuePair<string, string> keyValuePair)
{
return SyntaxFactory.FieldDeclaration(
SyntaxFactory.VariableDeclaration(SyntaxFactory.ParseTypeName("string"))
.AddVariables(SyntaxFactory.VariableDeclarator(keyValuePair.Key)
.WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(keyValuePair.Value))))))
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.ConstKeyword))
.WithLeadingTrivia(SyntaxFactory.TriviaList(
SyntaxFactory.CarriageReturnLineFeed,
SyntaxFactory.Comment("/// <summary>"),
SyntaxFactory.Comment($"/// Looks up a localized string using key {keyValuePair.Value}."),
SyntaxFactory.Comment("/// </summary>")
))
.WithTrailingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed);
}
Tentei de tudo para CreateConstantField
adicionar uma quebra de linha vazia. Adicionei espaços em branco com \n
, todos os fins de linha imagináveis e nada parece funcionar. Usei o gpt 4o e o claude 3.7 e eles me levaram a um círculo vicioso de WithTrailingTrivia que nunca funciona.
Estou verificando se o gerador está atualizado, reconstruindo-o e executando-o manualmente pelo Visual Studio (adiciono um comentário que altero para garantir que o código mais recente esteja sendo executado). Não tive sorte e não sei como posso obter essa funcionalidade (que eu consideraria básica) a partir de um código gerado!