using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Polonium.Generators.Generators; [Generator] public class TemplateInlineGenerator : AssetProcessGenerator { public override void Execute(GeneratorExecutionContext context) { if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver)) return; Compilation compilation = context.Compilation; INamedTypeSymbol? templateDefine = compilation.GetTypeByMetadataName("Polonium.Attributes.TemplateDefines.TemplateInline"); foreach (ClassDeclarationSyntax? cls in context.GetClassesWithAttribute(receiver, templateDefine)) { if(!cls.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword))) continue; string isStatic = ""; if(cls.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword))) isStatic = "static"; StringBuilder sb = new StringBuilder(); sb .AppendLine($"public {isStatic} partial class {cls.Identifier.ToString()}") .AppendLine("{"); HashSet headers = new(); foreach (AttributeData attr in context.GetAttributes(cls, templateDefine)) { string template = attr.ConstructorArguments[0].Value?.ToString()??string.Empty; string dataFile = attr.ConstructorArguments[1].Value?.ToString()??string.Empty; string depsString = attr.ConstructorArguments[2].Value?.ToString()??string.Empty; string[] deps = depsString.Split(';'); foreach (string dep in deps) headers.Add(dep); AdditionalText? df = context.AdditionalFiles.FirstOrDefault(f => f.Path.EndsWith(dataFile)); string[] data =(df?.GetText()?.ToString() ?? "").Split('\n'); foreach (string d in data) { if(d.Trim().Equals("")) continue; sb.AppendLine($" {Format(template, d)}"); } } sb.AppendLine("}"); StringBuilder hb = new(); foreach(string header in headers) { if(header.Trim().Equals("")) continue; hb.AppendLine($"using {header};"); } hb.Append(sb); Console.WriteLine(hb.ToString()); context.AddSource($"{cls.Identifier.ToString()}_TemplateInline.g.cs", hb.ToString()); } } }