using Fantasy.SourceGenerator.Common; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Generic; using System.Linq; using System.Text; // ReSharper disable AssignNullToNotNullAttribute namespace Fantasy.SourceGenerator.Generators { /// /// Event System 注册代码生成器 /// 自动生成 EventComponent 所需的 Event System 注册代码,替代运行时反射 /// [Generator] public partial class EventSystemGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { // 查找所有实现了 EventSystem 相关抽象类的类 var eventSystemTypes = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (node, _) => IsEventSystemClass(node), transform: static (ctx, _) => GetEventSystemTypeInfo(ctx)) .Where(static info => info != null) .Collect(); // 组合编译信息和找到的类型 var compilationAndTypes = context.CompilationProvider.Combine(eventSystemTypes); // 注册源代码输出 context.RegisterSourceOutput(compilationAndTypes, static (spc, source) => { // 检查1: 是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号 if (!CompilationHelper.HasFantasyDefine(source.Left)) { return; } // 检查2: 是否引用了 Fantasy 框架的核心类型 if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEventSystemRegistrar") == null) { return; } GenerateRegistrationCode(spc, source.Left, source.Right!); }); } /// /// 提取 EventSystem 类型信息 /// private static EventSystemTypeInfo? GetEventSystemTypeInfo(GeneratorSyntaxContext context) { var classDecl = (ClassDeclarationSyntax)context.Node; if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol || !symbol.IsInstantiable()) { return null; } if (symbol.BaseType == null) { return null; } var baseType = symbol.BaseType; if (!baseType.IsGenericType) { return null; } return baseType.Name switch { "EventSystem" => EventSystemTypeInfo.Create(EventSystemType.EventSystem, symbol), "AsyncEventSystem" => EventSystemTypeInfo.Create(EventSystemType.AsyncEventSystem, symbol), "SphereEventSystem" => EventSystemTypeInfo.Create(EventSystemType.SphereEventSystem, symbol), _ => null }; } /// /// 生成注册代码 /// private static void GenerateRegistrationCode( SourceProductionContext context, Compilation compilation, IEnumerable eventSystemTypes) { var eventSystems = eventSystemTypes.ToList(); // 获取当前程序集名称(仅用于注释) var assemblyName = compilation.AssemblyName ?? "Unknown"; // 生成代码文件 var builder = new SourceCodeBuilder(); // 添加文件头 builder.AppendLine(GeneratorConstants.AutoGeneratedHeader); // 添加 using builder.AddUsings( "System", "System.Collections.Generic", "Fantasy.Assembly", "Fantasy.DataStructure.Collection", "Fantasy.Event" ); builder.AppendLine(); // 开始命名空间(固定使用 Fantasy.Generated) builder.BeginNamespace("Fantasy.Generated"); // 开始类定义(实现 IEventSystemRegistrar 接口) builder.AddXmlComment($"Auto-generated Event System registration class for {assemblyName}"); builder.BeginClass("EventSystemRegistrar", "internal sealed", "IEventSystemRegistrar"); // 生成字段用于存储已注册的事件处理器(用于 UnRegister) GenerateFields(builder, eventSystems); // 生成 RegisterSystems 方法 GenerateRegisterMethod(builder, eventSystems); // 生成 UnRegisterSystems 方法 GenerateUnRegisterMethod(builder, eventSystems); // 生成 Dispose 方法 GenerateDisposeMethod(builder, eventSystems); // 结束类和命名空间 builder.EndClass(); builder.EndNamespace(); // 输出源代码 context.AddSource("EventSystemRegistrar.g.cs", builder.ToString()); } /// /// 生成字段,用于存储已注册的事件处理器实例 /// private static void GenerateFields(SourceCodeBuilder builder, List eventSystems) { builder.AddComment("Store registered event handlers for UnRegister"); if (!eventSystems.Any()) { return; } foreach (var eventSystemTypeInfo in eventSystems) { var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}"; builder.AppendLine($"private {eventSystemTypeInfo.TypeFullName} {fieldName} = new {eventSystemTypeInfo.TypeFullName}();"); } builder.AppendLine(); } /// /// 生成 RegisterSystems 方法 /// private static void GenerateRegisterMethod(SourceCodeBuilder builder, List eventSystems) { builder.AddXmlComment("Register all Event Systems to the containers"); builder.BeginMethod( "public void RegisterSystems(" + "OneToManyList events, " + "OneToManyList asyncEvents, " + "OneToManyList sphereEvents)"); if (eventSystems.Any()) { foreach (var eventSystemTypeInfo in eventSystems) { var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}"; switch (eventSystemTypeInfo.EventSystemType) { case EventSystemType.EventSystem: { builder.AppendLine($"events.Add({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } case EventSystemType.AsyncEventSystem: { builder.AppendLine($"asyncEvents.Add({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } case EventSystemType.SphereEventSystem: { builder.AppendLine($"sphereEvents.Add({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } } } } builder.EndMethod(); builder.AppendLine(); } /// /// 生成 UnRegisterSystems 方法 /// private static void GenerateUnRegisterMethod(SourceCodeBuilder builder, List eventSystems) { builder.AddXmlComment("Unregister all Event Systems from the containers (called on hot reload)"); builder.BeginMethod( "public void UnRegisterSystems(" + "OneToManyList events, " + "OneToManyList asyncEvents, " + "OneToManyList sphereEvents)"); if (eventSystems.Any()) { foreach (var eventSystemTypeInfo in eventSystems) { var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}"; switch (eventSystemTypeInfo.EventSystemType) { case EventSystemType.EventSystem: { builder.AppendLine($"events.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } case EventSystemType.AsyncEventSystem: { builder.AppendLine($"asyncEvents.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } case EventSystemType.SphereEventSystem: { builder.AppendLine($"sphereEvents.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});"); continue; } } } } builder.EndMethod(); builder.AppendLine(); } /// /// 生成 Dispose 方法 /// private static void GenerateDisposeMethod(SourceCodeBuilder builder, List eventSystems) { builder.AddXmlComment("Dispose all resources"); builder.BeginMethod("public void Dispose()"); builder.AddComment("Clear all references"); if (eventSystems.Any()) { foreach (var eventSystemTypeInfo in eventSystems) { var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}"; builder.AppendLine($"{fieldName} = null;"); } } builder.EndMethod(); } /// /// 快速判断语法节点是否可能是 EventSystem 类 /// private static bool IsEventSystemClass(SyntaxNode node) { if (node is not ClassDeclarationSyntax classDecl) { return false; } // 必须有基类型列表(继承抽象类) if (classDecl.BaseList == null || classDecl.BaseList.Types.Count == 0) { return false; } // 快速检查是否包含可能的 EventSystem 基类名称 var baseListText = classDecl.BaseList.ToString(); return baseListText.Contains("AwakeSystem") || baseListText.Contains("AsyncEventSystem") || baseListText.Contains("SphereEventSystem"); } private enum EventSystemType { None, EventSystem, // EventSystem 事件类 AsyncEventSystem, // AsyncEventSystem 事件类 SphereEventSystem, // SphereEventSystem 事件类 } private sealed class EventSystemTypeInfo { public readonly EventSystemType EventSystemType; public readonly string TypeFullName; public readonly string TypeName; private EventSystemTypeInfo(EventSystemType eventSystemType, string typeFullName, string typeName) { EventSystemType = eventSystemType; TypeFullName = typeFullName; TypeName = typeName; } public static EventSystemTypeInfo Create(EventSystemType eventSystemType, INamedTypeSymbol symbol) { return new EventSystemTypeInfo( eventSystemType, symbol.GetFullName(), symbol.Name); } } } }