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);
}
}
}
}