using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; namespace MfGames.Nitride.Generators; /// /// Implements a source generator that creates the additional properties /// and methods for a singleton component including the constructor and /// instance methods, along with extension methods for adding them to entities. /// [Generator] public class SingletonComponentSourceGenerator : ClassAttributeSourceGeneratorBase { protected override SingletonComponentSyntaxReceiver CreateSyntaxReceiver( GeneratorInitializationContext context) { return new SingletonComponentSyntaxReceiver(context); } protected override void GenerateClassFile( GeneratorExecutionContext context, ClassAttributeReference unit) { // Pull out some fields. ClassDeclarationSyntax cds = unit.ClassDeclaration; // Create the partial class. StringBuilder buffer = new(); buffer.AppendLine("#nullable enable"); // Copy the using statements from the file. foreach (UsingDirectiveSyntax? uds in unit.UsingDirectiveList) { buffer.AppendLine(uds.ToString()); } buffer.AppendLine(); // Create the namespace. SyntaxToken cls = cds.Identifier; buffer.AppendLine( string.Join( "\n", $"using MfGames.Gallium;", $"", $"namespace {unit.Namespace}", $"{{", $" public partial class {cls}", $" {{", $" static {cls}()", $" {{", $" Instance = new {cls}();", $" }}", $"", $" private {cls}()", $" {{", $" }}", $"", $" public static {cls} Instance {{ get; }}", $" }}", $"", $" public static class {cls}Extensions", $" {{", $" public static bool Has{cls}(this Entity entity)", $" {{", $" return entity.Has<{cls}>();", $" }}", $"", $" public static Entity Remove{cls}(this Entity entity)", $" {{", $" return entity.Remove<{cls}>();", $" }}", $"", $" public static Entity Set{cls}(this Entity entity)", $" {{", $" return entity.Set({cls}.Instance);", $" }}", $" }}", $"}}", "")); // Create the source text and write out the file. var sourceText = SourceText.From(buffer.ToString(), Encoding.UTF8); context.AddSource(cls + ".Generated.cs", sourceText); } }