完成多语言源码生成

完成多语言源码生成
This commit is contained in:
polarboy 2024-08-20 18:23:02 +08:00
parent b92f3e8c28
commit 125352b02e
8 changed files with 166 additions and 11 deletions

View File

@ -0,0 +1,9 @@
using AtomUI.Theme;
namespace AtomUI.Controls.Lang
{
public static class LoadingIndicatorLangResourceKey
{
public static readonly LanguageResourceKey LoadingText = new LanguageResourceKey("LoadingIndicator.LoadingText", "AtomUI.Token");
}
}

View File

@ -0,0 +1,141 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace AtomUI.Generator.Language;
public class LangResourceKeyClassSourceWriter
{
private SourceProductionContext _context;
private List<LanguageInfo> _languageInfos;
private List<string> _usingInfos;
private Dictionary<string, List<LanguageInfo>> _languagesById;
public LangResourceKeyClassSourceWriter(SourceProductionContext context, List<LanguageInfo> languageInfos)
{
_context = context;
_languageInfos = languageInfos;
_languagesById = new Dictionary<string, List<LanguageInfo>>();
_usingInfos = new List<string>();
SetupUsingInfos();
BuildLanguageKeys();
}
private void BuildLanguageKeys()
{
foreach (var languageInfo in _languageInfos) {
if (!_languagesById.ContainsKey(languageInfo.LanguageId)) {
_languagesById[languageInfo.LanguageId] = new List<LanguageInfo>();
}
_languagesById[languageInfo.LanguageId].Add(languageInfo);
}
}
private void SetupUsingInfos()
{
_usingInfos.Add("AtomUI.Theme");
}
public void Write()
{
var compilationUnitSyntax = BuildCompilationUnitSyntax();
_context.AddSource($"LanguageResourceConst.g.cs", compilationUnitSyntax.NormalizeWhitespace().ToFullString());
}
private ClassDeclarationSyntax BuildClassSyntax(string className)
{
var modifiers = new List<SyntaxToken>()
{
SyntaxFactory.Token(SyntaxKind.PublicKeyword),
SyntaxFactory.Token(SyntaxKind.StaticKeyword)
};
var classSyntax = SyntaxFactory.ClassDeclaration(className)
.AddModifiers(modifiers.ToArray());
return classSyntax;
}
private FieldDeclarationSyntax BuildResourceKeyFieldSyntax(string catalog, string name, string value)
{
var modifiers = new List<SyntaxToken>()
{
SyntaxFactory.Token(SyntaxKind.PublicKeyword),
SyntaxFactory.Token(SyntaxKind.StaticKeyword),
SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)
};
var resourceKeyType = SyntaxFactory.ParseTypeName("LanguageResourceKey");
var argument = SyntaxFactory.Argument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal($"{value}")));
var nsArgument = SyntaxFactory.Argument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal($"{catalog}")));
var resourceKeyInstanceExpr = SyntaxFactory.ObjectCreationExpression(resourceKeyType)
.WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList<ArgumentSyntax>(new SyntaxNodeOrToken[]
{
argument,
SyntaxFactory.Token(SyntaxKind.CommaToken),
nsArgument
})));
var fieldSyntax = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(resourceKeyType)
.WithVariables(SyntaxFactory.SingletonSeparatedList(
SyntaxFactory.VariableDeclarator(name)
.WithInitializer(
SyntaxFactory.EqualsValueClause(resourceKeyInstanceExpr)))))
.AddModifiers(modifiers.ToArray());
return fieldSyntax;
}
private NamespaceDeclarationSyntax BuildLanguageResourceKey(List<LanguageInfo> languages)
{
var targetNamespace = languages.First().Namespace;
var catalog = languages.First().ResourceCatalog;
var languageId = languages.First().LanguageId;
var keys = new HashSet<string>();
foreach (var languageInfo in languages) {
keys.UnionWith(languageInfo.Items.Keys);
}
var namespaceSyntax = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(targetNamespace));
var className = $"{languageId}LangResourceKey";
var classSyntax = BuildClassSyntax(className);
var resourceKeyFields = new List<MemberDeclarationSyntax>();
foreach (var key in keys) {
resourceKeyFields.Add(BuildResourceKeyFieldSyntax(catalog, key, $"{languageId}.{key}"));
}
classSyntax = classSyntax.AddMembers(resourceKeyFields.ToArray());
namespaceSyntax = namespaceSyntax.AddMembers(classSyntax);
return namespaceSyntax;
}
private CompilationUnitSyntax BuildCompilationUnitSyntax()
{
var compilationUnit = SyntaxFactory.CompilationUnit();
var usingSyntaxList = new List<UsingDirectiveSyntax>();
foreach (var usingInfo in _usingInfos) {
var usingSyntax = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(usingInfo));
usingSyntaxList.Add(usingSyntax);
}
compilationUnit = compilationUnit.AddUsings(usingSyntaxList.ToArray());
foreach (var entry in _languagesById) {
if (entry.Value.Count > 0) {
var namespaceDeclSyntax = BuildLanguageResourceKey(entry.Value);
compilationUnit = compilationUnit.AddMembers(namespaceDeclSyntax);
}
}
return compilationUnit;
}
}

View File

@ -47,6 +47,15 @@ public class LanguageProviderWalker : CSharpSyntaxWalker
}
}
var ns = string.Empty;
if (node.Parent is FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDecl) {
ns = fileScopedNamespaceDecl.Name.ToString();
} else if (node.Parent is NamespaceDeclarationSyntax namespaceDecl) {
ns = namespaceDecl.Name.ToString();
}
LanguageInfo.Namespace = ns;
base.VisitClassDeclaration(node);
}
}

View File

@ -1,6 +0,0 @@
namespace AtomUI.Generator.Language;
public class ResourceKeyClassSourceWriter
{
}

View File

@ -20,7 +20,8 @@ public class LanguageGenerator : IIncrementalGenerator
}).Collect();
initContext.RegisterImplementationSourceOutput(languageProvider, (context, languageProviders) =>
{
var classWriter = new LangResourceKeyClassSourceWriter(context, languageProviders.ToList());
classWriter.Write();
});
}
}

View File

@ -60,7 +60,7 @@ public class ResourceKeyClassSourceWriter
var nsArgument = SyntaxFactory.Argument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal($"{tokenName.ResourceNamespace}")));
SyntaxFactory.Literal($"{tokenName.ResourceCatalog}")));
var resourceKeyInstanceExpr = SyntaxFactory.ObjectCreationExpression(resourceKeyType)
.WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList<ArgumentSyntax>(new SyntaxNodeOrToken[]

View File

@ -38,11 +38,11 @@ public class TokenInfo
public record TokenName
{
public string Name { get; }
public string ResourceNamespace { get; }
public string ResourceCatalog { get; }
public TokenName(string name, string resourceNamespace)
public TokenName(string name, string catalog)
{
Name = name;
ResourceNamespace = resourceNamespace;
ResourceCatalog = catalog;
}
}