Skip to content

Commit 0d654be

Browse files
committed
[大大解决泛型问题] 1. EntityTypeCollectionGenerator- 开放式泛型实体错误注册Debug;
2. EntitySystemGenerator - 添加开放式泛型System的正确分析与生成; 3. PoolCreatorGenerator - 支持池化泛型实体实例化; 4. 删掉Entity<T>抽象类, 它是多余的, 且限制了多参数泛型的声明.
1 parent de2e1ad commit 0d654be

File tree

8 files changed

+404
-233
lines changed

8 files changed

+404
-233
lines changed

‎Fantasy.Packages/Fantasy.Net/Runtime/Core/Entitas/Entity.cs‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -970,12 +970,4 @@ public void SetIsPool(bool isPool) { }
970970

971971
#endregion
972972
}
973-
974-
/// <summary>
975-
/// Entity的泛型抽象类,如果使用泛型Entity必须继承这个接口才可以使用
976-
/// </summary>
977-
/// <typeparam name="T"></typeparam>
978-
public abstract partial class Entity<T> : Entity
979-
{
980-
}
981973
}

‎Fantasy.Packages/Fantasy.SourceGenerator/Common/RoslynExtensions.cs‎

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,39 @@ public static string GetFullName(this ITypeSymbol typeSymbol, bool includeGlobal
8080
}
8181

8282
/// <summary>
83-
/// 检查类型是否可以被实例化(非抽象、非接口、非泛型定义
83+
/// 检查类型是否可以被实例化(非抽象、非接口、非无参泛型、非开放式泛型、非静态
8484
/// </summary>
8585
public static bool IsInstantiable(this INamedTypeSymbol typeSymbol)
8686
{
87-
// 允许:具体的类(非抽象、非静态)
88-
// 排除:抽象类、静态类、接口、开放泛型类型(如 MyClass<T> where T 未指定)
89-
return typeSymbol is { IsAbstract: false, IsStatic: false, TypeKind: TypeKind.Class };
87+
return typeSymbol.IsSpecific() && !typeSymbol.IsOpenGeneric();
88+
}
89+
90+
/// <summary>
91+
/// 是具体的。排除:抽象、静态、接口、无参泛型。
92+
/// </summary>
93+
public static bool IsSpecific(this INamedTypeSymbol typeSymbol) {
94+
return typeSymbol is { IsAbstract: false, IsStatic: false, TypeKind: TypeKind.Class, IsUnboundGenericType: false };
95+
}
96+
97+
/// <summary>
98+
/// 是否为开放式泛型(递归检查)
99+
/// </summary>
100+
public static bool IsOpenGeneric(this ITypeSymbol typeSymbol)
101+
{
102+
if (typeSymbol is INamedTypeSymbol namedType)
103+
{
104+
// 顶层类型参数是开放类型
105+
if (namedType.TypeArguments.Any(ta => ta.TypeKind == TypeKind.TypeParameter))
106+
return true;
107+
108+
// 递归检查
109+
foreach (var ta in namedType.TypeArguments)
110+
{
111+
if (ta.IsOpenGeneric())
112+
return true;
113+
}
114+
}
115+
return false;
90116
}
91117

92118
/// <summary>

‎Fantasy.Packages/Fantasy.SourceGenerator/Generators/EntitySystemGenerator.cs‎

Lines changed: 149 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Text;
8+
using System.Collections.Immutable;
89
#pragma warning disable CS8602 // Dereference of a possibly null reference.
910

1011
namespace Fantasy.SourceGenerator.Generators
@@ -18,54 +19,166 @@ public partial class EntitySystemGenerator : IIncrementalGenerator
1819
{
1920
public void Initialize(IncrementalGeneratorInitializationContext context)
2021
{
21-
// 查找所有实现了 IEntitySystem 相关接口的类
22+
// 查找所有 System 类
2223
var systemTypes = context.SyntaxProvider
2324
.CreateSyntaxProvider(
2425
predicate: static (node, _) => IsSystemClass(node),
25-
transform: static (ctx, _) => GetSystemTypeInfo(ctx))
26-
.Where(static info => info != null)
26+
transform: static (ctx, _) => GetSystemSymbol(ctx))
27+
.Where(static symbol => symbol != null)
2728
.Collect();
28-
// 组合编译信息和找到的类型
29-
var compilationAndTypes = context.CompilationProvider.Combine(systemTypes);
30-
// 注册源代码输出
31-
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
29+
30+
// 查找代码中所有使用到的闭合泛型 Entity
31+
var usedClosedGenericEntities = context.SyntaxProvider
32+
.CreateSyntaxProvider(
33+
predicate: static (node, _) => IsGenericEntityUsage(node),
34+
transform: static (ctx, _) => GetClosedEntitySymbol(ctx))
35+
.Where(static symbol => symbol != null)
36+
.Collect()
37+
.Select(static (types, _) => types.Distinct<INamedTypeSymbol>(SymbolEqualityComparer.Default).ToImmutableArray());
38+
39+
// 根据 闭合Entity 处理 System
40+
var finalSystemInfos = systemTypes.Combine(usedClosedGenericEntities)
41+
.Select((tuple, _) =>
3242
{
33-
if (CompilationHelper.IsSourceGeneratorDisabled(source.Left))
34-
{
35-
return;
36-
}
37-
38-
if (!CompilationHelper.HasFantasyDefine(source.Left))
39-
{
40-
return;
41-
}
42-
43-
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEntitySystemRegistrar") == null)
43+
var systems = tuple.Left;
44+
var usedEntities = tuple.Right;
45+
var result = new List<EntitySystemTypeInfo>();
46+
47+
foreach (var systemSymbol in systems)
4448
{
45-
return;
49+
// 泛型System
50+
if (systemSymbol!.IsOpenGeneric())
51+
{
52+
foreach (var entitySymbol in usedEntities)
53+
{
54+
// 尝试为 闭合Entity 构造 闭合System
55+
if (TryCreateClosedSystemInfo(systemSymbol!, entitySymbol!, out var info))
56+
{
57+
result.Add(info!);
58+
}
59+
}
60+
}
61+
else // 普通 System
62+
{
63+
var info = CreateInfoFromSymbol(systemSymbol!);
64+
if (info != null)
65+
{
66+
result.Add(info);
67+
}
68+
}
4669
}
70+
return result;
71+
});
4772

48-
GenerateRegistrationCode(spc, source.Left, source.Right!);
73+
//组合编译信息输出
74+
var source = context.CompilationProvider.Combine(finalSystemInfos);
75+
context.RegisterSourceOutput(source, (spc, source) =>
76+
{
77+
if (CompilationHelper.IsSourceGeneratorDisabled(source.Left)) return;
78+
if (!CompilationHelper.HasFantasyDefine(source.Left)) return;
79+
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEntitySystemRegistrar") == null) return;
80+
81+
GenerateRegistrationCode(spc, source.Left, source.Right);
4982
});
5083
}
51-
52-
private static EntitySystemTypeInfo? GetSystemTypeInfo(GeneratorSyntaxContext context)
84+
85+
86+
#region Predicate & Transform
87+
88+
private static INamedTypeSymbol? GetSystemSymbol(GeneratorSyntaxContext context)
5389
{
5490
var classDecl = (ClassDeclarationSyntax)context.Node;
91+
var symbol = context.SemanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
92+
if (symbol == null || symbol.IsAbstract) return null; // 忽略抽象类
5593

56-
if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol || !symbol.IsInstantiable())
57-
{
94+
// 目标实体不能是闭合泛型
95+
var targetEntityArg = GetSystemTargetEntityArg(symbol!);
96+
if(targetEntityArg == null) return null;
97+
if(targetEntityArg.IsGenericType && !targetEntityArg.IsOpenGeneric()) return null;
98+
99+
return symbol;
100+
}
101+
102+
// 判断代码中使用到的闭合泛型 Entity
103+
private static bool IsGenericEntityUsage(SyntaxNode node) => node is GenericNameSyntax;
104+
105+
private static INamedTypeSymbol? GetClosedEntitySymbol(GeneratorSyntaxContext context)
106+
{
107+
if (context.Node is not GenericNameSyntax genericName) return null;
108+
109+
var symbolInfo = context.SemanticModel.GetSymbolInfo(genericName);
110+
var symbol = symbolInfo.Symbol as INamedTypeSymbol;
111+
112+
if (symbol == null) return null;
113+
if (symbol.IsOpenGeneric()) return null; // 确保是闭合泛型
114+
115+
// 检查继承自 Entity
116+
if (!EntityTypeCollectionGenerator.InheritsFromEntitySymbol(symbol)) return null;
117+
118+
return symbol;
119+
}
120+
121+
#endregion
122+
123+
#region Generic Analysis
124+
125+
/// <summary>
126+
/// 获取System类的目标实体参数
127+
/// </summary>
128+
private static INamedTypeSymbol? GetSystemTargetEntityArg(INamedTypeSymbol systemSymbol) {
129+
var baseType = systemSymbol.BaseType;
130+
131+
if (!baseType.IsGenericType)
58132
return null;
59-
}
60-
61-
var baseType = symbol.BaseType;
62133

63-
if (!baseType.IsGenericType)
134+
return baseType.TypeArguments.FirstOrDefault() as INamedTypeSymbol;
135+
}
136+
137+
///<summary>
138+
/// NOTE : 需要提高完备性
139+
/// 尝试将一个 开放泛型System 和一个 闭合泛型Entity 进行匹配,
140+
/// 并生成闭合的 System 信息。
141+
///</summary>
142+
private static bool TryCreateClosedSystemInfo(INamedTypeSymbol systemSymbol, INamedTypeSymbol entitySymbol, out EntitySystemTypeInfo? info)
143+
{
144+
// 1. 获取 System 关注的实体基类型 (从 AwakeSystem<T> 中提取 T)
145+
var targetEntityArg = GetSystemTargetEntityArg(systemSymbol);
146+
info = null;
147+
148+
// 2. 检查 Entity 是否匹配 System 的定义
149+
150+
// 比如 泛型System 的参数结构 AGenericEntity<T1, T2> 与对应的实体 AGenericEntity<EnumA, EnumB>,
151+
// 它们的 ConstructedFrom 必须吻合
152+
153+
if (!SymbolEqualityComparer.Default.Equals(targetEntityArg.ConstructedFrom, entitySymbol.ConstructedFrom))
154+
return false;
155+
156+
// 3. 检查参数数量是否相等
157+
var systemTypeArgs = entitySymbol.TypeArguments.ToArray();
158+
if (systemTypeArgs.Length != systemSymbol.TypeParameters.Length) return false;
159+
160+
// 4. 构造闭合的 System 类型
161+
// 使用 Entity 的泛型参数 (EnumA, EnumB) 来填充 System 的泛型参数
162+
try
64163
{
65-
return null;
164+
var constructedSystemSymbol = systemSymbol.Construct(systemTypeArgs);
165+
info = CreateInfoFromSymbol(constructedSystemSymbol);
166+
return info != null;
167+
}
168+
catch
169+
{
170+
return false;
66171
}
67-
68-
return baseType.Name switch
172+
}
173+
174+
private static EntitySystemTypeInfo? CreateInfoFromSymbol(INamedTypeSymbol symbol)
175+
{
176+
var baseType = symbol.BaseType;
177+
if (baseType == null) return null;
178+
179+
var typeName = baseType.ConstructedFrom.Name;
180+
181+
return typeName switch
69182
{
70183
"AwakeSystem" => EntitySystemTypeInfo.Create(EntitySystemType.AwakeSystem, symbol),
71184
"UpdateSystem" => EntitySystemTypeInfo.Create(EntitySystemType.UpdateSystem, symbol),
@@ -75,7 +188,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
75188
_ => null
76189
};
77190
}
78-
191+
192+
#endregion
193+
79194
private static void GenerateRegistrationCode(
80195
SourceProductionContext context,
81196
Compilation compilation,
@@ -218,16 +333,12 @@ private static void GenerateSystemCode(SourceCodeBuilder builder, string defineC
218333
private static bool IsSystemClass(SyntaxNode node)
219334
{
220335
if (node is not ClassDeclarationSyntax classDecl)
221-
{
222336
return false;
223-
}
224337

225338
// 必须有基类型列表(继承抽象类)
226339
if (classDecl.BaseList == null || classDecl.BaseList.Types.Count == 0)
227-
{
228340
return false;
229-
}
230-
341+
231342
// 快速检查是否包含可能的 EntitySystem 基类名称
232343
var baseListText = classDecl.BaseList.ToString();
233344
return baseListText.Contains("AwakeSystem") ||
@@ -275,7 +386,7 @@ private EntitySystemTypeInfo(
275386
public static EntitySystemTypeInfo Create(EntitySystemType entitySystemType, INamedTypeSymbol symbol)
276387
{
277388
// 获取泛型参数 T (例如:AwakeSystem<T> 中的 T)
278-
var entityType = symbol.BaseType?.TypeArguments.FirstOrDefault();
389+
var entityType = GetSystemTargetEntityArg(symbol);
279390
var entityTypeFullName = entityType?.GetFullName(false) ?? "Unknown";
280391

281392
// // 使用与运行时相同的算法计算哈希值

0 commit comments

Comments
 (0)