From 09f751a4f7d482146520fabc346eaaf0f85607cc Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:36:15 +0800 Subject: [PATCH 1/8] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=20CQRS=20?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E6=A8=A1=E5=BC=8F=E5=92=8C=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=B3=BB=E7=BB=9F=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CQRS 核心概念、命令查询处理器实现指南 - 添加 CQRS 高级用法包括通知发布、管道行为和流式处理 - 提供 CQRS 最佳实践和常见问题解决方案 - 添加游戏配置系统完整接入模板和运行时读取示例 - 包含 YAML 配置文件和 JSON Schema 结构定义说明 - 提供 Godot 引擎配置桥接和热重载功能使用指南 - 添加架构模块集成和生成查询辅助功能文档 --- CLAUDE.md | 5 +- .../Architectures/IArchitecture.cs | 15 -- .../Ioc/IIocContainer.cs | 15 +- .../AutoRegisterModuleAttribute.cs | 0 .../Architectures/RegisterModelAttribute.cs | 0 .../Architectures/RegisterSystemAttribute.cs | 0 .../Architectures/RegisterUtilityAttribute.cs | 0 .../Bases/PriorityAttribute.cs | 2 +- .../Directory.Build.props | 0 .../Enums/GenerateEnumExtensionsAttribute.cs | 2 +- ....Core.SourceGenerators.Abstractions.csproj | 0 .../GlobalUsings.cs | 2 +- .../Logging/LogAttribute.cs | 2 +- .../Rule/ContextAwareAttribute.cs | 2 +- .../Rule/GetAllAttribute.cs | 2 +- .../Rule/GetModelAttribute.cs | 2 +- .../Rule/GetModelsAttribute.cs | 2 +- .../Rule/GetServiceAttribute.cs | 2 +- .../Rule/GetServicesAttribute.cs | 2 +- .../Rule/GetSystemAttribute.cs | 2 +- .../Rule/GetSystemsAttribute.cs | 2 +- .../Rule/GetUtilitiesAttribute.cs | 2 +- .../Rule/GetUtilityAttribute.cs | 2 +- .../AnalyzerReleases.Shipped.md | 0 .../AnalyzerReleases.Unshipped.md | 10 -- .../Analyzers/ContextRegistrationAnalyzer.cs | 78 ++++++---- .../Analyzers/PriorityUsageAnalyzer.cs | 4 +- .../AutoRegisterModuleGenerator.cs | 0 .../Bases/PriorityGenerator.cs | 6 +- .../AutoRegisterModuleDiagnostics.cs | 0 .../Diagnostics/ContextAwareDiagnostic.cs | 6 +- .../Diagnostics/ContextGetDiagnostics.cs | 2 +- .../ContextRegistrationDiagnostics.cs | 0 .../Diagnostics/LoggerDiagnostic.cs | 6 +- .../Diagnostics/PriorityDiagnostic.cs | 4 +- .../Enums/EnumExtensionsGenerator.cs | 7 +- .../GFramework.Core.SourceGenerators.csproj | 4 +- ...u.GFramework.Core.SourceGenerators.targets | 15 ++ .../GlobalUsings.cs | 2 +- .../Logging/LoggerGenerator.cs | 7 +- .../README.md | 0 .../Rule/ContextAwareGenerator.cs | 8 +- .../Rule/ContextGetGenerator.cs | 3 +- .../ArchitectureModulesBehaviorTests.cs | 22 --- .../RegistryInitializationHookBaseTests.cs | 12 -- .../MediatorCompatibilityDeprecationTests.cs | 99 ------------- .../GFramework.Core.Tests.csproj | 8 +- GFramework.Core/Architectures/Architecture.cs | 16 --- .../Architectures/ArchitectureModules.cs | 15 -- .../Extensions/MediatorCoroutineExtensions.cs | 47 ------ .../ContextAwareMediatorCommandExtensions.cs | 49 ------- .../ContextAwareMediatorExtensions.cs | 123 ---------------- .../ContextAwareMediatorQueryExtensions.cs | 48 ------- GFramework.Core/Ioc/MicrosoftDiContainer.cs | 15 -- .../Cqrs/CqrsHandlerRegistryGenerator.cs | 135 ++++++++++++++++-- .../GFramework.Cqrs.SourceGenerators.csproj | 49 +++++++ .../GlobalUsings.cs | 13 ++ .../AnalyzerReleases.Shipped.md | 2 + .../AnalyzerReleases.Unshipped.md | 17 +++ .../Config/SchemaConfigGenerator.cs | 6 +- .../Diagnostics/ConfigSchemaDiagnostics.cs | 0 .../GFramework.Game.SourceGenerators.csproj | 55 +++++++ ...u.GFramework.Game.SourceGenerators.targets | 19 +-- .../GlobalUsings.cs | 14 ++ .../GFramework.Game.Tests.csproj | 11 +- .../Cqrs/CqrsHandlerRegistryGeneratorTests.cs | 20 ++- .../GFramework.SourceGenerators.Tests.csproj | 4 +- GFramework.csproj | 26 +++- GFramework.sln | 84 +++++++---- docs/zh-CN/core/cqrs.md | 5 +- docs/zh-CN/game/config-system.md | 17 ++- 71 files changed, 485 insertions(+), 671 deletions(-) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Architectures/AutoRegisterModuleAttribute.cs (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Architectures/RegisterModelAttribute.cs (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Architectures/RegisterSystemAttribute.cs (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Architectures/RegisterUtilityAttribute.cs (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Bases/PriorityAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Directory.Build.props (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Enums/GenerateEnumExtensionsAttribute.cs (99%) rename GFramework.SourceGenerators.Abstractions/GFramework.SourceGenerators.Abstractions.csproj => GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj (100%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/GlobalUsings.cs (95%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Logging/LogAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/ContextAwareAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetAllAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetModelAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetModelsAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetServiceAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetServicesAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetSystemAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetSystemsAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetUtilitiesAttribute.cs (99%) rename {GFramework.SourceGenerators.Abstractions => GFramework.Core.SourceGenerators.Abstractions}/Rule/GetUtilityAttribute.cs (99%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/AnalyzerReleases.Shipped.md (100%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/AnalyzerReleases.Unshipped.md (73%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Analyzers/ContextRegistrationAnalyzer.cs (94%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Analyzers/PriorityUsageAnalyzer.cs (98%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Architectures/AutoRegisterModuleGenerator.cs (100%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Bases/PriorityGenerator.cs (97%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/AutoRegisterModuleDiagnostics.cs (100%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/ContextAwareDiagnostic.cs (86%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/ContextGetDiagnostics.cs (99%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/ContextRegistrationDiagnostics.cs (100%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/LoggerDiagnostic.cs (87%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Diagnostics/PriorityDiagnostic.cs (99%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Enums/EnumExtensionsGenerator.cs (96%) rename GFramework.SourceGenerators/GFramework.SourceGenerators.csproj => GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj (92%) create mode 100644 GFramework.Core.SourceGenerators/GeWuYou.GFramework.Core.SourceGenerators.targets rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/GlobalUsings.cs (97%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Logging/LoggerGenerator.cs (95%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/README.md (100%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Rule/ContextAwareGenerator.cs (97%) rename {GFramework.SourceGenerators => GFramework.Core.SourceGenerators}/Rule/ContextGetGenerator.cs (99%) delete mode 100644 GFramework.Core.Tests/Cqrs/MediatorCompatibilityDeprecationTests.cs delete mode 100644 GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs delete mode 100644 GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs delete mode 100644 GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs delete mode 100644 GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs rename {GFramework.SourceGenerators => GFramework.Cqrs.SourceGenerators}/Cqrs/CqrsHandlerRegistryGenerator.cs (91%) create mode 100644 GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj create mode 100644 GFramework.Cqrs.SourceGenerators/GlobalUsings.cs create mode 100644 GFramework.Game.SourceGenerators/AnalyzerReleases.Shipped.md create mode 100644 GFramework.Game.SourceGenerators/AnalyzerReleases.Unshipped.md rename {GFramework.SourceGenerators => GFramework.Game.SourceGenerators}/Config/SchemaConfigGenerator.cs (99%) rename {GFramework.SourceGenerators => GFramework.Game.SourceGenerators}/Diagnostics/ConfigSchemaDiagnostics.cs (100%) create mode 100644 GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj rename GFramework.SourceGenerators/GeWuYou.GFramework.SourceGenerators.targets => GFramework.Game.SourceGenerators/GeWuYou.GFramework.Game.SourceGenerators.targets (57%) create mode 100644 GFramework.Game.SourceGenerators/GlobalUsings.cs diff --git a/CLAUDE.md b/CLAUDE.md index da7e13c6..b847b5cd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,9 +73,8 @@ Architecture 负责统一生命周期编排,核心阶段包括: ### CQRS -命令与查询分离,支持同步与异步执行。当前版本内建自有 CQRS runtime、行为管道和 handler 自动注册;公开 API 里仍保留少量历史 -`Mediator` 命名以兼容旧调用点,但这些别名已进入正式弃用周期:新代码应使用 `Cqrs` 命名入口,旧别名会继续兼容一段时间并计划在未来 -major 版本中移除。 +命令与查询分离,支持同步与异步执行。当前版本内建自有 CQRS runtime、行为管道和 handler 自动注册;历史 `Mediator` +兼容别名已从公开 API 移除,统一使用 `Cqrs` 命名入口。 ### EventBus diff --git a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs index e1687ff9..bbdbf25b 100644 --- a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs +++ b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.Reflection; using GFramework.Core.Abstractions.Lifecycle; using GFramework.Core.Abstractions.Model; @@ -82,20 +81,6 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia void RegisterCqrsPipelineBehavior() where TBehavior : class; - /// - /// 注册 CQRS 请求管道行为。 - /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 - /// 新代码不应继续依赖该别名;兼容层计划在未来的 major 版本中移除。 - /// 既支持实现 IPipelineBehavior<,> 的开放泛型行为类型, - /// 也支持绑定到单一请求/响应对的封闭行为类型。 - /// - /// 行为类型,必须是引用类型 - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete( - "Use RegisterCqrsPipelineBehavior() instead. This compatibility alias will be removed in a future major version.")] - void RegisterMediatorBehavior() - where TBehavior : class; - /// /// 从指定程序集显式注册 CQRS 处理器。 /// 当处理器位于默认架构程序集之外的模块或扩展程序集中时,可在初始化阶段调用该入口接入对应程序集。 diff --git a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs index 3149b3c4..26e80968 100644 --- a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs +++ b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs @@ -1,5 +1,4 @@ -using System.ComponentModel; -using System.Reflection; +using System.Reflection; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Systems; @@ -97,18 +96,6 @@ public interface IIocContainer : IContextAware void RegisterCqrsPipelineBehavior() where TBehavior : class; - /// - /// 注册 CQRS 请求管道行为。 - /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 - /// 新代码不应继续依赖该别名;兼容层计划在未来的 major 版本中移除。 - /// - /// 行为类型,必须是引用类型 - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete( - "Use RegisterCqrsPipelineBehavior() instead. This compatibility alias will be removed in a future major version.")] - void RegisterMediatorBehavior() - where TBehavior : class; - /// /// 从指定程序集显式注册 CQRS 处理器。 /// 该入口适用于处理器不位于默认架构程序集中的场景,例如扩展包、模块程序集或拆分后的业务程序集。 diff --git a/GFramework.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs similarity index 100% rename from GFramework.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs diff --git a/GFramework.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs similarity index 100% rename from GFramework.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs diff --git a/GFramework.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs similarity index 100% rename from GFramework.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs diff --git a/GFramework.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs similarity index 100% rename from GFramework.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs diff --git a/GFramework.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs index d406bb92..42459498 100644 --- a/GFramework.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs @@ -32,4 +32,4 @@ public sealed class PriorityAttribute : Attribute /// 获取优先级值 /// public int Value { get; } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Directory.Build.props b/GFramework.Core.SourceGenerators.Abstractions/Directory.Build.props similarity index 100% rename from GFramework.SourceGenerators.Abstractions/Directory.Build.props rename to GFramework.Core.SourceGenerators.Abstractions/Directory.Build.props diff --git a/GFramework.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs index 4780fc78..c5136a88 100644 --- a/GFramework.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs @@ -15,4 +15,4 @@ public sealed class GenerateEnumExtensionsAttribute : Attribute /// 是否生成一个 IsIn(params T[]) 方法以简化多值判断(默认 true)。 /// public bool GenerateIsInMethod { get; set; } = true; -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/GFramework.SourceGenerators.Abstractions.csproj b/GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj similarity index 100% rename from GFramework.SourceGenerators.Abstractions/GFramework.SourceGenerators.Abstractions.csproj rename to GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj diff --git a/GFramework.SourceGenerators.Abstractions/GlobalUsings.cs b/GFramework.Core.SourceGenerators.Abstractions/GlobalUsings.cs similarity index 95% rename from GFramework.SourceGenerators.Abstractions/GlobalUsings.cs rename to GFramework.Core.SourceGenerators.Abstractions/GlobalUsings.cs index 4d271811..68e12683 100644 --- a/GFramework.SourceGenerators.Abstractions/GlobalUsings.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/GlobalUsings.cs @@ -15,4 +15,4 @@ global using System; global using System.Collections.Generic; global using System.Linq; global using System.Threading; -global using System.Threading.Tasks; \ No newline at end of file +global using System.Threading.Tasks; diff --git a/GFramework.SourceGenerators.Abstractions/Logging/LogAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Logging/LogAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs index 679d3b63..0cddf94c 100644 --- a/GFramework.SourceGenerators.Abstractions/Logging/LogAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs @@ -35,4 +35,4 @@ public sealed class LogAttribute : Attribute /// 访问修饰符 public string AccessModifier { get; set; } = "private"; -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs index d1423583..7cb75238 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs @@ -6,4 +6,4 @@ [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class ContextAwareAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs index 5722ff42..cd310da6 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class GetAllAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs index 31e6a8d3..b97d395f 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetModelAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs index fb14d7c7..a6173a25 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetModelsAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs index 5a8563fd..46c23320 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetServiceAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs index 19cff728..5341d6a3 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetServicesAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs index c3352b2e..072cd112 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetSystemAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs index d8b1c037..da214089 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetSystemsAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs index 9b78d74f..afeb63ee 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetUtilitiesAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs similarity index 99% rename from GFramework.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs rename to GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs index 5c87bc45..99059a96 100644 --- a/GFramework.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs @@ -6,4 +6,4 @@ namespace GFramework.SourceGenerators.Abstractions.Rule; [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetUtilityAttribute : Attribute { -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/AnalyzerReleases.Shipped.md b/GFramework.Core.SourceGenerators/AnalyzerReleases.Shipped.md similarity index 100% rename from GFramework.SourceGenerators/AnalyzerReleases.Shipped.md rename to GFramework.Core.SourceGenerators/AnalyzerReleases.Shipped.md diff --git a/GFramework.SourceGenerators/AnalyzerReleases.Unshipped.md b/GFramework.Core.SourceGenerators/AnalyzerReleases.Unshipped.md similarity index 73% rename from GFramework.SourceGenerators/AnalyzerReleases.Unshipped.md rename to GFramework.Core.SourceGenerators/AnalyzerReleases.Unshipped.md index 752f563a..9e0a6cb0 100644 --- a/GFramework.SourceGenerators/AnalyzerReleases.Unshipped.md +++ b/GFramework.Core.SourceGenerators/AnalyzerReleases.Unshipped.md @@ -18,16 +18,6 @@ GF_ContextRegistration_001 | GFramework.SourceGenerators.rule | Warning | ContextRegistrationDiagnostics GF_ContextRegistration_002 | GFramework.SourceGenerators.rule | Warning | ContextRegistrationDiagnostics GF_ContextRegistration_003 | GFramework.SourceGenerators.rule | Warning | ContextRegistrationDiagnostics - GF_ConfigSchema_001 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_002 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_003 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_004 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_005 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_006 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_007 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_008 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_009 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics - GF_ConfigSchema_010 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics GF_AutoModule_001 | GFramework.SourceGenerators.Architecture | Error | AutoRegisterModuleDiagnostics GF_AutoModule_002 | GFramework.SourceGenerators.Architecture | Error | AutoRegisterModuleDiagnostics GF_AutoModule_003 | GFramework.SourceGenerators.Architecture | Error | AutoRegisterModuleDiagnostics diff --git a/GFramework.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs similarity index 94% rename from GFramework.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs rename to GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs index ffbc0aae..dcd25ca8 100644 --- a/GFramework.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; @@ -12,6 +11,17 @@ namespace GFramework.SourceGenerators.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer { + private static readonly IReadOnlyDictionary _contextAwareBindingNames = + new Dictionary(StringComparer.Ordinal) + { + ["GetModel"] = ComponentKind.Model, + ["GetModels"] = ComponentKind.Model, + ["GetSystem"] = ComponentKind.System, + ["GetSystems"] = ComponentKind.System, + ["GetUtility"] = ComponentKind.Utility, + ["GetUtilities"] = ComponentKind.Utility + }; + /// /// 当前分析器支持的诊断规则。 /// @@ -58,10 +68,12 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer if (context.Node is not VariableDeclaratorSyntax variableDeclarator) return; - if (context.SemanticModel.GetDeclaredSymbol(variableDeclarator, context.CancellationToken) is not IFieldSymbol fieldSymbol) + if (context.SemanticModel.GetDeclaredSymbol(variableDeclarator, context.CancellationToken) is not IFieldSymbol + fieldSymbol) return; - if (!TryCreateBindingRequest(fieldSymbol, variableDeclarator.Identifier.GetLocation(), symbols, out var request)) + if (!TryCreateBindingRequest(fieldSymbol, variableDeclarator.Identifier.GetLocation(), symbols, + out var request)) return; ReportMissingRegistration(context, registrationIndex, request); @@ -272,17 +284,6 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer return namedType.TypeArguments[0] as INamedTypeSymbol; } - private static readonly IReadOnlyDictionary _contextAwareBindingNames = - new Dictionary(StringComparer.Ordinal) - { - ["GetModel"] = ComponentKind.Model, - ["GetModels"] = ComponentKind.Model, - ["GetSystem"] = ComponentKind.System, - ["GetSystems"] = ComponentKind.System, - ["GetUtility"] = ComponentKind.Utility, - ["GetUtilities"] = ComponentKind.Utility - }; - private enum ComponentKind { Model, @@ -368,22 +369,35 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer { return new SymbolCache( compilation.GetTypeByMetadataName($"{PathContests.CoreNamespace}.Architectures.Architecture"), - compilation.GetTypeByMetadataName($"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitecture"), - compilation.GetTypeByMetadataName($"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitectureModule"), - compilation.GetTypeByMetadataName($"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitectureContext"), + compilation.GetTypeByMetadataName( + $"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitecture"), + compilation.GetTypeByMetadataName( + $"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitectureModule"), + compilation.GetTypeByMetadataName( + $"{PathContests.CoreAbstractionsNamespace}.Architectures.IArchitectureContext"), compilation.GetTypeByMetadataName("System.Collections.Generic.IReadOnlyList`1"), - compilation.GetTypeByMetadataName($"{PathContests.CoreNamespace}.Extensions.ContextAwareServiceExtensions"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetModelAttribute"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetModelsAttribute"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetSystemAttribute"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetSystemsAttribute"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetUtilityAttribute"), - compilation.GetTypeByMetadataName($"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetUtilitiesAttribute")); + compilation.GetTypeByMetadataName( + $"{PathContests.CoreNamespace}.Extensions.ContextAwareServiceExtensions"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetModelAttribute"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetModelsAttribute"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetSystemAttribute"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetSystemsAttribute"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetUtilityAttribute"), + compilation.GetTypeByMetadataName( + $"{PathContests.SourceGeneratorsAbstractionsPath}.Rule.GetUtilitiesAttribute")); } } private sealed class RegistrationIndex { + private readonly Compilation _compilation; + private readonly IReadOnlyDictionary _registrations; + private RegistrationIndex( Compilation compilation, IReadOnlyDictionary registrations) @@ -392,14 +406,12 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer _registrations = registrations; } - private readonly Compilation _compilation; - private readonly IReadOnlyDictionary _registrations; - public static RegistrationIndex Build( Compilation compilation, SymbolCache symbols) { - var registrations = new Dictionary(SymbolEqualityComparer.Default); + var registrations = + new Dictionary(SymbolEqualityComparer.Default); foreach (var type in SymbolHelpers.EnumerateNamedTypes(compilation.Assembly.GlobalNamespace)) { @@ -690,7 +702,8 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer return helperMethod.DeclaringSyntaxReferences.Length > 0; } - helperMethod = SymbolHelpers.ResolveHierarchyMethodImplementation(targetMethod, concreteType) ?? targetMethod; + helperMethod = SymbolHelpers.ResolveHierarchyMethodImplementation(targetMethod, concreteType) ?? + targetMethod; return helperMethod.DeclaringSyntaxReferences.Length > 0; } } @@ -813,9 +826,12 @@ public sealed class ContextRegistrationAnalyzer : DiagnosticAnalyzer if (SymbolEqualityComparer.Default.Equals(candidate.OriginalDefinition, method.OriginalDefinition)) return candidate; - for (var overridden = candidate.OverriddenMethod; overridden != null; overridden = overridden.OverriddenMethod) + for (var overridden = candidate.OverriddenMethod; + overridden != null; + overridden = overridden.OverriddenMethod) { - if (SymbolEqualityComparer.Default.Equals(overridden.OriginalDefinition, method.OriginalDefinition)) + if (SymbolEqualityComparer.Default.Equals(overridden.OriginalDefinition, + method.OriginalDefinition)) return candidate; } } diff --git a/GFramework.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs similarity index 98% rename from GFramework.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs rename to GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs index 6fc3a961..b58871a1 100644 --- a/GFramework.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs @@ -1,6 +1,4 @@ -using System.Collections.Immutable; using GFramework.SourceGenerators.Diagnostics; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; @@ -111,4 +109,4 @@ public sealed class PriorityUsageAnalyzer : DiagnosticAnalyzer { return type.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, interfaceType)); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs b/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs similarity index 100% rename from GFramework.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs rename to GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs diff --git a/GFramework.SourceGenerators/Bases/PriorityGenerator.cs b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs similarity index 97% rename from GFramework.SourceGenerators/Bases/PriorityGenerator.cs rename to GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs index 62985003..b0331900 100644 --- a/GFramework.SourceGenerators/Bases/PriorityGenerator.cs +++ b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs @@ -1,10 +1,6 @@ -using System.Text; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Diagnostics; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.Bases; @@ -150,4 +146,4 @@ public sealed class PriorityGenerator : MetadataAttributeClassGeneratorBase return $"{metadataName}.Priority.g.cs"; } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs similarity index 100% rename from GFramework.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs rename to GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs diff --git a/GFramework.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs similarity index 86% rename from GFramework.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs rename to GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs index 94dbd837..70b06fc8 100644 --- a/GFramework.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs @@ -1,6 +1,4 @@ -using Microsoft.CodeAnalysis; - -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.SourceGenerators.Diagnostics; /// /// 提供与上下文感知相关的诊断规则定义 @@ -18,4 +16,4 @@ public static class ContextAwareDiagnostic DiagnosticSeverity.Error, true ); -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs similarity index 99% rename from GFramework.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs rename to GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs index 1f18ac60..dd9534d4 100644 --- a/GFramework.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs @@ -96,4 +96,4 @@ public static class ContextGetDiagnostics SourceGeneratorsRuleCategory, DiagnosticSeverity.Error, true); -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs similarity index 100% rename from GFramework.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs rename to GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs diff --git a/GFramework.SourceGenerators/Diagnostics/LoggerDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs similarity index 87% rename from GFramework.SourceGenerators/Diagnostics/LoggerDiagnostic.cs rename to GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs index 26d5a78b..0ff2bf90 100644 --- a/GFramework.SourceGenerators/Diagnostics/LoggerDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs @@ -1,6 +1,4 @@ -using Microsoft.CodeAnalysis; - -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.SourceGenerators.Diagnostics; /// /// 提供诊断描述符的静态类,用于GFramework日志生成器的编译时检查 @@ -18,4 +16,4 @@ internal static class LoggerDiagnostics "GFramework.Godot.Logging", DiagnosticSeverity.Warning, true); -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Diagnostics/PriorityDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs similarity index 99% rename from GFramework.SourceGenerators/Diagnostics/PriorityDiagnostic.cs rename to GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs index df7d7813..86030071 100644 --- a/GFramework.SourceGenerators/Diagnostics/PriorityDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs @@ -1,5 +1,3 @@ -using Microsoft.CodeAnalysis; - namespace GFramework.SourceGenerators.Diagnostics; /// @@ -86,4 +84,4 @@ internal static class PriorityDiagnostic isEnabledByDefault: true, description: "当获取实现了 IPrioritized 接口的服务时,应使用 GetAllByPriority 方法以确保按优先级排序." ); -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Enums/EnumExtensionsGenerator.cs b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs similarity index 96% rename from GFramework.SourceGenerators/Enums/EnumExtensionsGenerator.cs rename to GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs index 2a5e3040..b04a3640 100644 --- a/GFramework.SourceGenerators/Enums/EnumExtensionsGenerator.cs +++ b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs @@ -1,9 +1,6 @@ -using System.Text; -using GFramework.SourceGenerators.Common.Constants; +using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.Enums; @@ -110,4 +107,4 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase { return $"{symbol.Name}.EnumExtensions.g.cs"; } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/GFramework.SourceGenerators.csproj b/GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj similarity index 92% rename from GFramework.SourceGenerators/GFramework.SourceGenerators.csproj rename to GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj index 57810ee2..72a2c200 100644 --- a/GFramework.SourceGenerators/GFramework.SourceGenerators.csproj +++ b/GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj @@ -30,7 +30,7 @@ - + @@ -63,6 +63,6 @@ - + diff --git a/GFramework.Core.SourceGenerators/GeWuYou.GFramework.Core.SourceGenerators.targets b/GFramework.Core.SourceGenerators/GeWuYou.GFramework.Core.SourceGenerators.targets new file mode 100644 index 00000000..4a1d4f8e --- /dev/null +++ b/GFramework.Core.SourceGenerators/GeWuYou.GFramework.Core.SourceGenerators.targets @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/GFramework.SourceGenerators/GlobalUsings.cs b/GFramework.Core.SourceGenerators/GlobalUsings.cs similarity index 97% rename from GFramework.SourceGenerators/GlobalUsings.cs rename to GFramework.Core.SourceGenerators/GlobalUsings.cs index f098c130..a2428fdc 100644 --- a/GFramework.SourceGenerators/GlobalUsings.cs +++ b/GFramework.Core.SourceGenerators/GlobalUsings.cs @@ -24,4 +24,4 @@ global using Microsoft.CodeAnalysis.Text; global using System.Globalization; global using System.IO; global using System.Text; -global using System.Text.Json; \ No newline at end of file +global using System.Text.Json; diff --git a/GFramework.SourceGenerators/Logging/LoggerGenerator.cs b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs similarity index 95% rename from GFramework.SourceGenerators/Logging/LoggerGenerator.cs rename to GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs index 8f3b789f..e861f0c3 100644 --- a/GFramework.SourceGenerators/Logging/LoggerGenerator.cs +++ b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs @@ -1,10 +1,7 @@ -using System.Text; -using GFramework.SourceGenerators.Abstractions.Logging; +using GFramework.SourceGenerators.Abstractions.Logging; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Generator; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.Logging; @@ -97,4 +94,4 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase { return $"{symbol.Name}.Logger.g.cs"; } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/README.md b/GFramework.Core.SourceGenerators/README.md similarity index 100% rename from GFramework.SourceGenerators/README.md rename to GFramework.Core.SourceGenerators/README.md diff --git a/GFramework.SourceGenerators/Rule/ContextAwareGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs similarity index 97% rename from GFramework.SourceGenerators/Rule/ContextAwareGenerator.cs rename to GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs index bd48ab3a..68c2ad45 100644 --- a/GFramework.SourceGenerators/Rule/ContextAwareGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs @@ -1,11 +1,7 @@ -using System.Text; -using GFramework.SourceGenerators.Common.Constants; +using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Diagnostics; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.Rule; @@ -251,4 +247,4 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase break; } } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators/Rule/ContextGetGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs similarity index 99% rename from GFramework.SourceGenerators/Rule/ContextGetGenerator.cs rename to GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs index c6261f4c..c3915b00 100644 --- a/GFramework.SourceGenerators/Rule/ContextGetGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs @@ -1,4 +1,3 @@ -using System.Text; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Extensions; @@ -894,4 +893,4 @@ public sealed class ContextGetGenerator : IIncrementalGenerator public List FieldCandidates { get; } = []; public ClassDeclarationSyntax? GetAllDeclaration { get; set; } } -} \ No newline at end of file +} diff --git a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs index 493f3590..195a0f3c 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs @@ -78,28 +78,6 @@ public class ArchitectureModulesBehaviorTests await architecture.DestroyAsync(); } - /// - /// 验证兼容别名 RegisterMediatorBehavior 仍会把 CQRS 行为接入请求管道。 - /// - [Test] - public async Task RegisterMediatorBehavior_Should_Apply_Pipeline_Behavior_To_Request() - { - var architecture = new ModuleTestArchitecture(target => - target.RegisterMediatorBehavior>()); - - await architecture.InitializeAsync(); - - var response = await architecture.Context.SendRequestAsync(new ModuleBehaviorRequest()); - - Assert.Multiple(() => - { - Assert.That(response, Is.EqualTo("handled")); - Assert.That(TrackingPipelineBehavior.InvocationCount, Is.EqualTo(1)); - }); - - await architecture.DestroyAsync(); - } - /// /// 用于测试模块行为的最小架构实现。 /// diff --git a/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs b/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs index b224804d..6882ced4 100644 --- a/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs +++ b/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs @@ -206,12 +206,6 @@ public class TestArchitectureWithRegistry : IArchitecture throw new NotImplementedException(); } - [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] - public void RegisterMediatorBehavior() where TBehavior : class - { - RegisterCqrsPipelineBehavior(); - } - public IArchitectureModule InstallModule(IArchitectureModule module) { throw new NotImplementedException(); @@ -357,12 +351,6 @@ public class TestArchitectureWithoutRegistry : IArchitecture throw new NotImplementedException(); } - [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] - public void RegisterMediatorBehavior() where TBehavior : class - { - RegisterCqrsPipelineBehavior(); - } - public IArchitectureModule InstallModule(IArchitectureModule module) { throw new NotImplementedException(); diff --git a/GFramework.Core.Tests/Cqrs/MediatorCompatibilityDeprecationTests.cs b/GFramework.Core.Tests/Cqrs/MediatorCompatibilityDeprecationTests.cs deleted file mode 100644 index a6cc927f..00000000 --- a/GFramework.Core.Tests/Cqrs/MediatorCompatibilityDeprecationTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.ComponentModel; -using System.Reflection; -using GFramework.Core.Abstractions.Architectures; -using GFramework.Core.Abstractions.Ioc; -using GFramework.Core.Architectures; -using GFramework.Core.Coroutine.Extensions; -using GFramework.Core.Ioc; - -namespace GFramework.Core.Tests.Cqrs; - -/// -/// 锁定历史 Mediator 兼容入口的正式弃用策略。 -/// 这些测试确保旧 API 不仅保留行为兼容,还会通过编译期提示和 IntelliSense 隐藏引导调用方迁移到新的 CQRS 命名。 -/// -[TestFixture] -public class MediatorCompatibilityDeprecationTests -{ - /// - /// 验证公开兼容方法仍可用,但已被显式标记为未来移除的旧别名。 - /// - [Test] - public void Legacy_Public_Methods_Should_Be_Obsolete_And_Hidden_From_Editor_Browsing() - { - AssertLegacyMethod(typeof(IArchitecture), nameof(IArchitecture.RegisterMediatorBehavior)); - AssertLegacyMethod(typeof(IIocContainer), nameof(IIocContainer.RegisterMediatorBehavior)); - AssertLegacyMethod(typeof(Architecture), nameof(Architecture.RegisterMediatorBehavior)); - AssertLegacyMethod(typeof(MicrosoftDiContainer), nameof(MicrosoftDiContainer.RegisterMediatorBehavior)); - } - - /// - /// 验证历史扩展类型会把迁移目标写入弃用说明,并从 IntelliSense 主路径隐藏。 - /// - [Test] - public void Legacy_Extension_Types_Should_Be_Obsolete_And_Hidden_From_Editor_Browsing() - { - AssertLegacyType( - typeof(ContextAwareMediatorExtensions), - "Use GFramework.Core.Extensions.ContextAwareCqrsExtensions instead."); - AssertLegacyType( - typeof(ContextAwareMediatorCommandExtensions), - "Use GFramework.Cqrs.Extensions.ContextAwareCqrsCommandExtensions instead."); - AssertLegacyType( - typeof(ContextAwareMediatorQueryExtensions), - "Use GFramework.Cqrs.Extensions.ContextAwareCqrsQueryExtensions instead."); - AssertLegacyType( - typeof(MediatorCoroutineExtensions), - "Use GFramework.Core.Coroutine.Extensions.CqrsCoroutineExtensions instead."); - } - - /// - /// 断言方法级兼容 API 具备统一的弃用元数据。 - /// - /// 声明该方法的类型。 - /// 方法名称。 - private static void AssertLegacyMethod(Type declaringType, string methodName) - { - var method = declaringType - .GetMethods(BindingFlags.Public | BindingFlags.Instance) - .Single(candidate => candidate.Name == methodName); - - var obsoleteAttribute = method.GetCustomAttribute(); - var editorBrowsableAttribute = method.GetCustomAttribute(); - - Assert.Multiple(() => - { - Assert.That(obsoleteAttribute, Is.Not.Null); - Assert.That( - obsoleteAttribute!.Message, - Does.Contain("Use RegisterCqrsPipelineBehavior() instead.")); - Assert.That( - obsoleteAttribute.Message, - Does.Contain("removed in a future major version")); - Assert.That(editorBrowsableAttribute, Is.Not.Null); - Assert.That(editorBrowsableAttribute!.State, Is.EqualTo(EditorBrowsableState.Never)); - }); - } - - /// - /// 断言类型级兼容扩展具备统一的弃用元数据。 - /// - /// 兼容扩展类型。 - /// 期望的迁移提示。 - private static void AssertLegacyType(Type type, string expectedReplacementHint) - { - var obsoleteAttribute = type.GetCustomAttribute(); - var editorBrowsableAttribute = type.GetCustomAttribute(); - - Assert.Multiple(() => - { - Assert.That(obsoleteAttribute, Is.Not.Null); - Assert.That(obsoleteAttribute!.Message, Does.Contain(expectedReplacementHint)); - Assert.That( - obsoleteAttribute.Message, - Does.Contain("removed in a future major version")); - Assert.That(editorBrowsableAttribute, Is.Not.Null); - Assert.That(editorBrowsableAttribute!.State, Is.EqualTo(EditorBrowsableState.Never)); - }); - } -} diff --git a/GFramework.Core.Tests/GFramework.Core.Tests.csproj b/GFramework.Core.Tests/GFramework.Core.Tests.csproj index 391b2924..efea29cf 100644 --- a/GFramework.Core.Tests/GFramework.Core.Tests.csproj +++ b/GFramework.Core.Tests/GFramework.Core.Tests.csproj @@ -21,9 +21,11 @@ - - - + + + diff --git a/GFramework.Core/Architectures/Architecture.cs b/GFramework.Core/Architectures/Architecture.cs index 8d2582aa..cf55b192 100644 --- a/GFramework.Core/Architectures/Architecture.cs +++ b/GFramework.Core/Architectures/Architecture.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.Reflection; using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Enums; @@ -8,7 +7,6 @@ using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Environment; -using GFramework.Core.Logging; namespace GFramework.Core.Architectures; @@ -156,20 +154,6 @@ public abstract class Architecture : IArchitecture _modules.RegisterCqrsPipelineBehavior(); } - /// - /// 注册 CQRS 请求管道行为。 - /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 - /// 新代码不应继续依赖该别名;兼容层计划在未来的 major 版本中移除。 - /// - /// 行为类型,必须是引用类型 - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete( - "Use RegisterCqrsPipelineBehavior() instead. This compatibility alias will be removed in a future major version.")] - public void RegisterMediatorBehavior() where TBehavior : class - { - RegisterCqrsPipelineBehavior(); - } - /// /// 从指定程序集显式注册 CQRS 处理器。 /// 该入口适用于把拆分到其他模块或扩展包程序集中的 handlers 接入当前架构。 diff --git a/GFramework.Core/Architectures/ArchitectureModules.cs b/GFramework.Core/Architectures/ArchitectureModules.cs index f5d2a55d..082baa1e 100644 --- a/GFramework.Core/Architectures/ArchitectureModules.cs +++ b/GFramework.Core/Architectures/ArchitectureModules.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.Reflection; using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Logging; @@ -25,20 +24,6 @@ internal sealed class ArchitectureModules( services.Container.RegisterCqrsPipelineBehavior(); } - /// - /// 注册 CQRS 请求管道行为。 - /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 - /// 新代码不应继续依赖该别名;兼容层计划在未来的 major 版本中移除。 - /// - /// 行为类型,必须是引用类型 - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete( - "Use RegisterCqrsPipelineBehavior() instead. This compatibility alias will be removed in a future major version.")] - public void RegisterMediatorBehavior() where TBehavior : class - { - RegisterCqrsPipelineBehavior(); - } - /// /// 从指定程序集显式注册 CQRS 处理器。 /// 该入口用于把默认架构程序集之外的扩展处理器接入当前架构容器。 diff --git a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs b/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs deleted file mode 100644 index 5086e392..00000000 --- a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2026 GeWuYou -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.ComponentModel; -using GFramework.Core.Abstractions.Coroutine; -using GFramework.Core.Abstractions.Rule; -using GFramework.Cqrs.Abstractions.Cqrs; - -namespace GFramework.Core.Coroutine.Extensions; - -/// -/// 提供 CQRS 命令与协程集成的扩展方法。 -/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 -/// 兼容层计划在未来的 major 版本中移除,因此不会继续承载新能力。 -/// -[EditorBrowsable(EditorBrowsableState.Never)] -[Obsolete( - "Use GFramework.Core.Coroutine.Extensions.CqrsCoroutineExtensions instead. This compatibility alias will be removed in a future major version.")] -public static class MediatorCoroutineExtensions -{ - /// - /// 以协程方式发送无返回值 CQRS 命令并处理可能的异常。 - /// - /// 命令的类型。 - /// 上下文感知对象,用于获取服务 - /// 要发送的命令对象 - /// 发生异常时的回调处理函数 - /// 协程枚举器,用于协程执行 - public static IEnumerator SendCommandCoroutine( - this IContextAware contextAware, - TCommand command, - Action? onError = null) - where TCommand : IRequest - { - return CqrsCoroutineExtensions.SendCommandCoroutine(contextAware, command, onError); - } -} diff --git a/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs deleted file mode 100644 index 24490239..00000000 --- a/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.ComponentModel; -using GFramework.Core.Abstractions.Rule; -using GFramework.Cqrs.Abstractions.Cqrs.Command; -using GFramework.Cqrs.Extensions; - -namespace GFramework.Core.Extensions; - -/// -/// 提供对 接口的 CQRS 命令扩展方法。 -/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 -/// 兼容层计划在未来的 major 版本中移除,因此不会继续承载新能力。 -/// -[EditorBrowsable(EditorBrowsableState.Never)] -[Obsolete( - "Use GFramework.Cqrs.Extensions.ContextAwareCqrsCommandExtensions instead. This compatibility alias will be removed in a future major version.")] -public static class ContextAwareMediatorCommandExtensions -{ - /// - /// 发送命令的同步版本(不推荐,仅用于兼容性) - /// - /// 命令响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的命令对象 - /// 命令执行结果 - /// 当 contextAware 或 command 为 null 时抛出 - public static TResponse SendCommand(this IContextAware contextAware, - ICommand command) - { - return ContextAwareCqrsCommandExtensions.SendCommand(contextAware, command); - } - - /// - /// 异步发送命令并返回结果 - /// - /// 命令响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的命令对象 - /// 取消令牌,用于取消操作 - /// 包含命令执行结果的ValueTask - /// 当 contextAware 或 command 为 null 时抛出 - public static ValueTask SendCommandAsync(this IContextAware contextAware, - ICommand command, CancellationToken cancellationToken = default) - { - return ContextAwareCqrsCommandExtensions.SendCommandAsync( - contextAware, - command, - cancellationToken); - } -} diff --git a/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs deleted file mode 100644 index c7aec1b6..00000000 --- a/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.ComponentModel; -using GFramework.Core.Abstractions.Rule; -using GFramework.Cqrs.Abstractions.Cqrs; -using GFramework.Cqrs.Extensions; - -namespace GFramework.Core.Extensions; - -/// -/// 提供对 接口的 CQRS 统一接口扩展方法。 -/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 -/// 兼容层计划在未来的 major 版本中移除,因此不会继续承载新能力。 -/// -[EditorBrowsable(EditorBrowsableState.Never)] -[Obsolete( - "Use GFramework.Core.Extensions.ContextAwareCqrsExtensions instead. This compatibility alias will be removed in a future major version.")] -public static class ContextAwareMediatorExtensions -{ - /// - /// 发送请求(统一处理 Command/Query) - /// - /// 响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的请求 - /// 取消令牌 - /// 请求结果 - /// 当 contextAware 或 request 为 null 时抛出 - public static ValueTask SendRequestAsync(this IContextAware contextAware, - IRequest request, CancellationToken cancellationToken = default) - { - return ContextAwareCqrsExtensions.SendRequestAsync( - contextAware, - request, - cancellationToken); - } - - /// - /// 发送请求(同步版本,不推荐) - /// - /// 响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的请求 - /// 请求结果 - /// 当 contextAware 或 request 为 null 时抛出 - public static TResponse SendRequest(this IContextAware contextAware, - IRequest request) - { - return ContextAwareCqrsExtensions.SendRequest(contextAware, request); - } - - /// - /// 发布通知(一对多事件) - /// - /// 通知类型 - /// 实现 IContextAware 接口的对象 - /// 要发布的通知 - /// 取消令牌 - /// 异步任务 - /// 当 contextAware 或 notification 为 null 时抛出 - public static ValueTask PublishAsync(this IContextAware contextAware, - TNotification notification, CancellationToken cancellationToken = default) - where TNotification : INotification - { - return ContextAwareCqrsExtensions.PublishAsync( - contextAware, - notification, - cancellationToken); - } - - /// - /// 创建流式请求(用于大数据集) - /// - /// 响应类型 - /// 实现 IContextAware 接口的对象 - /// 流式请求 - /// 取消令牌 - /// 异步响应流 - /// 当 contextAware 或 request 为 null 时抛出 - public static IAsyncEnumerable CreateStream(this IContextAware contextAware, - IStreamRequest request, CancellationToken cancellationToken = default) - { - return ContextAwareCqrsExtensions.CreateStream( - contextAware, - request, - cancellationToken); - } - - /// - /// 发送命令(无返回值) - /// - /// 命令类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的命令 - /// 取消令牌 - /// 异步任务 - /// 当 contextAware 或 command 为 null 时抛出 - public static ValueTask SendAsync(this IContextAware contextAware, TCommand command, - CancellationToken cancellationToken = default) - where TCommand : IRequest - { - return ContextAwareCqrsExtensions.SendAsync( - contextAware, - command, - cancellationToken); - } - - /// - /// 发送命令(有返回值) - /// - /// 响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的命令 - /// 取消令牌 - /// 命令执行结果 - /// 当 contextAware 或 command 为 null 时抛出 - public static ValueTask SendAsync(this IContextAware contextAware, - IRequest command, CancellationToken cancellationToken = default) - { - return ContextAwareCqrsExtensions.SendAsync( - contextAware, - command, - cancellationToken); - } -} diff --git a/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs deleted file mode 100644 index cf0b4513..00000000 --- a/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.ComponentModel; -using GFramework.Core.Abstractions.Rule; -using GFramework.Cqrs.Abstractions.Cqrs.Query; -using GFramework.Cqrs.Extensions; - -namespace GFramework.Core.Extensions; - -/// -/// 提供对 接口的 CQRS 查询扩展方法。 -/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 -/// 兼容层计划在未来的 major 版本中移除,因此不会继续承载新能力。 -/// -[EditorBrowsable(EditorBrowsableState.Never)] -[Obsolete( - "Use GFramework.Cqrs.Extensions.ContextAwareCqrsQueryExtensions instead. This compatibility alias will be removed in a future major version.")] -public static class ContextAwareMediatorQueryExtensions -{ - /// - /// 发送查询的同步版本(不推荐,仅用于兼容性) - /// - /// 查询响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的查询对象 - /// 查询结果 - /// 当 contextAware 或 query 为 null 时抛出 - public static TResponse SendQuery(this IContextAware contextAware, IQuery query) - { - return ContextAwareCqrsQueryExtensions.SendQuery(contextAware, query); - } - - /// - /// 异步发送查询并返回结果 - /// - /// 查询响应类型 - /// 实现 IContextAware 接口的对象 - /// 要发送的查询对象 - /// 取消令牌,用于取消操作 - /// 包含查询结果的ValueTask - /// 当 contextAware 或 query 为 null 时抛出 - public static ValueTask SendQueryAsync(this IContextAware contextAware, - IQuery query, CancellationToken cancellationToken = default) - { - return ContextAwareCqrsQueryExtensions.SendQueryAsync( - contextAware, - query, - cancellationToken); - } -} diff --git a/GFramework.Core/Ioc/MicrosoftDiContainer.cs b/GFramework.Core/Ioc/MicrosoftDiContainer.cs index d1a0576d..9da7b6bc 100644 --- a/GFramework.Core/Ioc/MicrosoftDiContainer.cs +++ b/GFramework.Core/Ioc/MicrosoftDiContainer.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.Reflection; using GFramework.Core.Abstractions.Bases; using GFramework.Core.Abstractions.Ioc; @@ -367,20 +366,6 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) } } - /// - /// 注册 CQRS 请求管道行为。 - /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 - /// 新代码不应继续依赖该别名;兼容层计划在未来的 major 版本中移除。 - /// - /// 行为类型,必须是引用类型 - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete( - "Use RegisterCqrsPipelineBehavior() instead. This compatibility alias will be removed in a future major version.")] - public void RegisterMediatorBehavior() where TBehavior : class - { - RegisterCqrsPipelineBehavior(); - } - /// /// 从指定程序集显式注册 CQRS 处理器。 /// diff --git a/GFramework.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs similarity index 91% rename from GFramework.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs rename to GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs index 72ce6664..74e1daeb 100644 --- a/GFramework.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs +++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs @@ -337,10 +337,17 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator return true; } - if (type is INamedTypeSymbol namedType && - SymbolEqualityComparer.Default.Equals(namedType.ContainingAssembly, compilation.Assembly)) + if (type is INamedTypeSymbol namedType) { - runtimeTypeReference = RuntimeTypeReferenceSpec.FromReflectionLookup( + if (SymbolEqualityComparer.Default.Equals(namedType.ContainingAssembly, compilation.Assembly)) + { + runtimeTypeReference = RuntimeTypeReferenceSpec.FromReflectionLookup( + GetReflectionTypeMetadataName(namedType)); + return true; + } + + runtimeTypeReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( + namedType.ContainingAssembly.Identity.Name, GetReflectionTypeMetadataName(namedType)); return true; } @@ -388,8 +395,10 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator return true; } - genericTypeDefinitionReference = null; - return false; + genericTypeDefinitionReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( + genericTypeDefinition.ContainingAssembly.Identity.Name, + GetReflectionTypeMetadataName(genericTypeDefinition)); + return true; } private static bool CanReferenceFromGeneratedRegistry(Compilation compilation, ITypeSymbol type) @@ -492,6 +501,9 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator !registration.PreciseReflectedRegistrations.IsDefaultOrEmpty); var hasRuntimeInterfaceDiscovery = registrations.Any(static registration => registration.RequiresRuntimeInterfaceDiscovery); + var hasExternalAssemblyTypeLookups = registrations.Any(static registration => + registration.PreciseReflectedRegistrations.Any(static preciseRegistration => + preciseRegistration.ServiceTypeArguments.Any(ContainsExternalAssemblyTypeLookup))); var builder = new StringBuilder(); builder.AppendLine("// "); builder.AppendLine("#nullable enable"); @@ -556,10 +568,13 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator builder.AppendLine(" }"); - if (hasRuntimeInterfaceDiscovery) + if (hasRuntimeInterfaceDiscovery || hasExternalAssemblyTypeLookups) { builder.AppendLine(); - AppendReflectionHelpers(builder); + AppendReflectionHelpers( + builder, + hasRuntimeInterfaceDiscovery, + hasExternalAssemblyTypeLookups); } builder.AppendLine("}"); @@ -910,14 +925,68 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator builder.Append(indent); builder.Append("var "); builder.Append(variableBaseName); - builder.Append(" = registryAssembly.GetType(\""); - builder.Append(EscapeStringLiteral(reflectionTypeMetadataName)); - builder.AppendLine("\", throwOnError: false, ignoreCase: false);"); + if (string.IsNullOrWhiteSpace(runtimeTypeReference.ReflectionAssemblyName)) + { + builder.Append(" = registryAssembly.GetType(\""); + builder.Append(EscapeStringLiteral(reflectionTypeMetadataName)); + builder.AppendLine("\", throwOnError: false, ignoreCase: false);"); + } + else + { + builder.Append(" = ResolveReferencedAssemblyType(\""); + builder.Append(EscapeStringLiteral(runtimeTypeReference.ReflectionAssemblyName!)); + builder.Append("\", \""); + builder.Append(EscapeStringLiteral(reflectionTypeMetadataName)); + builder.AppendLine("\");"); + } + return variableBaseName; } - private static void AppendReflectionHelpers(StringBuilder builder) + private static void AppendReflectionHelpers( + StringBuilder builder, + bool includeRuntimeInterfaceDiscoveryHelpers, + bool includeExternalAssemblyTypeLookupHelpers) { + if (includeExternalAssemblyTypeLookupHelpers) + { + builder.AppendLine( + " private static global::System.Type? ResolveReferencedAssemblyType(string assemblyName, string typeMetadataName)"); + builder.AppendLine(" {"); + builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyName);"); + builder.AppendLine( + " return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);"); + builder.AppendLine(" }"); + builder.AppendLine(); + builder.AppendLine( + " private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyName)"); + builder.AppendLine(" {"); + builder.AppendLine( + " foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())"); + builder.AppendLine(" {"); + builder.AppendLine( + " if (global::System.StringComparer.Ordinal.Equals(assembly.GetName().Name, assemblyName))"); + builder.AppendLine(" return assembly;"); + builder.AppendLine(" }"); + builder.AppendLine(); + builder.AppendLine(" try"); + builder.AppendLine(" {"); + builder.AppendLine( + " return global::System.Reflection.Assembly.Load(new global::System.Reflection.AssemblyName(assemblyName));"); + builder.AppendLine(" }"); + builder.AppendLine(" catch"); + builder.AppendLine(" {"); + builder.AppendLine(" return null;"); + builder.AppendLine(" }"); + builder.AppendLine(" }"); + } + + if (!includeRuntimeInterfaceDiscoveryHelpers) + return; + + if (includeExternalAssemblyTypeLookupHelpers) + builder.AppendLine(); + // Emit the runtime helper methods only when at least one handler still needs implementation-scoped // interface discovery after all direct / precise registrations have been emitted. builder.AppendLine( @@ -1038,6 +1107,32 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator .Replace("\r", "\\r"); } + private static bool ContainsExternalAssemblyTypeLookup(RuntimeTypeReferenceSpec runtimeTypeReference) + { + if (!string.IsNullOrWhiteSpace(runtimeTypeReference.ReflectionAssemblyName)) + return true; + + if (runtimeTypeReference.ArrayElementTypeReference is not null && + ContainsExternalAssemblyTypeLookup(runtimeTypeReference.ArrayElementTypeReference)) + { + return true; + } + + if (runtimeTypeReference.GenericTypeDefinitionReference is not null && + ContainsExternalAssemblyTypeLookup(runtimeTypeReference.GenericTypeDefinitionReference)) + { + return true; + } + + foreach (var genericTypeArgument in runtimeTypeReference.GenericTypeArguments) + { + if (ContainsExternalAssemblyTypeLookup(genericTypeArgument)) + return true; + } + + return false; + } + private readonly record struct HandlerRegistrationSpec( string HandlerInterfaceDisplayName, string ImplementationTypeDisplayName, @@ -1058,6 +1153,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator private sealed record RuntimeTypeReferenceSpec( string? TypeDisplayName, string? ReflectionTypeMetadataName, + string? ReflectionAssemblyName, RuntimeTypeReferenceSpec? ArrayElementTypeReference, int ArrayRank, RuntimeTypeReferenceSpec? GenericTypeDefinitionReference, @@ -1065,19 +1161,28 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator { public static RuntimeTypeReferenceSpec FromDirectReference(string typeDisplayName) { - return new RuntimeTypeReferenceSpec(typeDisplayName, null, null, 0, null, + return new RuntimeTypeReferenceSpec(typeDisplayName, null, null, null, 0, null, ImmutableArray.Empty); } public static RuntimeTypeReferenceSpec FromReflectionLookup(string reflectionTypeMetadataName) { - return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, null, 0, null, + return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, null, null, 0, null, + ImmutableArray.Empty); + } + + public static RuntimeTypeReferenceSpec FromExternalReflectionLookup( + string reflectionAssemblyName, + string reflectionTypeMetadataName) + { + return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, reflectionAssemblyName, null, 0, + null, ImmutableArray.Empty); } public static RuntimeTypeReferenceSpec FromArray(RuntimeTypeReferenceSpec elementTypeReference, int arrayRank) { - return new RuntimeTypeReferenceSpec(null, null, elementTypeReference, arrayRank, null, + return new RuntimeTypeReferenceSpec(null, null, null, elementTypeReference, arrayRank, null, ImmutableArray.Empty); } @@ -1085,7 +1190,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator RuntimeTypeReferenceSpec genericTypeDefinitionReference, ImmutableArray genericTypeArguments) { - return new RuntimeTypeReferenceSpec(null, null, null, 0, genericTypeDefinitionReference, + return new RuntimeTypeReferenceSpec(null, null, null, null, 0, genericTypeDefinitionReference, genericTypeArguments); } } diff --git a/GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj b/GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj new file mode 100644 index 00000000..5f6376c3 --- /dev/null +++ b/GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj @@ -0,0 +1,49 @@ + + + + GeWuYou.$(AssemblyName) + netstandard2.0 + true + false + latest + enable + true + Generated + true + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GFramework.Cqrs.SourceGenerators/GlobalUsings.cs b/GFramework.Cqrs.SourceGenerators/GlobalUsings.cs new file mode 100644 index 00000000..f625284e --- /dev/null +++ b/GFramework.Cqrs.SourceGenerators/GlobalUsings.cs @@ -0,0 +1,13 @@ +global using System; +global using System.Collections.Generic; +global using System.Collections.Immutable; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Text.Json; +global using System.Threading; +global using System.Threading.Tasks; +global using Microsoft.CodeAnalysis; +global using Microsoft.CodeAnalysis.CSharp; +global using Microsoft.CodeAnalysis.CSharp.Syntax; +global using Microsoft.CodeAnalysis.Text; diff --git a/GFramework.Game.SourceGenerators/AnalyzerReleases.Shipped.md b/GFramework.Game.SourceGenerators/AnalyzerReleases.Shipped.md new file mode 100644 index 00000000..ad6aa830 --- /dev/null +++ b/GFramework.Game.SourceGenerators/AnalyzerReleases.Shipped.md @@ -0,0 +1,2 @@ +; Shipped analyzer release +; Intentionally empty until the split game source-generator package ships a stable analyzer release. diff --git a/GFramework.Game.SourceGenerators/AnalyzerReleases.Unshipped.md b/GFramework.Game.SourceGenerators/AnalyzerReleases.Unshipped.md new file mode 100644 index 00000000..3a2574f9 --- /dev/null +++ b/GFramework.Game.SourceGenerators/AnalyzerReleases.Unshipped.md @@ -0,0 +1,17 @@ +; Unshipped analyzer release +; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + +### New Rules + + Rule ID | Category | Severity | Notes +---------------------|------------------------------------|----------|------------------------- + GF_ConfigSchema_001 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_002 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_003 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_004 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_005 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_006 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_007 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_008 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_009 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics + GF_ConfigSchema_010 | GFramework.SourceGenerators.Config | Error | ConfigSchemaDiagnostics diff --git a/GFramework.SourceGenerators/Config/SchemaConfigGenerator.cs b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs similarity index 99% rename from GFramework.SourceGenerators/Config/SchemaConfigGenerator.cs rename to GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs index 7b449fa9..8eafa13e 100644 --- a/GFramework.SourceGenerators/Config/SchemaConfigGenerator.cs +++ b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs @@ -31,7 +31,8 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator private const string LookupIndexReferencePropertyMessage = "Reference properties are excluded from generated lookup indexes because they already carry cross-table semantics."; - private const string SupportedStringFormatNames = "'date', 'date-time', 'duration', 'email', 'time', 'uri', and 'uuid'"; + private const string SupportedStringFormatNames = + "'date', 'date-time', 'duration', 'email', 'time', 'uri', and 'uuid'"; /// public void Initialize(IncrementalGeneratorInitializationContext context) @@ -3183,7 +3184,8 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator var targets = dependency.Value .EnumerateArray() - .Where(static item => item.ValueKind == JsonValueKind.String && !string.IsNullOrWhiteSpace(item.GetString())) + .Where(static item => + item.ValueKind == JsonValueKind.String && !string.IsNullOrWhiteSpace(item.GetString())) .Select(static item => item.GetString()!) .Distinct(StringComparer.Ordinal) .ToArray(); diff --git a/GFramework.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs b/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs similarity index 100% rename from GFramework.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs rename to GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs diff --git a/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj new file mode 100644 index 00000000..e7cc0ae6 --- /dev/null +++ b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj @@ -0,0 +1,55 @@ + + + + GeWuYou.$(AssemblyName) + netstandard2.0 + true + false + latest + enable + true + Generated + true + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GFramework.SourceGenerators/GeWuYou.GFramework.SourceGenerators.targets b/GFramework.Game.SourceGenerators/GeWuYou.GFramework.Game.SourceGenerators.targets similarity index 57% rename from GFramework.SourceGenerators/GeWuYou.GFramework.SourceGenerators.targets rename to GFramework.Game.SourceGenerators/GeWuYou.GFramework.Game.SourceGenerators.targets index c2c3af2d..5d5b5815 100644 --- a/GFramework.SourceGenerators/GeWuYou.GFramework.SourceGenerators.targets +++ b/GFramework.Game.SourceGenerators/GeWuYou.GFramework.Game.SourceGenerators.targets @@ -1,8 +1,5 @@ - - - - - + @@ -33,8 +23,7 @@ - - - + + diff --git a/GFramework.Game.SourceGenerators/GlobalUsings.cs b/GFramework.Game.SourceGenerators/GlobalUsings.cs new file mode 100644 index 00000000..a864b104 --- /dev/null +++ b/GFramework.Game.SourceGenerators/GlobalUsings.cs @@ -0,0 +1,14 @@ +global using System; +global using System.Collections.Generic; +global using System.Collections.Immutable; +global using System.Globalization; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Text.Json; +global using System.Threading; +global using System.Threading.Tasks; +global using Microsoft.CodeAnalysis; +global using Microsoft.CodeAnalysis.CSharp; +global using Microsoft.CodeAnalysis.CSharp.Syntax; +global using Microsoft.CodeAnalysis.Text; diff --git a/GFramework.Game.Tests/GFramework.Game.Tests.csproj b/GFramework.Game.Tests/GFramework.Game.Tests.csproj index f912db4d..b8e4c61f 100644 --- a/GFramework.Game.Tests/GFramework.Game.Tests.csproj +++ b/GFramework.Game.Tests/GFramework.Game.Tests.csproj @@ -20,13 +20,14 @@ - + - + @@ -35,6 +36,6 @@ 通过仓库内的 targets 复用消费者默认约定,确保测试项目与真实消费项目一样 自动拾取 schemas/**/*.schema.json 作为 Source Generator 的 AdditionalFiles。 --> - + diff --git a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs index 2e321993..4077c980 100644 --- a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs @@ -827,10 +827,10 @@ public class CqrsHandlerRegistryGeneratorTests /// /// 验证当外部基类暴露的 handler interface 含有生成注册器顶层上下文不可直接引用的 protected 类型时, - /// 生成器会保留已知直注册,并只对剩余未知接口做本地 interface discovery。 + /// 生成器会输出定向程序集查找,而不是继续退回 implementation 级接口发现。 /// [Test] - public void Generates_Partial_Runtime_Interface_Discovery_For_Inaccessible_External_Protected_Types() + public void Generates_Precise_Assembly_Type_Lookups_For_Inaccessible_External_Protected_Types() { const string contractsSource = """ namespace GFramework.Cqrs.Abstractions.Cqrs @@ -931,30 +931,28 @@ public class CqrsHandlerRegistryGeneratorTests Assert.That( generatedSource, Does.Contain( - "var knownServiceTypes0 = new global::System.Collections.Generic.HashSet();")); + "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedRequest\")")); Assert.That( generatedSource, Does.Contain( - "// Remaining runtime interface discovery target: GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler")); + "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedResponse\")")); Assert.That( generatedSource, Does.Contain( - "knownServiceTypes0.Add(typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler));")); + "typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler)")); Assert.That( generatedSource, - Does.Contain( - "RegisterRemainingReflectedHandlerInterfaces(services, logger, implementationType0, knownServiceTypes0);")); + Does.Contain("ResolveReferencedAssembly(string assemblyName)")); Assert.That( generatedSource, - Does.Contain("if (knownServiceTypes.Contains(handlerInterface))")); + Does.Not.Contain("knownServiceTypes0")); Assert.That( generatedSource, - Does.Contain( - "Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler.")); + Does.Not.Contain("RegisterRemainingReflectedHandlerInterfaces")); Assert.That( generatedSource, Does.Not.Contain( - "typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler - + + + diff --git a/GFramework.csproj b/GFramework.csproj index b9c6c7a4..12324d1c 100644 --- a/GFramework.csproj +++ b/GFramework.csproj @@ -29,21 +29,25 @@ - + GFramework.SorceGenerators\logging\README.md - + GFramework.SorceGenerators\README.md - + GFramework.SorceGenerators\AnalyzerReleases.Shipped.md - + GFramework.SorceGenerators\AnalyzerReleases.Unshipped.md + + + + @@ -77,18 +81,22 @@ - + GFramework.SorceGenerators\enums\EnumExtensionsGenerator.cs - + GFramework.SorceGenerators\logging\Diagnostic.cs - + GFramework.SorceGenerators\logging\LoggerGenerator.cs + + + + @@ -120,6 +128,10 @@ + + + + diff --git a/GFramework.sln b/GFramework.sln index bc64ce21..b2fe4c40 100644 --- a/GFramework.sln +++ b/GFramework.sln @@ -2,10 +2,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework", "GFramework.csproj", "{9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.SourceGenerators", "GFramework.SourceGenerators\GFramework.SourceGenerators.csproj", "{E9D51809-0351-4B83-B85B-B5F469AAB3B8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.SourceGenerators.Abstractions", "GFramework.SourceGenerators.Abstractions\GFramework.SourceGenerators.Abstractions.csproj", "{84C5C3C9-5620-4924-BA04-92F813F2B70F}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Core", "GFramework.Core\GFramework.Core.csproj", "{A6D5854D-79EA-487A-9ED9-396E6A1F8031}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Godot", "GFramework.Godot\GFramework.Godot.csproj", "{FC56D81A-3A3B-4B49-B318-363DFA0D8206}" @@ -46,6 +42,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Cqrs.Tests", "GF EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Tests.Common", "GFramework.Tests.Common\GFramework.Tests.Common.csproj", "{1100EE3E-A12D-4DE5-ABA8-591D3126570B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Core.SourceGenerators", "GFramework.Core.SourceGenerators\GFramework.Core.SourceGenerators.csproj", "{2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Core.SourceGenerators.Abstractions", "GFramework.Core.SourceGenerators.Abstractions\GFramework.Core.SourceGenerators.Abstractions.csproj", "{8858F489-4EDD-41F1-9A74-1CA1CB287EB4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Cqrs.SourceGenerators", "GFramework.Cqrs.SourceGenerators\GFramework.Cqrs.SourceGenerators.csproj", "{3FDCD803-604F-48D9-B2A8-2EC621E8D598}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Game.SourceGenerators", "GFramework.Game.SourceGenerators\GFramework.Game.SourceGenerators.csproj", "{9D3AADF0-55E6-4F80-B9C5-875F63E170D8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -68,30 +72,6 @@ Global {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x64.Build.0 = Release|Any CPU {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x86.ActiveCfg = Release|Any CPU {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x86.Build.0 = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x64.ActiveCfg = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x64.Build.0 = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x86.ActiveCfg = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x86.Build.0 = Debug|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|Any CPU.Build.0 = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x64.ActiveCfg = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x64.Build.0 = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x86.ActiveCfg = Release|Any CPU - {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x86.Build.0 = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x64.ActiveCfg = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x64.Build.0 = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x86.ActiveCfg = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x86.Build.0 = Debug|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|Any CPU.Build.0 = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x64.ActiveCfg = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x64.Build.0 = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x86.ActiveCfg = Release|Any CPU - {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x86.Build.0 = Release|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|Any CPU.Build.0 = Debug|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -332,6 +312,54 @@ Global {1100EE3E-A12D-4DE5-ABA8-591D3126570B}.Release|x64.Build.0 = Release|Any CPU {1100EE3E-A12D-4DE5-ABA8-591D3126570B}.Release|x86.ActiveCfg = Release|Any CPU {1100EE3E-A12D-4DE5-ABA8-591D3126570B}.Release|x86.Build.0 = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|x64.Build.0 = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Debug|x86.Build.0 = Debug|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|Any CPU.Build.0 = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|x64.ActiveCfg = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|x64.Build.0 = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|x86.ActiveCfg = Release|Any CPU + {2E8A4BB6-DA58-484F-ACC5-A8F2FA885B36}.Release|x86.Build.0 = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|x64.ActiveCfg = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|x64.Build.0 = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|x86.ActiveCfg = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Debug|x86.Build.0 = Debug|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|Any CPU.Build.0 = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|x64.ActiveCfg = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|x64.Build.0 = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|x86.ActiveCfg = Release|Any CPU + {8858F489-4EDD-41F1-9A74-1CA1CB287EB4}.Release|x86.Build.0 = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|x64.ActiveCfg = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|x64.Build.0 = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|x86.ActiveCfg = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Debug|x86.Build.0 = Debug|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|Any CPU.Build.0 = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|x64.ActiveCfg = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|x64.Build.0 = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|x86.ActiveCfg = Release|Any CPU + {3FDCD803-604F-48D9-B2A8-2EC621E8D598}.Release|x86.Build.0 = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|x64.ActiveCfg = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|x64.Build.0 = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|x86.ActiveCfg = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Debug|x86.Build.0 = Debug|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|Any CPU.Build.0 = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|x64.ActiveCfg = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|x64.Build.0 = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|x86.ActiveCfg = Release|Any CPU + {9D3AADF0-55E6-4F80-B9C5-875F63E170D8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index 9d2410fe..c488ff19 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -246,9 +246,8 @@ public class GameArchitecture : Architecture 优先使用程序集级生成注册器,失败时自动回退到反射扫描;如果同一程序集已经由默认路径或其他模块接入,框架会自动去重,避免重复注册 handler。 -`RegisterCqrsPipelineBehavior()` 是推荐入口;旧的 `RegisterMediatorBehavior()` -仅作为兼容名称保留,当前已标记为 `Obsolete` 并从 IntelliSense 主路径隐藏,计划在未来 major 版本中移除。 -`ContextAwareMediator*Extensions` 与 `MediatorCoroutineExtensions` 也遵循同样的弃用节奏。当前接口支持两种形式: +`RegisterCqrsPipelineBehavior()` 是唯一保留的公开入口;旧的 `Mediator` 兼容别名与扩展已移除,不再继续维护。 +当前接口支持两种形式: - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 - 封闭行为类型,例如某个只服务于单一请求的 `SpecialBehavior` diff --git a/docs/zh-CN/game/config-system.md b/docs/zh-CN/game/config-system.md index 3ca3776e..5725d2c6 100644 --- a/docs/zh-CN/game/config-system.md +++ b/docs/zh-CN/game/config-system.md @@ -153,26 +153,29 @@ GameProject/ - + - + - + ``` 这段配置的作用: - `GFramework.Game` 提供运行时 `YamlConfigLoader`、`ConfigRegistry`、`GameConfigBootstrap`、`GameConfigModule` 和只读表实现 -- 三个 `ProjectReference(... OutputItemType="Analyzer")` 把生成器接进当前消费者项目 -- `GeWuYou.GFramework.SourceGenerators.targets` 自动把 `schemas/**/*.schema.json` 加入 `AdditionalFiles` +- `GFramework.Core.SourceGenerators.Abstractions` 提供 `Core` 侧 source-generator attributes +- `GFramework.SourceGenerators.Common`、`GFramework.Core.SourceGenerators` 与 `GFramework.Game.SourceGenerators` + 共同把生成器接进当前消费者项目 +- `GeWuYou.GFramework.Game.SourceGenerators.targets` 自动把 `schemas/**/*.schema.json` 加入 `AdditionalFiles` 如果你使用打包后的 NuGet,而不是仓库内项目引用,原则保持不变: From 0cf4945e78afef4e78324670f7d3a79e7c7a0be0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:01:01 +0800 Subject: [PATCH 2/8] =?UTF-8?q?docs(config):=20=E6=B7=BB=E5=8A=A0=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E5=86=85=E5=AE=B9=E9=85=8D=E7=BD=AE=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CQRS 架构模式详细文档,包括命令查询职责分离核心概念 - 添加命令、查询、处理器、请求分发器等基本用法示例 - 包含高级用法如通知、管道行为、流式处理等完整功能介绍 - 提供最佳实践指南和常见问题解决方案 - 添加游戏内容配置系统文档,涵盖 YAML 配置源文件和 JSON Schema 结构描述 - 包含推荐目录结构、Schema 示例和 YAML 示例配置 - 提供完整的接入模板,包括 csproj 配置、启动帮助器和运行时读取模板 - 添加 Godot 文本配置桥接、热重载和 Architecture 接入等高级功能说明 --- .../AutoRegisterModuleAttribute.cs | 2 +- .../Architectures/RegisterModelAttribute.cs | 2 +- .../Architectures/RegisterSystemAttribute.cs | 2 +- .../Architectures/RegisterUtilityAttribute.cs | 2 +- .../Bases/PriorityAttribute.cs | 2 +- .../Enums/GenerateEnumExtensionsAttribute.cs | 2 +- .../Logging/LogAttribute.cs | 2 +- .../Rule/ContextAwareAttribute.cs | 2 +- .../Rule/GetAllAttribute.cs | 2 +- .../Rule/GetModelAttribute.cs | 2 +- .../Rule/GetModelsAttribute.cs | 2 +- .../Rule/GetServiceAttribute.cs | 2 +- .../Rule/GetServicesAttribute.cs | 2 +- .../Rule/GetSystemAttribute.cs | 2 +- .../Rule/GetSystemsAttribute.cs | 16 +- .../Rule/GetUtilitiesAttribute.cs | 2 +- .../Rule/GetUtilityAttribute.cs | 2 +- .../Analyzers/ContextRegistrationAnalyzer.cs | 4 +- .../Analyzers/PriorityUsageAnalyzer.cs | 4 +- .../AutoRegisterModuleGenerator.cs | 6 +- .../Bases/PriorityGenerator.cs | 4 +- .../AutoRegisterModuleDiagnostics.cs | 2 +- .../Diagnostics/ContextAwareDiagnostic.cs | 2 +- .../Diagnostics/ContextGetDiagnostics.cs | 2 +- .../ContextRegistrationDiagnostics.cs | 2 +- .../Diagnostics/LoggerDiagnostic.cs | 2 +- .../Diagnostics/PriorityDiagnostic.cs | 2 +- .../Enums/EnumExtensionsGenerator.cs | 2 +- .../Logging/LoggerGenerator.cs | 4 +- .../Rule/ContextAwareGenerator.cs | 6 +- .../Rule/ContextGetGenerator.cs | 4 +- .../Cqrs/CqrsHandlerRegistryGenerator.cs | 27 +- .../Config/SchemaConfigGenerator.cs | 4 +- .../Diagnostics/ConfigSchemaDiagnostics.cs | 2 +- .../GFramework.Game.SourceGenerators.csproj | 1 + .../ContextRegistrationAnalyzerTests.cs | 249 +++++++++--------- .../AutoRegisterModuleGeneratorTests.cs | 69 ++--- .../Bases/PriorityGeneratorSnapshotTests.cs | 5 +- .../Config/SchemaGeneratorTestDriver.cs | 5 +- .../Cqrs/CqrsHandlerRegistryGeneratorTests.cs | 114 +++++--- .../EnumExtensionsGeneratorSnapshotTests.cs | 5 +- .../Logging/LoggerGeneratorSnapshotTests.cs | 5 +- .../ContextAwareGeneratorSnapshotTests.cs | 5 +- .../Rule/ContextGetGeneratorTests.cs | 2 +- GFramework.csproj | 17 +- README.md | 7 +- docs/zh-CN/core/cqrs.md | 2 + docs/zh-CN/game/config-system.md | 4 +- docs/zh-CN/getting-started/installation.md | 46 +++- docs/zh-CN/source-generators/index.md | 29 +- .../zh-CN/tutorials/basic/02-project-setup.md | 17 +- 51 files changed, 416 insertions(+), 293 deletions(-) diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs index 04daaa46..08168ebf 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 标记架构模块类型,Source Generator 会根据注册特性生成 Install 方法。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs index 6c47d8b1..5607fed7 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的模型类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs index 7119db2f..64f8e7ce 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的系统类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs index 88e5d93c..4cde0498 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的工具类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs index 42459498..f2bfc9ab 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Bases; +namespace GFramework.Core.SourceGenerators.Abstractions.Bases; /// /// 标记类的优先级,自动生成 GFramework.Core.Abstractions.Bases.IPrioritized 接口实现。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs index c5136a88..a48c7b7f 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Enums; +namespace GFramework.Core.SourceGenerators.Abstractions.Enums; /// /// 标注在 enum 上,Source Generator 会为该 enum 生成扩展方法。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs index 0cddf94c..6ba80e27 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs @@ -1,5 +1,5 @@ #nullable enable -namespace GFramework.SourceGenerators.Abstractions.Logging; +namespace GFramework.Core.SourceGenerators.Abstractions.Logging; /// /// 标注在类上,Source Generator 会为该类自动生成一个日志记录器字段。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs index 7cb75238..6827cc30 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记该类需要自动实现 IContextAware diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs index cd310da6..203a4ac7 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记类需要自动推断并注入上下文相关字段。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs index b97d395f..59c8b44a 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个模型实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs index a6173a25..9bd9168e 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入模型集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs index 46c23320..fe652d17 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个服务实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs index 5341d6a3..c81fcf2d 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入服务集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs index 072cd112..9bfc7b70 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个系统实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs index da214089..4b05b051 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs @@ -1,8 +1,22 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入系统集合。 /// +/// +/// Source Generator 会为标记字段生成从当前架构上下文收集系统实例的注入代码,用于避免在组件内部重复书写 +/// GetSystems() 一类的样板访问逻辑。 +/// 被标记字段应声明为可承载多个系统实例的类型,例如 IEnumerable<ISystem> 或兼容集合接口。 +/// +/// +/// +/// public partial class CombatPanel : IContextAware +/// { +/// [GetSystems] +/// private IEnumerable<ISystem> _systems = Array.Empty<ISystem>(); +/// } +/// +/// [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetSystemsAttribute : Attribute { diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs index afeb63ee..5f9c65d6 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入工具集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs index 99059a96..3b934a67 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个工具实例。 diff --git a/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs index dcd25ca8..57c49d08 100644 --- a/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs @@ -1,9 +1,9 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; -using GFramework.SourceGenerators.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace GFramework.SourceGenerators.Analyzers; +namespace GFramework.Core.SourceGenerators.Analyzers; /// /// 分析 Context Get 使用点是否能在所属架构中找到静态可见的 Model、System、Utility 注册。 diff --git a/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs index b58871a1..520448a6 100644 --- a/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs @@ -1,8 +1,8 @@ -using GFramework.SourceGenerators.Diagnostics; +using GFramework.Core.SourceGenerators.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace GFramework.SourceGenerators.Analyzers; +namespace GFramework.Core.SourceGenerators.Analyzers; /// /// 优先级使用分析器,检测应该使用 GetAllByPriority 而非 GetAll 的场景 diff --git a/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs b/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs index 0385d221..93771bc1 100644 --- a/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs +++ b/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs @@ -1,10 +1,10 @@ -using GFramework.SourceGenerators.Abstractions.Architectures; +using GFramework.Core.SourceGenerators.Abstractions.Architectures; +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Extensions; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Architectures; +namespace GFramework.Core.SourceGenerators.Architectures; /// /// 为标记了 的模块生成固定顺序的组件注册代码。 diff --git a/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs index b0331900..ee534f8a 100644 --- a/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs +++ b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs @@ -1,8 +1,8 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Generator; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Bases; +namespace GFramework.Core.SourceGenerators.Bases; /// /// Priority 特性生成器,为标记了 [Priority] 的类自动生成 IPrioritized 接口实现 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs index 83b9566f..eb3323aa 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; internal static class AutoRegisterModuleDiagnostics { diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs index 70b06fc8..e84e1853 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供与上下文感知相关的诊断规则定义 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs index dd9534d4..be2e69e6 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供 Context Get 注入生成器相关诊断。 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs index 7643c812..a6d9ba13 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供 Context Get 注册可见性分析相关诊断。 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs index 0ff2bf90..14238e16 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供诊断描述符的静态类,用于GFramework日志生成器的编译时检查 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs index 86030071..169143e3 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// Priority 特性相关的诊断信息 diff --git a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs index b04a3640..493c10e1 100644 --- a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs +++ b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs @@ -2,7 +2,7 @@ using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; -namespace GFramework.SourceGenerators.Enums; +namespace GFramework.Core.SourceGenerators.Enums; /// /// 枚举扩展方法生成器,用于自动生成枚举相关的扩展方法 diff --git a/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs index e861f0c3..2be4a1d4 100644 --- a/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs +++ b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs @@ -1,9 +1,9 @@ -using GFramework.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Logging; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Generator; -namespace GFramework.SourceGenerators.Logging; +namespace GFramework.Core.SourceGenerators.Logging; /// /// 日志生成器,用于为标记了LogAttribute的类自动生成日志字段 diff --git a/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs index 68c2ad45..9bdeb3f9 100644 --- a/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs @@ -1,9 +1,9 @@ -using GFramework.SourceGenerators.Common.Constants; +using GFramework.Core.SourceGenerators.Diagnostics; +using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Rule; +namespace GFramework.Core.SourceGenerators.Rule; /// /// 上下文感知生成器,用于为标记了ContextAware特性的类自动生成IContextAware接口实现 diff --git a/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs index c3915b00..f0b4aeba 100644 --- a/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs @@ -1,10 +1,10 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Info; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Rule; +namespace GFramework.Core.SourceGenerators.Rule; /// /// 为上下文感知类生成 Core 上下文 Get 注入方法。 diff --git a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs index 74e1daeb..ba63ea11 100644 --- a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs +++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Cqrs; +namespace GFramework.Cqrs.SourceGenerators.Cqrs; /// /// 为当前编译程序集生成 CQRS 处理器注册器,以减少运行时的程序集反射扫描成本。 @@ -347,7 +347,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator } runtimeTypeReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( - namedType.ContainingAssembly.Identity.Name, + namedType.ContainingAssembly.Identity.ToString(), GetReflectionTypeMetadataName(namedType)); return true; } @@ -396,7 +396,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator } genericTypeDefinitionReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( - genericTypeDefinition.ContainingAssembly.Identity.Name, + genericTypeDefinition.ContainingAssembly.Identity.ToString(), GetReflectionTypeMetadataName(genericTypeDefinition)); return true; } @@ -951,28 +951,39 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator if (includeExternalAssemblyTypeLookupHelpers) { builder.AppendLine( - " private static global::System.Type? ResolveReferencedAssemblyType(string assemblyName, string typeMetadataName)"); + " private static global::System.Type? ResolveReferencedAssemblyType(string assemblyIdentity, string typeMetadataName)"); builder.AppendLine(" {"); - builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyName);"); + builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyIdentity);"); builder.AppendLine( " return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);"); builder.AppendLine(" }"); builder.AppendLine(); builder.AppendLine( - " private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyName)"); + " private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyIdentity)"); builder.AppendLine(" {"); + builder.AppendLine(" global::System.Reflection.AssemblyName targetAssemblyName;"); + builder.AppendLine(" try"); + builder.AppendLine(" {"); + builder.AppendLine( + " targetAssemblyName = new global::System.Reflection.AssemblyName(assemblyIdentity);"); + builder.AppendLine(" }"); + builder.AppendLine(" catch"); + builder.AppendLine(" {"); + builder.AppendLine(" return null;"); + builder.AppendLine(" }"); + builder.AppendLine(); builder.AppendLine( " foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())"); builder.AppendLine(" {"); builder.AppendLine( - " if (global::System.StringComparer.Ordinal.Equals(assembly.GetName().Name, assemblyName))"); + " if (global::System.Reflection.AssemblyName.ReferenceMatchesDefinition(targetAssemblyName, assembly.GetName()))"); builder.AppendLine(" return assembly;"); builder.AppendLine(" }"); builder.AppendLine(); builder.AppendLine(" try"); builder.AppendLine(" {"); builder.AppendLine( - " return global::System.Reflection.Assembly.Load(new global::System.Reflection.AssemblyName(assemblyName));"); + " return global::System.Reflection.Assembly.Load(targetAssemblyName);"); builder.AppendLine(" }"); builder.AppendLine(" catch"); builder.AppendLine(" {"); diff --git a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs index 8eafa13e..aca981c8 100644 --- a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs +++ b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs @@ -1,6 +1,6 @@ -using GFramework.SourceGenerators.Diagnostics; +using GFramework.Game.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Config; +namespace GFramework.Game.SourceGenerators.Config; /// /// 根据 AdditionalFiles 中的 JSON schema 生成配置类型和配置表包装。 diff --git a/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs b/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs index 115ecea2..04d1c02e 100644 --- a/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs +++ b/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Game.SourceGenerators.Diagnostics; /// /// 提供配置 schema 代码生成相关诊断。 diff --git a/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj index e7cc0ae6..1c0a9bd1 100644 --- a/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj +++ b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj @@ -7,6 +7,7 @@ false latest enable + true true Generated true diff --git a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs index 781a77bc..abcb4ccf 100644 --- a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs +++ b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Analyzers; +using GFramework.Core.SourceGenerators.Analyzers; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Analyzers; @@ -9,128 +9,128 @@ namespace GFramework.SourceGenerators.Tests.Analyzers; public sealed class ContextRegistrationAnalyzerTests { private const string TestPreamble = """ - using System; - using System.Collections.Generic; - - namespace GFramework.Core.Abstractions.Rule - { - public interface IContextAware { } - } - - namespace GFramework.Core.Abstractions.Model - { - public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Systems - { - public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Utility - { - public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Architectures - { - public interface IArchitecture - { - T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel; - void RegisterModel(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel; - T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem; - void RegisterSystem(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem; - T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility; - void RegisterUtility(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility; - IArchitectureModule InstallModule(IArchitectureModule module); - } - - public interface IArchitectureModule - { - void Install(IArchitecture architecture); - } - - public interface IArchitectureContext - { - TModel GetModel() where TModel : class, GFramework.Core.Abstractions.Model.IModel; - IReadOnlyList GetModels() where TModel : class, GFramework.Core.Abstractions.Model.IModel; - TSystem GetSystem() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; - IReadOnlyList GetSystems() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; - TUtility GetUtility() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; - IReadOnlyList GetUtilities() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; - } - } - - namespace GFramework.Core.Architectures - { - public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture - { - protected abstract void OnInitialize(); - - public virtual T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel => model; - - public virtual void RegisterModel(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Model.IModel - { - } - - public virtual T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system; - - public virtual void RegisterSystem(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Systems.ISystem - { - } - - public virtual T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility; - - public virtual void RegisterUtility(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Utility.IUtility - { - } - - public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule( - GFramework.Core.Abstractions.Architectures.IArchitectureModule module) - { - module.Install(this); - return module; - } - } - } - - namespace GFramework.Core.Extensions - { - public static class ContextAwareServiceExtensions - { - public static TModel GetModel(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); - - public static IReadOnlyList GetModels(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); - - public static TSystem GetSystem(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); - - public static IReadOnlyList GetSystems(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); - - public static TUtility GetUtility(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); - - public static IReadOnlyList GetUtilities(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); - } - } - - namespace GFramework.SourceGenerators.Abstractions.Rule - { - public sealed class GetModelAttribute : Attribute { } - public sealed class GetModelsAttribute : Attribute { } - public sealed class GetSystemAttribute : Attribute { } - public sealed class GetSystemsAttribute : Attribute { } - public sealed class GetUtilityAttribute : Attribute { } - public sealed class GetUtilitiesAttribute : Attribute { } - } - """; + using System; + using System.Collections.Generic; + + namespace GFramework.Core.Abstractions.Rule + { + public interface IContextAware { } + } + + namespace GFramework.Core.Abstractions.Model + { + public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Systems + { + public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Utility + { + public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Architectures + { + public interface IArchitecture + { + T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel; + void RegisterModel(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel; + T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem; + void RegisterSystem(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem; + T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility; + void RegisterUtility(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility; + IArchitectureModule InstallModule(IArchitectureModule module); + } + + public interface IArchitectureModule + { + void Install(IArchitecture architecture); + } + + public interface IArchitectureContext + { + TModel GetModel() where TModel : class, GFramework.Core.Abstractions.Model.IModel; + IReadOnlyList GetModels() where TModel : class, GFramework.Core.Abstractions.Model.IModel; + TSystem GetSystem() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; + IReadOnlyList GetSystems() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; + TUtility GetUtility() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; + IReadOnlyList GetUtilities() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; + } + } + + namespace GFramework.Core.Architectures + { + public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture + { + protected abstract void OnInitialize(); + + public virtual T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel => model; + + public virtual void RegisterModel(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Model.IModel + { + } + + public virtual T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system; + + public virtual void RegisterSystem(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Systems.ISystem + { + } + + public virtual T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility; + + public virtual void RegisterUtility(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Utility.IUtility + { + } + + public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule( + GFramework.Core.Abstractions.Architectures.IArchitectureModule module) + { + module.Install(this); + return module; + } + } + } + + namespace GFramework.Core.Extensions + { + public static class ContextAwareServiceExtensions + { + public static TModel GetModel(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); + + public static IReadOnlyList GetModels(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); + + public static TSystem GetSystem(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); + + public static IReadOnlyList GetSystems(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); + + public static TUtility GetUtility(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); + + public static IReadOnlyList GetUtilities(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); + } + } + + namespace GFramework.SourceGenerators.Abstractions.Rule + { + public sealed class GetModelAttribute : Attribute { } + public sealed class GetModelsAttribute : Attribute { } + public sealed class GetSystemAttribute : Attribute { } + public sealed class GetSystemsAttribute : Attribute { } + public sealed class GetUtilityAttribute : Attribute { } + public sealed class GetUtilitiesAttribute : Attribute { } + } + """; [Test] public async Task Reports_Warning_When_FieldInjectedModel_Is_Not_Registered() @@ -366,7 +366,8 @@ public sealed class ContextRegistrationAnalyzerTests } [Test] - public async Task Does_Not_Report_When_Inherited_OnInitialize_Calls_Virtual_Helper_Overridden_In_Derived_Architecture() + public async Task + Does_Not_Report_When_Inherited_OnInitialize_Calls_Virtual_Helper_Overridden_In_Derived_Architecture() { await AnalyzerTestDriver.RunAsync( Wrap(""" diff --git a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs index 964bba4a..ae44a8ed 100644 --- a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Architectures; +using GFramework.Core.SourceGenerators.Architectures; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Architectures; @@ -180,42 +180,42 @@ public class AutoRegisterModuleGeneratorTests """; const string partASource = """ - namespace TestApp - { - using GFramework.SourceGenerators.Abstractions.Architectures; + namespace TestApp + { + using GFramework.SourceGenerators.Abstractions.Architectures; - // Padding ensures this attribute lives later in the file than the attributes in PartB. - // The generator should still place it first because PartA sorts before PartB. - // padding 01 - // padding 02 - // padding 03 - // padding 04 - // padding 05 - // padding 06 - // padding 07 - // padding 08 - // padding 09 - // padding 10 - [AutoRegisterModule] - [RegisterUtility(typeof(AudioUtility))] - public partial class GameplayModule - { - } - } - """; + // Padding ensures this attribute lives later in the file than the attributes in PartB. + // The generator should still place it first because PartA sorts before PartB. + // padding 01 + // padding 02 + // padding 03 + // padding 04 + // padding 05 + // padding 06 + // padding 07 + // padding 08 + // padding 09 + // padding 10 + [AutoRegisterModule] + [RegisterUtility(typeof(AudioUtility))] + public partial class GameplayModule + { + } + } + """; const string partBSource = """ - namespace TestApp - { - using GFramework.SourceGenerators.Abstractions.Architectures; + namespace TestApp + { + using GFramework.SourceGenerators.Abstractions.Architectures; - [RegisterSystem(typeof(CombatSystem))] - [RegisterModel(typeof(PlayerModel))] - public partial class GameplayModule - { - } - } - """; + [RegisterSystem(typeof(CombatSystem))] + [RegisterModel(typeof(PlayerModel))] + public partial class GameplayModule + { + } + } + """; const string expected = """ // @@ -247,7 +247,8 @@ public class AutoRegisterModuleGeneratorTests }, GeneratedSources = { - (typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs", NormalizeLineEndings(expected)) + (typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs", + NormalizeLineEndings(expected)) } }, DisabledDiagnostics = { "GF_Common_Trace_001" } diff --git a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs index 37588603..bb29762a 100644 --- a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Bases; +using GFramework.Core.SourceGenerators.Bases; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Bases; @@ -212,4 +211,4 @@ public class PriorityGeneratorSnapshotTests "PriorityGenerator", "GenericClass")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs b/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs index 4da9519a..c8f5a4e4 100644 --- a/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs +++ b/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.IO; -using GFramework.SourceGenerators.Config; -using Microsoft.CodeAnalysis.CSharp; +using GFramework.Game.SourceGenerators.Config; namespace GFramework.SourceGenerators.Tests.Config; @@ -85,4 +84,4 @@ public static class SchemaGeneratorTestDriver return _text; } } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs index 4077c980..5d97e998 100644 --- a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs @@ -1,5 +1,5 @@ using System.Reflection; -using GFramework.SourceGenerators.Cqrs; +using GFramework.Cqrs.SourceGenerators.Cqrs; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Cqrs; @@ -252,6 +252,84 @@ public class CqrsHandlerRegistryGeneratorTests """; + private const string ExternalAssemblyPreciseLookupExpected = """ + // + #nullable enable + + [assembly: global::GFramework.Cqrs.CqrsHandlerRegistryAttribute(typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry))] + + namespace GFramework.Generated.Cqrs; + + internal sealed class __GFrameworkGeneratedCqrsHandlerRegistry : global::GFramework.Cqrs.ICqrsHandlerRegistry + { + public void Register(global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::GFramework.Core.Abstractions.Logging.ILogger logger) + { + if (services is null) + throw new global::System.ArgumentNullException(nameof(services)); + if (logger is null) + throw new global::System.ArgumentNullException(nameof(logger)); + + var registryAssembly = typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry).Assembly; + + var implementationType0 = typeof(global::TestApp.DerivedHandler); + if (implementationType0 is not null) + { + var serviceType0_0Argument0 = ResolveReferencedAssemblyType("Dependency, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Dep.VisibilityScope+ProtectedRequest"); + var serviceType0_0Argument1Element = ResolveReferencedAssemblyType("Dependency, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Dep.VisibilityScope+ProtectedResponse"); + if (serviceType0_0Argument0 is not null && serviceType0_0Argument1Element is not null) + { + var serviceType0_0 = typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<,>).MakeGenericType(serviceType0_0Argument0, serviceType0_0Argument1Element.MakeArrayType()); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + serviceType0_0, + implementationType0); + logger.Debug("Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); + } + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler), + implementationType0); + logger.Debug("Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); + } + } + + private static global::System.Type? ResolveReferencedAssemblyType(string assemblyIdentity, string typeMetadataName) + { + var assembly = ResolveReferencedAssembly(assemblyIdentity); + return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false); + } + + private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyIdentity) + { + global::System.Reflection.AssemblyName targetAssemblyName; + try + { + targetAssemblyName = new global::System.Reflection.AssemblyName(assemblyIdentity); + } + catch + { + return null; + } + + foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies()) + { + if (global::System.Reflection.AssemblyName.ReferenceMatchesDefinition(targetAssemblyName, assembly.GetName())) + return assembly; + } + + try + { + return global::System.Reflection.Assembly.Load(targetAssemblyName); + } + catch + { + return null; + } + } + } + + """; + /// /// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。 /// @@ -923,37 +1001,9 @@ public class CqrsHandlerRegistryGeneratorTests contractsReference, dependencyReference); - Assert.Multiple(() => - { - Assert.That( - generatedSource, - Does.Contain("var implementationType0 = typeof(global::TestApp.DerivedHandler);")); - Assert.That( - generatedSource, - Does.Contain( - "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedRequest\")")); - Assert.That( - generatedSource, - Does.Contain( - "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedResponse\")")); - Assert.That( - generatedSource, - Does.Contain( - "typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler)")); - Assert.That( - generatedSource, - Does.Contain("ResolveReferencedAssembly(string assemblyName)")); - Assert.That( - generatedSource, - Does.Not.Contain("knownServiceTypes0")); - Assert.That( - generatedSource, - Does.Not.Contain("RegisterRemainingReflectedHandlerInterfaces")); - Assert.That( - generatedSource, - Does.Not.Contain( - "// Remaining runtime interface discovery target:")); - }); + Assert.That( + generatedSource, + Is.EqualTo(ExternalAssemblyPreciseLookupExpected)); } /// diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index 27d73c11..f9ddf5c0 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Enums; +using GFramework.Core.SourceGenerators.Enums; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Enums; @@ -206,4 +205,4 @@ public class EnumExtensionsGeneratorSnapshotTests "EnumExtensionsGenerator", "DisableIsInMethod")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs index d90412e8..e1263a0f 100644 --- a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Logging; +using GFramework.Core.SourceGenerators.Logging; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Logging; @@ -589,4 +588,4 @@ public class LoggerGeneratorSnapshotTests "LoggerGenerator", "GenericClass")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs index dba9faa1..415a7f09 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Rule; +using GFramework.Core.SourceGenerators.Rule; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Rule; @@ -93,4 +92,4 @@ public class ContextAwareGeneratorSnapshotTests "snapshots", "ContextAwareGenerator")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs index c8804f58..d16806e6 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Rule; +using GFramework.Core.SourceGenerators.Rule; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Rule; diff --git a/GFramework.csproj b/GFramework.csproj index 12324d1c..33baacae 100644 --- a/GFramework.csproj +++ b/GFramework.csproj @@ -30,19 +30,18 @@ - GFramework.SorceGenerators\logging\README.md + GFramework.Core.SourceGenerators\logging\README.md - GFramework.SorceGenerators\README.md + GFramework.Core.SourceGenerators\README.md - GFramework.SorceGenerators\AnalyzerReleases.Shipped.md + GFramework.Core.SourceGenerators\AnalyzerReleases.Shipped.md - GFramework.SorceGenerators\AnalyzerReleases.Unshipped.md + GFramework.Core.SourceGenerators\AnalyzerReleases.Unshipped.md - @@ -82,16 +81,15 @@ - GFramework.SorceGenerators\enums\EnumExtensionsGenerator.cs + GFramework.Core.SourceGenerators\enums\EnumExtensionsGenerator.cs - GFramework.SorceGenerators\logging\Diagnostic.cs + GFramework.Core.SourceGenerators\logging\Diagnostic.cs - GFramework.SorceGenerators\logging\LoggerGenerator.cs + GFramework.Core.SourceGenerators\logging\LoggerGenerator.cs - @@ -126,7 +124,6 @@ - diff --git a/README.md b/README.md index 19f04dae..4fe20e29 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成(仅 Godot 项目需要) dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# 按场景选择源码生成器(可选,但推荐) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators +dotnet add package GeWuYou.GFramework.Game.SourceGenerators +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators +dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators ``` ## 可选模块导入 diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index c488ff19..c0357fa5 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -247,6 +247,8 @@ public class GameArchitecture : Architecture handler。 `RegisterCqrsPipelineBehavior()` 是唯一保留的公开入口;旧的 `Mediator` 兼容别名与扩展已移除,不再继续维护。 +如果你正在从旧版本迁移,显式替换关系就是 +`RegisterMediatorBehavior() -> RegisterCqrsPipelineBehavior()`。 当前接口支持两种形式: - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 diff --git a/docs/zh-CN/game/config-system.md b/docs/zh-CN/game/config-system.md index 5725d2c6..c00f2a2c 100644 --- a/docs/zh-CN/game/config-system.md +++ b/docs/zh-CN/game/config-system.md @@ -180,7 +180,9 @@ GameProject/ 如果你使用打包后的 NuGet,而不是仓库内项目引用,原则保持不变: - 运行时项目需要引用 `GeWuYou.GFramework.Game` -- 生成器项目需要引用 `GeWuYou.GFramework.SourceGenerators` +- 配置 schema 生成器需要引用 `GeWuYou.GFramework.Game.SourceGenerators` +- 如果同一项目还会使用 `[Log]`、`[ContextAware]`、`[GetSystem]` 等 Core 侧生成器特性,再额外引用 + `GeWuYou.GFramework.Core.SourceGenerators` - schema 目录默认仍然是 `schemas/` 如果你的 schema 不放在默认目录,可以在项目文件里覆盖: diff --git a/docs/zh-CN/getting-started/installation.md b/docs/zh-CN/getting-started/installation.md index c6b8618c..b99432de 100644 --- a/docs/zh-CN/getting-started/installation.md +++ b/docs/zh-CN/getting-started/installation.md @@ -6,13 +6,18 @@ GFramework 提供多种安装方式,您可以根据项目需求选择合适的 GFramework 采用模块化设计,不同包提供不同的功能: -| 包名 | 说明 | 适用场景 | -|---------------------------------------|---------|-----------| -| `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 | -| `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 | -| `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 | -| `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 | -| `GeWuYou.GFramework.SourceGenerators` | 源码生成器 | 推荐安装 | +| 包名 | 说明 | 适用场景 | +|---------------------------------------------|-------------|--------------------------------| +| `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 | +| `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 | +| `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 | +| `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 | +| `GeWuYou.GFramework.Core.SourceGenerators` | Core 源码生成器 | `[Log]`、`[ContextAware]`、架构注入等 | +| `GeWuYou.GFramework.Game.SourceGenerators` | Game 源码生成器 | 配置 schema / 配表生成 | +| `GeWuYou.GFramework.Godot.SourceGenerators` | Godot 源码生成器 | Godot 节点、UI、项目元数据生成 | +| `GeWuYou.GFramework.Cqrs.SourceGenerators` | CQRS 源码生成器 | 处理器注册表生成 | + +当前 NuGet 发布按模块拆分 source generator 包,不存在 `GeWuYou.GFramework.SourceGenerators` 聚合包。 ## 安装方式 @@ -30,8 +35,17 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成(仅 Godot 项目需要) dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器([Log] / [ContextAware] / [GetSystem] 等) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Game 配置 schema 生成器 +dotnet add package GeWuYou.GFramework.Game.SourceGenerators + +# Godot 生成器(仅 Godot 项目需要) +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators + +# CQRS 处理器注册生成器(仅使用 CQRS source generator 时需要) +dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators ``` ### 2. 使用 PackageReference @@ -56,8 +70,14 @@ dotnet add package GeWuYou.GFramework.SourceGenerators - - + + + + @@ -183,6 +203,8 @@ dotnet build 检查: -- 确保安装了 `GeWuYou.GFramework.SourceGenerators` +- 确保安装了与你正在使用的特性对应的拆分生成器包,例如: + `GeWuYou.GFramework.Core.SourceGenerators`、`GeWuYou.GFramework.Game.SourceGenerators`、 + `GeWuYou.GFramework.Godot.SourceGenerators` 或 `GeWuYou.GFramework.Cqrs.SourceGenerators` - 重启 IDE - 清理并重新构建项目 diff --git a/docs/zh-CN/source-generators/index.md b/docs/zh-CN/source-generators/index.md index ea62aad0..224ed96a 100644 --- a/docs/zh-CN/source-generators/index.md +++ b/docs/zh-CN/source-generators/index.md @@ -30,7 +30,16 @@ GFramework.SourceGenerators 是 GFramework 框架的源代码生成器包,通 ## 概述 -GFramework.SourceGenerators 利用 Roslyn 源代码生成器技术,在编译时分析你的代码并自动生成常用的样板代码,让开发者专注于业务逻辑而不是重复的模板代码。 +GFramework 的 source generators 利用 Roslyn 源代码生成器技术,在编译时分析你的代码并自动生成常用的样板代码,让开发者专注于业务逻辑而不是重复的模板代码。 + +当前 NuGet 发布按模块拆分为: + +- `GeWuYou.GFramework.Core.SourceGenerators` +- `GeWuYou.GFramework.Game.SourceGenerators` +- `GeWuYou.GFramework.Godot.SourceGenerators` +- `GeWuYou.GFramework.Cqrs.SourceGenerators` + +不存在 `GeWuYou.GFramework.SourceGenerators` 或 `GeWuYou.GFramework.SourceGenerators.Attributes` 这类聚合包。 ### 核心设计理念 @@ -74,22 +83,30 @@ GFramework.SourceGenerators 利用 Roslyn 源代码生成器技术,在编译 ### NuGet 包安装 ```xml - net6.0 - - + + ``` +如果你只使用 Godot 生成器或 CQRS 处理器注册生成器,请把上面的包替换为对应的 +`GeWuYou.GFramework.Godot.SourceGenerators` 或 `GeWuYou.GFramework.Cqrs.SourceGenerators`。 +这些拆分包会同时带上各自需要的 abstractions 程序集,不需要再额外安装单独的 `*.Attributes` 包。 + ### Config Schema 文件约定 -当项目引用 `GeWuYou.GFramework.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置 schema +当项目引用 `GeWuYou.GFramework.Game.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置 +schema 文件并作为 `AdditionalFiles` 输入。 这意味着消费者项目通常只需要维护如下结构: @@ -150,7 +167,7 @@ Config Schema 生成器会扫描 `*.schema.json` 文件,并生成: ### 基础使用 ```csharp -using GFramework.SourceGenerators.Attributes; +using GFramework.SourceGenerators.Abstractions.Logging; [Log] public partial class PlayerController diff --git a/docs/zh-CN/tutorials/basic/02-project-setup.md b/docs/zh-CN/tutorials/basic/02-project-setup.md index 2df9a3a6..41022e99 100644 --- a/docs/zh-CN/tutorials/basic/02-project-setup.md +++ b/docs/zh-CN/tutorials/basic/02-project-setup.md @@ -74,8 +74,11 @@ dotnet add package GeWuYou.GFramework # Godot 集成 dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器([Log] / [ContextAware] 等) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Godot 侧源码生成器([GetNode] / [AutoUiPage] 等) +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators ``` ::: details 分包安装(了解即可) @@ -93,8 +96,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成 dotnet add package GeWuYou.GFramework.Godot -# 源码生成器 -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器 +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Godot 侧源码生成器 +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators ``` ::: @@ -108,7 +114,8 @@ dotnet add package GeWuYou.GFramework.SourceGenerators 3. 安装以下包: - `GeWuYou.GFramework` - `GeWuYou.GFramework.Godot` - - `GeWuYou.GFramework.SourceGenerators` + - `GeWuYou.GFramework.Core.SourceGenerators` + - `GeWuYou.GFramework.Godot.SourceGenerators` ![NuGet 包管理](../assets/basic/image-20260211211756993.png) From 9f9a421b6cf9b3236e3c08ef485e1344fe70ed68 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:16:23 +0800 Subject: [PATCH 3/8] =?UTF-8?q?docs(source-generators):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=BA=90=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=92=8C=E6=8A=BD=E8=B1=A1=E5=8C=85=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增完整的 GFramework.SourceGenerators 文档,涵盖所有生成器功能 - 添加 Log 属性生成器、ContextAware 属性生成器、Config Schema 生成器等详细说明 - 包含 Godot 专用生成器如 GetNode、BindNodeSignal、AutoUiPage 等使用指南 - 提供诊断信息、性能优势、使用示例和最佳实践章节 - 创建 Core.SourceGenerators.Abstractions 项目文件和配置 - 集成 Meziantou.Analyzer 和 Meziantou.Polyfill 包引用 - 配置项目构建属性和命名空间引入设置 --- ....Core.SourceGenerators.Abstractions.csproj | 2 +- docs/zh-CN/source-generators/index.md | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj b/GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj index 86fe2d35..03d4dd42 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj +++ b/GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj @@ -12,7 +12,7 @@ - + diff --git a/docs/zh-CN/source-generators/index.md b/docs/zh-CN/source-generators/index.md index 224ed96a..c1d65128 100644 --- a/docs/zh-CN/source-generators/index.md +++ b/docs/zh-CN/source-generators/index.md @@ -167,7 +167,7 @@ Config Schema 生成器会扫描 `*.schema.json` 文件,并生成: ### 基础使用 ```csharp -using GFramework.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log] public partial class PlayerController @@ -246,7 +246,7 @@ public static partial class MathHelper ```csharp using GFramework.Core.Abstractions.Controller; -using GFramework.SourceGenerators.Abstractions.Rule; +using GFramework.Core.SourceGenerators.Abstractions.Rule; [ContextAware] public partial class PlayerController : IController @@ -354,8 +354,8 @@ public async Task TestPlayerController() ```csharp using GFramework.Core.Abstractions.Controller; -using GFramework.SourceGenerators.Abstractions.Logging; -using GFramework.SourceGenerators.Abstractions.Rule; +using GFramework.Core.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Rule; [Log] [ContextAware] @@ -381,7 +381,7 @@ public partial class AdvancedController : IController ### 基础使用 ```csharp -using GFramework.SourceGenerators.Abstractions.Enums; +using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions] public enum GameState @@ -560,7 +560,7 @@ AutoRegisterModule 生成器面向 GFramework 模块安装场景,为类上的 ### 基础示例 ```csharp -using GFramework.SourceGenerators.Abstractions.Architectures; +using GFramework.Core.SourceGenerators.Abstractions.Architectures; [AutoRegisterModule] [RegisterModel(typeof(RunStateModel))] @@ -863,8 +863,8 @@ public class InefficientController : IController ```csharp using GFramework.Core.Abstractions.Controller; -using GFramework.SourceGenerators.Abstractions.Logging; -using GFramework.SourceGenerators.Abstractions.Rule; +using GFramework.Core.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Rule; [Log] [ContextAware] @@ -953,8 +953,8 @@ public enum CharacterState } using GFramework.Core.Abstractions.Controller; -using GFramework.SourceGenerators.Abstractions.Logging; -using GFramework.SourceGenerators.Abstractions.Rule; +using GFramework.Core.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Rule; [Log] [ContextAware] @@ -1235,7 +1235,7 @@ public partial class ServiceComponent : IService ```mermaid graph TD - A[GFramework.SourceGenerators] --> B[GFramework.SourceGenerators.Abstractions] + A[GFramework.SourceGenerators] --> B[GFramework.Core.SourceGenerators.Abstractions] A --> C[GFramework.SourceGenerators.Common] A --> D[GFramework.Core.Abstractions] A --> E[Microsoft.CodeAnalysis.CSharp] From 534818f5f6a8d7366d7bd6cd1f774e2ad0757775 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:40:47 +0800 Subject: [PATCH 4/8] =?UTF-8?q?docs(source-generators):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=BA=90=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=92=8C=E7=9B=B8=E5=85=B3=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增完整的 GFramework.SourceGenerators 文档,涵盖所有核心特性 - 添加 Log 属性生成器、Config Schema 生成器等详细使用说明 - 添加 ContextAware、GenerateEnumExtensions 等属性生成器文档 - 添加 Godot 专用生成器如 GetNode、BindNodeSignal 等使用指南 - 添加 AutoRegisterModule、AutoUiPage、AutoScene 等自动化工具文档 - 添加诊断信息、性能优势、使用示例和最佳实践章节 - 新增 PathContests 常量类定义 GFramework 项目路径常量 - 添加 ContextRegistrationAnalyzerTests 测试类验证上下文注册分析器 --- .../Constants/PathContests.cs | 2 +- .../ContextRegistrationAnalyzerTests.cs | 20 +++--- .../AutoRegisterModuleGeneratorTests.cs | 18 +++--- .../Bases/PriorityGeneratorSnapshotTests.cs | 16 ++--- .../EnumExtensionsGeneratorSnapshotTests.cs | 20 +++--- .../Logging/LoggerGeneratorSnapshotTests.cs | 24 +++---- .../ContextAwareGeneratorSnapshotTests.cs | 4 +- .../Rule/ContextGetGeneratorTests.cs | 62 +++++++++---------- docs/zh-CN/source-generators/index.md | 10 ++- 9 files changed, 90 insertions(+), 86 deletions(-) diff --git a/GFramework.SourceGenerators.Common/Constants/PathContests.cs b/GFramework.SourceGenerators.Common/Constants/PathContests.cs index a9416fbe..cae0748c 100644 --- a/GFramework.SourceGenerators.Common/Constants/PathContests.cs +++ b/GFramework.SourceGenerators.Common/Constants/PathContests.cs @@ -39,7 +39,7 @@ public static class PathContests /// /// GFramework源代码生成器抽象层命名空间 /// - public const string SourceGeneratorsAbstractionsPath = $"{BaseNamespace}.SourceGenerators.Abstractions"; + public const string SourceGeneratorsAbstractionsPath = $"{CoreNamespace}.SourceGenerators.Abstractions"; /// /// GFramework Godot源代码生成器抽象层命名空间 diff --git a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs index abcb4ccf..20d25f24 100644 --- a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs +++ b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs @@ -121,7 +121,7 @@ public sealed class ContextRegistrationAnalyzerTests } } - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { public sealed class GetModelAttribute : Attribute { } public sealed class GetModelsAttribute : Attribute { } @@ -142,7 +142,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -180,7 +180,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -255,7 +255,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -297,7 +297,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -337,7 +337,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryUtility : IUtility { } @@ -376,7 +376,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -423,7 +423,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -477,7 +477,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } @@ -532,7 +532,7 @@ public sealed class ContextRegistrationAnalyzerTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; public interface IInventoryModel : IModel { } diff --git a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs index ae44a8ed..5eafa7c2 100644 --- a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs @@ -14,9 +14,9 @@ public class AutoRegisterModuleGeneratorTests { const string source = """ using System; - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; - namespace GFramework.SourceGenerators.Abstractions.Architectures + namespace GFramework.Core.SourceGenerators.Abstractions.Architectures { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoRegisterModuleAttribute : Attribute { } @@ -70,7 +70,7 @@ public class AutoRegisterModuleGeneratorTests using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; public sealed class PlayerModel : IModel { } public sealed class CombatSystem : ISystem { } @@ -118,7 +118,7 @@ public class AutoRegisterModuleGeneratorTests const string commonSource = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Architectures + namespace GFramework.Core.SourceGenerators.Abstractions.Architectures { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoRegisterModuleAttribute : Attribute { } @@ -182,7 +182,7 @@ public class AutoRegisterModuleGeneratorTests const string partASource = """ namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; // Padding ensures this attribute lives later in the file than the attributes in PartB. // The generator should still place it first because PartA sorts before PartB. @@ -207,7 +207,7 @@ public class AutoRegisterModuleGeneratorTests const string partBSource = """ namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; [RegisterSystem(typeof(CombatSystem))] [RegisterModel(typeof(PlayerModel))] @@ -266,9 +266,9 @@ public class AutoRegisterModuleGeneratorTests const string source = """ #nullable enable using System; - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; - namespace GFramework.SourceGenerators.Abstractions.Architectures + namespace GFramework.Core.SourceGenerators.Abstractions.Architectures { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoRegisterModuleAttribute : Attribute { } @@ -320,7 +320,7 @@ public class AutoRegisterModuleGeneratorTests namespace TestApp { using GFramework.Core.Abstractions.Model; - using GFramework.SourceGenerators.Abstractions.Architectures; + using GFramework.Core.SourceGenerators.Abstractions.Architectures; public sealed class PlayerModel : IModel { } diff --git a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs index bb29762a..79da21bb 100644 --- a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs @@ -19,7 +19,7 @@ public class PriorityGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Bases + namespace GFramework.Core.SourceGenerators.Abstractions.Bases { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class PriorityAttribute : Attribute @@ -39,7 +39,7 @@ public class PriorityGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Bases; + using GFramework.Core.SourceGenerators.Abstractions.Bases; [Priority(10)] public partial class MySystem @@ -67,7 +67,7 @@ public class PriorityGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Bases + namespace GFramework.Core.SourceGenerators.Abstractions.Bases { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class PriorityAttribute : Attribute @@ -87,7 +87,7 @@ public class PriorityGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Bases; + using GFramework.Core.SourceGenerators.Abstractions.Bases; [Priority(-100)] public partial class CriticalSystem @@ -115,7 +115,7 @@ public class PriorityGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Bases + namespace GFramework.Core.SourceGenerators.Abstractions.Bases { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class PriorityAttribute : Attribute @@ -144,7 +144,7 @@ public class PriorityGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Bases; + using GFramework.Core.SourceGenerators.Abstractions.Bases; using GFramework.Core.Abstractions.Bases; [Priority(PriorityGroup.High)] @@ -173,7 +173,7 @@ public class PriorityGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Bases + namespace GFramework.Core.SourceGenerators.Abstractions.Bases { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class PriorityAttribute : Attribute @@ -193,7 +193,7 @@ public class PriorityGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Bases; + using GFramework.Core.SourceGenerators.Abstractions.Bases; [Priority(20)] public partial class GenericSystem diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index f9ddf5c0..e70b4020 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -13,7 +13,7 @@ public class EnumExtensionsGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Enums + namespace GFramework.Core.SourceGenerators.Abstractions.Enums { [AttributeUsage(AttributeTargets.Enum)] public sealed class GenerateEnumExtensionsAttribute : Attribute @@ -25,7 +25,7 @@ public class EnumExtensionsGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Enums; + using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions] public enum Status @@ -53,7 +53,7 @@ public class EnumExtensionsGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Enums + namespace GFramework.Core.SourceGenerators.Abstractions.Enums { [AttributeUsage(AttributeTargets.Enum)] public sealed class GenerateEnumExtensionsAttribute : Attribute @@ -65,7 +65,7 @@ public class EnumExtensionsGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Enums; + using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions] public enum Status @@ -92,7 +92,7 @@ public class EnumExtensionsGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Enums + namespace GFramework.Core.SourceGenerators.Abstractions.Enums { [AttributeUsage(AttributeTargets.Enum)] public sealed class GenerateEnumExtensionsAttribute : Attribute @@ -104,7 +104,7 @@ public class EnumExtensionsGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Enums; + using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions] [Flags] @@ -134,7 +134,7 @@ public class EnumExtensionsGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Enums + namespace GFramework.Core.SourceGenerators.Abstractions.Enums { [AttributeUsage(AttributeTargets.Enum)] public sealed class GenerateEnumExtensionsAttribute : Attribute @@ -146,7 +146,7 @@ public class EnumExtensionsGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Enums; + using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions(GenerateIsMethods = false)] public enum Status @@ -173,7 +173,7 @@ public class EnumExtensionsGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Enums + namespace GFramework.Core.SourceGenerators.Abstractions.Enums { [AttributeUsage(AttributeTargets.Enum)] public sealed class GenerateEnumExtensionsAttribute : Attribute @@ -185,7 +185,7 @@ public class EnumExtensionsGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Enums; + using GFramework.Core.SourceGenerators.Abstractions.Enums; [GenerateEnumExtensions(GenerateIsInMethod = false)] public enum Status diff --git a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs index e1263a0f..07bb60a2 100644 --- a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs @@ -13,7 +13,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -85,7 +85,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log] public partial class MyService @@ -110,7 +110,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -182,7 +182,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log(Name = "CustomLogger")] public partial class MyService @@ -207,7 +207,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -279,7 +279,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log(FieldName = "MyLogger")] public partial class MyService @@ -304,7 +304,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -376,7 +376,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log(IsStatic = false)] public partial class MyService @@ -401,7 +401,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -473,7 +473,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log(AccessModifier = "public")] public partial class MyService @@ -498,7 +498,7 @@ public class LoggerGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Logging + namespace GFramework.Core.SourceGenerators.Abstractions.Logging { [AttributeUsage(AttributeTargets.Class)] public sealed class LogAttribute : Attribute @@ -570,7 +570,7 @@ public class LoggerGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Logging; + using GFramework.Core.SourceGenerators.Abstractions.Logging; [Log] public partial class MyService diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs index 415a7f09..e7b352bf 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs @@ -23,7 +23,7 @@ public class ContextAwareGeneratorSnapshotTests const string source = """ using System; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class)] public sealed class ContextAwareAttribute : Attribute { } @@ -73,7 +73,7 @@ public class ContextAwareGeneratorSnapshotTests namespace TestApp { - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; using GFramework.Core.Abstractions.Rule; [ContextAware] diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs index d16806e6..bae2d00c 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs @@ -12,9 +12,9 @@ public class ContextGetGeneratorTests var source = """ using System; using System.Collections.Generic; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class ContextAwareAttribute : Attribute { } @@ -102,9 +102,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class ContextAwareAttribute : Attribute { } @@ -148,7 +148,7 @@ public class ContextGetGeneratorTests [ContextAware] public partial class InventoryPanel { - [global::GFramework.SourceGenerators.Abstractions.Rule.GetModel] + [global::GFramework.Core.SourceGenerators.Abstractions.Rule.GetModel] private IInventoryModel _model = null!; } } @@ -184,9 +184,9 @@ public class ContextGetGeneratorTests var source = """ using System; using System.Collections.Generic; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class GetAllAttribute : Attribute { } @@ -291,9 +291,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class GetAllAttribute : Attribute { } @@ -382,9 +382,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class ContextAwareAttribute : Attribute { } @@ -460,9 +460,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class GetAllAttribute : Attribute { } @@ -543,9 +543,9 @@ public class ContextGetGeneratorTests { var source = MarkupTestSource.Parse(""" using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class GetAllAttribute : Attribute { } @@ -644,9 +644,9 @@ public class ContextGetGeneratorTests { var source = MarkupTestSource.Parse(""" using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class GetAllAttribute : Attribute { } @@ -753,9 +753,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class ContextAwareAttribute : Attribute { } @@ -845,9 +845,9 @@ public class ContextGetGeneratorTests { var source = """ using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetServiceAttribute : Attribute { } @@ -922,9 +922,9 @@ public class ContextGetGeneratorTests { var source = MarkupTestSource.Parse(""" using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetModelAttribute : Attribute { } @@ -989,9 +989,9 @@ public class ContextGetGeneratorTests var source = MarkupTestSource.Parse(""" using System; using System.Collections.Generic; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetModelsAttribute : Attribute { } @@ -1060,9 +1060,9 @@ public class ContextGetGeneratorTests { var source = MarkupTestSource.Parse(""" using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetModelAttribute : Attribute { } @@ -1131,9 +1131,9 @@ public class ContextGetGeneratorTests { var source = MarkupTestSource.Parse(""" using System; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetModelAttribute : Attribute { } @@ -1203,9 +1203,9 @@ public class ContextGetGeneratorTests var source = """ using System; using System.Collections.Generic; - using GFramework.SourceGenerators.Abstractions.Rule; + using GFramework.Core.SourceGenerators.Abstractions.Rule; - namespace GFramework.SourceGenerators.Abstractions.Rule + namespace GFramework.Core.SourceGenerators.Abstractions.Rule { [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class GetModelsAttribute : Attribute { } diff --git a/docs/zh-CN/source-generators/index.md b/docs/zh-CN/source-generators/index.md index c1d65128..1b4638d1 100644 --- a/docs/zh-CN/source-generators/index.md +++ b/docs/zh-CN/source-generators/index.md @@ -89,10 +89,10 @@ GFramework 的 source generators 利用 Roslyn 源代码生成器技术,在编 - - @@ -102,6 +102,7 @@ GFramework 的 source generators 利用 Roslyn 源代码生成器技术,在编 如果你只使用 Godot 生成器或 CQRS 处理器注册生成器,请把上面的包替换为对应的 `GeWuYou.GFramework.Godot.SourceGenerators` 或 `GeWuYou.GFramework.Cqrs.SourceGenerators`。 这些拆分包会同时带上各自需要的 abstractions 程序集,不需要再额外安装单独的 `*.Attributes` 包。 +实际接入时请替换为当前发布版本,或与项目中其余 `GeWuYou.GFramework.*` 包保持同一版本。 ### Config Schema 文件约定 @@ -1235,11 +1236,14 @@ public partial class ServiceComponent : IService ```mermaid graph TD - A[GFramework.SourceGenerators] --> B[GFramework.Core.SourceGenerators.Abstractions] + A[GeWuYou.GFramework.Core.SourceGenerators] --> B[GFramework.Core.SourceGenerators.Abstractions] A --> C[GFramework.SourceGenerators.Common] A --> D[GFramework.Core.Abstractions] A --> E[Microsoft.CodeAnalysis.CSharp] A --> F[Microsoft.CodeAnalysis.Analyzers] + G[GeWuYou.GFramework.Game.SourceGenerators] --> C + H[GeWuYou.GFramework.Godot.SourceGenerators] --> C + I[GeWuYou.GFramework.Cqrs.SourceGenerators] --> C ``` ## 版本兼容性 From 08b12ae8525002223d76be9b50f390309630fada Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:49:59 +0800 Subject: [PATCH 5/8] =?UTF-8?q?test(EnumExtensions):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=E6=89=A9=E5=B1=95=E7=94=9F=E6=88=90=E5=99=A8?= =?UTF-8?q?=E5=BF=AB=E7=85=A7=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现基本枚举的 IsMethods 快照测试 - 实现基本枚举的 IsInMethod 快照测试 - 实现带标志值枚举的快照测试 - 实现禁用 IsMethods 选项的快照测试 - 实现禁用 IsInMethod 选项的快照测试 - 创建统一的源代码构建方法用于测试场景 --- .../EnumExtensionsGeneratorSnapshotTests.cs | 202 +++++++----------- 1 file changed, 73 insertions(+), 129 deletions(-) diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index e70b4020..e5c27226 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -7,35 +7,20 @@ namespace GFramework.SourceGenerators.Tests.Enums; [TestFixture] public class EnumExtensionsGeneratorSnapshotTests { + private const string EnumAttributeNamespace = "GFramework.Core.SourceGenerators.Abstractions.Enums"; + [Test] public async Task Snapshot_BasicEnum_IsMethods() { - const string source = """ - using System; - - namespace GFramework.Core.SourceGenerators.Abstractions.Enums - { - [AttributeUsage(AttributeTargets.Enum)] - public sealed class GenerateEnumExtensionsAttribute : Attribute - { - public bool GenerateIsMethods { get; set; } = true; - public bool GenerateIsInMethod { get; set; } = true; - } - } - - namespace TestApp - { - using GFramework.Core.SourceGenerators.Abstractions.Enums; - - [GenerateEnumExtensions] - public enum Status - { - Active, - Inactive, - Pending - } - } - """; + var source = BuildSource( + """ + public enum Status + { + Active, + Inactive, + Pending + } + """); await GeneratorSnapshotTest.RunAsync( source, @@ -50,31 +35,14 @@ public class EnumExtensionsGeneratorSnapshotTests [Test] public async Task Snapshot_BasicEnum_IsInMethod() { - const string source = """ - using System; - - namespace GFramework.Core.SourceGenerators.Abstractions.Enums - { - [AttributeUsage(AttributeTargets.Enum)] - public sealed class GenerateEnumExtensionsAttribute : Attribute - { - public bool GenerateIsMethods { get; set; } = true; - public bool GenerateIsInMethod { get; set; } = true; - } - } - - namespace TestApp - { - using GFramework.Core.SourceGenerators.Abstractions.Enums; - - [GenerateEnumExtensions] - public enum Status - { - Active, - Inactive - } - } - """; + var source = BuildSource( + """ + public enum Status + { + Active, + Inactive + } + """); await GeneratorSnapshotTest.RunAsync( source, @@ -89,34 +57,17 @@ public class EnumExtensionsGeneratorSnapshotTests [Test] public async Task Snapshot_EnumWithFlagValues() { - const string source = """ - using System; - - namespace GFramework.Core.SourceGenerators.Abstractions.Enums - { - [AttributeUsage(AttributeTargets.Enum)] - public sealed class GenerateEnumExtensionsAttribute : Attribute - { - public bool GenerateIsMethods { get; set; } = true; - public bool GenerateIsInMethod { get; set; } = true; - } - } - - namespace TestApp - { - using GFramework.Core.SourceGenerators.Abstractions.Enums; - - [GenerateEnumExtensions] - [Flags] - public enum Permissions - { - None = 0, - Read = 1, - Write = 2, - Execute = 4 - } - } - """; + var source = BuildSource( + """ + [Flags] + public enum Permissions + { + None = 0, + Read = 1, + Write = 2, + Execute = 4 + } + """); await GeneratorSnapshotTest.RunAsync( source, @@ -131,31 +82,15 @@ public class EnumExtensionsGeneratorSnapshotTests [Test] public async Task Snapshot_DisableIsMethods() { - const string source = """ - using System; - - namespace GFramework.Core.SourceGenerators.Abstractions.Enums - { - [AttributeUsage(AttributeTargets.Enum)] - public sealed class GenerateEnumExtensionsAttribute : Attribute - { - public bool GenerateIsMethods { get; set; } = true; - public bool GenerateIsInMethod { get; set; } = true; - } - } - - namespace TestApp - { - using GFramework.Core.SourceGenerators.Abstractions.Enums; - - [GenerateEnumExtensions(GenerateIsMethods = false)] - public enum Status - { - Active, - Inactive - } - } - """; + var source = BuildSource( + """ + public enum Status + { + Active, + Inactive + } + """, + "[GenerateEnumExtensions(GenerateIsMethods = false)]"); await GeneratorSnapshotTest.RunAsync( source, @@ -170,31 +105,15 @@ public class EnumExtensionsGeneratorSnapshotTests [Test] public async Task Snapshot_DisableIsInMethod() { - const string source = """ - using System; - - namespace GFramework.Core.SourceGenerators.Abstractions.Enums - { - [AttributeUsage(AttributeTargets.Enum)] - public sealed class GenerateEnumExtensionsAttribute : Attribute - { - public bool GenerateIsMethods { get; set; } = true; - public bool GenerateIsInMethod { get; set; } = true; - } - } - - namespace TestApp - { - using GFramework.Core.SourceGenerators.Abstractions.Enums; - - [GenerateEnumExtensions(GenerateIsInMethod = false)] - public enum Status - { - Active, - Inactive - } - } - """; + var source = BuildSource( + """ + public enum Status + { + Active, + Inactive + } + """, + "[GenerateEnumExtensions(GenerateIsInMethod = false)]"); await GeneratorSnapshotTest.RunAsync( source, @@ -205,4 +124,29 @@ public class EnumExtensionsGeneratorSnapshotTests "EnumExtensionsGenerator", "DisableIsInMethod")); } + + private static string BuildSource(string enumBody, string attributeUsage = "[GenerateEnumExtensions]") + { + return $$""" + using System; + + namespace {{EnumAttributeNamespace}} + { + [AttributeUsage(AttributeTargets.Enum)] + public sealed class GenerateEnumExtensionsAttribute : Attribute + { + public bool GenerateIsMethods { get; set; } = true; + public bool GenerateIsInMethod { get; set; } = true; + } + } + + namespace TestApp + { + using {{EnumAttributeNamespace}}; + + {{attributeUsage}} + {{enumBody}} + } + """; + } } From 30e3ca05fdae7bf55b72fbe64d5b39037ed866a8 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 22:16:06 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat(enum):=20=E6=B7=BB=E5=8A=A0=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 EnumExtensionsGenerator 自动生成枚举扩展方法 - 支持 GenerateIsMethods 和 GenerateIsInMethod 两种生成开关 - 添加完整的单元测试和快照验证机制 - 实现 IsIn 扩展方法支持多值匹配功能 - 支持带显式位标志值的枚举生成扩展方法 - 提供灵活的属性参数配置选项 --- .../Enums/EnumExtensionsGenerator.cs | 124 +++++++++++++++--- .../EnumExtensionsGeneratorSnapshotTests.cs | 105 ++++++++++----- .../Status.EnumExtensions.g.cs | 21 +++ .../Status.EnumExtensions.g.cs | 24 ++++ .../Status.EnumExtensions.g.cs | 8 ++ .../Status.EnumExtensions.g.cs | 13 ++ .../Status.EnumExtensions.g.cs | 15 +++ .../Permissions.EnumExtensions.g.cs | 27 ++++ .../GFramework.SourceGenerators.Tests.csproj | 2 + 9 files changed, 294 insertions(+), 45 deletions(-) create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs create mode 100644 GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs diff --git a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs index 493c10e1..a73d076d 100644 --- a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs +++ b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs @@ -1,4 +1,5 @@ -using GFramework.SourceGenerators.Common.Constants; +using GFramework.Core.SourceGenerators.Abstractions.Enums; +using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; @@ -18,6 +19,12 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase /// protected override string AttributeShortNameWithoutSuffix => "GenerateEnumExtensions"; + /// + /// 按元数据名称解析枚举上的 GenerateEnumExtensionsAttribute。 + /// + /// 当前编译上下文。 + /// 待检查的枚举符号。 + /// 匹配到的属性数据;若未标注目标属性则返回 protected override AttributeData? ResolveAttribute(Compilation compilation, INamedTypeSymbol symbol) { var attrSymbol = compilation.GetTypeByMetadataName(AttributeMetadataName); @@ -30,6 +37,15 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol)); } + /// + /// 验证候选符号仍然是可生成扩展方法的枚举类型。 + /// + /// 源生成诊断上下文。 + /// 当前编译上下文。 + /// 候选枚举声明语法。 + /// 候选命名类型符号。 + /// 已解析出的生成器属性。 + /// 当符号满足生成前置条件时返回 protected override bool ValidateSymbol(SourceProductionContext context, Compilation compilation, EnumDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr) @@ -56,6 +72,14 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase ? null : symbol.ContainingNamespace.ToDisplayString(); + var generateIsMethods = GetNamedBooleanArgument( + attr, + nameof(GenerateEnumExtensionsAttribute.GenerateIsMethods), + true); + var generateIsInMethod = GetNamedBooleanArgument( + attr, + nameof(GenerateEnumExtensionsAttribute.GenerateIsInMethod), + true); var enumName = symbol.Name; var fullEnumName = symbol.ToDisplayString(); var members = symbol.GetMembers() @@ -74,23 +98,28 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase sb.AppendLine($" public static partial class {enumName}Extensions"); sb.AppendLine(" {"); - // 生成 IsX 方法 - foreach (var memberName in members.Select(m => m.Name)) + // 两个生成开关是彼此独立的契约,需要分别控制输出,并保持空行布局稳定,便于快照精确回归。 + var hasGeneratedMembers = false; + + if (generateIsMethods) { - sb.AppendLine($" /// 是否为 {memberName}"); - sb.AppendLine( - $" public static bool Is{memberName}(this {fullEnumName} value) => value == {fullEnumName}.{memberName};"); - sb.AppendLine(); + hasGeneratedMembers = AppendIsMethods( + sb, + members, + fullEnumName); } - // 生成 IsIn 方法 - sb.AppendLine(" /// 判断是否属于指定集合"); - sb.AppendLine($" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)"); - sb.AppendLine(" {"); - sb.AppendLine(" if (values == null) return false;"); - sb.AppendLine(" foreach (var v in values) if (value == v) return true;"); - sb.AppendLine(" return false;"); - sb.AppendLine(" }"); + if (generateIsInMethod) + { + if (hasGeneratedMembers) + { + sb.AppendLine(); + } + + AppendIsInMethod( + sb, + fullEnumName); + } sb.AppendLine(" }"); sb.AppendLine("}"); // namespace @@ -107,4 +136,69 @@ public sealed class EnumExtensionsGenerator : AttributeEnumGeneratorBase { return $"{symbol.Name}.EnumExtensions.g.cs"; } + + /// + /// 读取属性上的命名布尔参数,并在参数未显式提供时回退到属性契约默认值。 + /// + /// 待读取的属性数据。 + /// 命名参数名称。 + /// 属性未提供该参数时使用的默认值。 + /// 解析得到的布尔值;若参数缺失或类型不匹配则返回 + private static bool GetNamedBooleanArgument(AttributeData attribute, string argumentName, bool defaultValue) + { + foreach (var namedArgument in attribute.NamedArguments) + { + if (namedArgument.Key == argumentName && + namedArgument.Value.Value is bool value) + { + return value; + } + } + + return defaultValue; + } + + /// + /// 为每个枚举成员追加单值判断扩展方法。 + /// + /// 目标源码构建器。 + /// 需要生成扩展方法的枚举成员。 + /// 枚举的完整类型名。 + /// 当至少生成了一个方法时返回 + private static bool AppendIsMethods(StringBuilder builder, IEnumerable members, string fullEnumName) + { + var hasGeneratedMembers = false; + + foreach (var memberName in members.Select(m => m.Name)) + { + if (hasGeneratedMembers) + { + builder.AppendLine(); + } + + builder.AppendLine($" /// 是否为 {memberName}"); + builder.AppendLine( + $" public static bool Is{memberName}(this {fullEnumName} value) => value == {fullEnumName}.{memberName};"); + hasGeneratedMembers = true; + } + + return hasGeneratedMembers; + } + + /// + /// 追加用于多值匹配的 IsIn 扩展方法。 + /// + /// 目标源码构建器。 + /// 枚举的完整类型名。 + private static void AppendIsInMethod(StringBuilder builder, string fullEnumName) + { + builder.AppendLine(" /// 判断是否属于指定集合"); + builder.AppendLine( + $" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)"); + builder.AppendLine(" {"); + builder.AppendLine(" if (values == null) return false;"); + builder.AppendLine(" foreach (var v in values) if (value == v) return true;"); + builder.AppendLine(" return false;"); + builder.AppendLine(" }"); + } } diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index e5c27226..ce109a36 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -4,11 +4,17 @@ using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Enums; +/// +/// 验证枚举扩展生成器在不同属性开关组合下的快照输出。 +/// [TestFixture] public class EnumExtensionsGeneratorSnapshotTests { private const string EnumAttributeNamespace = "GFramework.Core.SourceGenerators.Abstractions.Enums"; + /// + /// 验证默认配置会为普通枚举生成逐项判断方法与集合判断方法。 + /// [Test] public async Task Snapshot_BasicEnum_IsMethods() { @@ -24,14 +30,12 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - Path.Combine( - TestContext.CurrentContext.TestDirectory, - "enums", - "snapshots", - "EnumExtensionsGenerator", - "BasicEnum_IsMethods")); + GetSnapshotFolder("BasicEnum_IsMethods")); } + /// + /// 验证默认配置在较小枚举上仍会生成集合判断方法。 + /// [Test] public async Task Snapshot_BasicEnum_IsInMethod() { @@ -46,14 +50,12 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - Path.Combine( - TestContext.CurrentContext.TestDirectory, - "enums", - "snapshots", - "EnumExtensionsGenerator", - "BasicEnum_IsInMethod")); + GetSnapshotFolder("BasicEnum_IsInMethod")); } + /// + /// 验证带显式位标志值的枚举也会生成对应扩展方法。 + /// [Test] public async Task Snapshot_EnumWithFlagValues() { @@ -71,14 +73,12 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - Path.Combine( - TestContext.CurrentContext.TestDirectory, - "enums", - "snapshots", - "EnumExtensionsGenerator", - "EnumWithFlagValues")); + GetSnapshotFolder("EnumWithFlagValues")); } + /// + /// 验证关闭逐项判断开关后仅保留集合判断方法。 + /// [Test] public async Task Snapshot_DisableIsMethods() { @@ -94,14 +94,12 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - Path.Combine( - TestContext.CurrentContext.TestDirectory, - "enums", - "snapshots", - "EnumExtensionsGenerator", - "DisableIsMethods")); + GetSnapshotFolder("DisableIsMethods")); } + /// + /// 验证关闭集合判断开关后仅保留逐项判断方法。 + /// [Test] public async Task Snapshot_DisableIsInMethod() { @@ -117,16 +115,63 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - Path.Combine( - TestContext.CurrentContext.TestDirectory, - "enums", - "snapshots", - "EnumExtensionsGenerator", - "DisableIsInMethod")); + GetSnapshotFolder("DisableIsInMethod")); } + /// + /// 验证同时关闭两个生成开关时不会输出任何扩展方法。 + /// + [Test] + public async Task Snapshot_DisableAllGeneratedMethods() + { + var source = BuildSource( + """ + public enum Status + { + Active, + Inactive + } + """, + "[GenerateEnumExtensions(GenerateIsMethods = false, GenerateIsInMethod = false)]"); + + await GeneratorSnapshotTest.RunAsync( + source, + GetSnapshotFolder("DisableAllGeneratedMethods")); + } + + /// + /// 将运行时测试目录映射回仓库内已提交的枚举快照目录。 + /// + /// 快照场景名称。 + /// 场景对应的绝对快照目录。 + private static string GetSnapshotFolder(string scenarioName) + { + return Path.GetFullPath( + Path.Combine( + TestContext.CurrentContext.TestDirectory, + "..", + "..", + "..", + "Enums", + "snapshots", + "EnumExtensionsGenerator", + scenarioName)); + } + + /// + /// 构造最小自洽的测试输入源码,以稳定驱动枚举扩展生成器的快照测试。 + /// + /// 要注入到测试命名空间中的枚举声明文本。 + /// 枚举上的属性使用方式,默认启用所有生成选项。 + /// 包含内联测试属性与目标枚举声明的完整源码。 + /// + /// 这里内联声明 GenerateEnumExtensionsAttribute,以便每个快照输入保持最小自洽。 + /// 属性命名空间必须与生成器按 metadata name 查找的契约保持一致;如果命名空间、属性名或参数发生变更, + /// 需要同步更新该模板与相关快照,否则测试可能出现静默漂移。 + /// private static string BuildSource(string enumBody, string attributeUsage = "[GenerateEnumExtensions]") { + // 保持属性声明与测试输入同处一个模板中,能够明确锁定生成器对元数据名称和可选参数的语义假设。 return $$""" using System; diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs new file mode 100644 index 00000000..2897d09c --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs @@ -0,0 +1,21 @@ +// +using System; +namespace TestApp +{ + public static partial class StatusExtensions + { + /// 是否为 Active + public static bool IsActive(this TestApp.Status value) => value == TestApp.Status.Active; + + /// 是否为 Inactive + public static bool IsInactive(this TestApp.Status value) => value == TestApp.Status.Inactive; + + /// 判断是否属于指定集合 + public static bool IsIn(this TestApp.Status value, params TestApp.Status[] values) + { + if (values == null) return false; + foreach (var v in values) if (value == v) return true; + return false; + } + } +} diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs new file mode 100644 index 00000000..db9fa7ba --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs @@ -0,0 +1,24 @@ +// +using System; +namespace TestApp +{ + public static partial class StatusExtensions + { + /// 是否为 Active + public static bool IsActive(this TestApp.Status value) => value == TestApp.Status.Active; + + /// 是否为 Inactive + public static bool IsInactive(this TestApp.Status value) => value == TestApp.Status.Inactive; + + /// 是否为 Pending + public static bool IsPending(this TestApp.Status value) => value == TestApp.Status.Pending; + + /// 判断是否属于指定集合 + public static bool IsIn(this TestApp.Status value, params TestApp.Status[] values) + { + if (values == null) return false; + foreach (var v in values) if (value == v) return true; + return false; + } + } +} diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs new file mode 100644 index 00000000..74b39b20 --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs @@ -0,0 +1,8 @@ +// +using System; +namespace TestApp +{ + public static partial class StatusExtensions + { + } +} diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs new file mode 100644 index 00000000..3563db50 --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs @@ -0,0 +1,13 @@ +// +using System; +namespace TestApp +{ + public static partial class StatusExtensions + { + /// 是否为 Active + public static bool IsActive(this TestApp.Status value) => value == TestApp.Status.Active; + + /// 是否为 Inactive + public static bool IsInactive(this TestApp.Status value) => value == TestApp.Status.Inactive; + } +} diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs new file mode 100644 index 00000000..41154546 --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs @@ -0,0 +1,15 @@ +// +using System; +namespace TestApp +{ + public static partial class StatusExtensions + { + /// 判断是否属于指定集合 + public static bool IsIn(this TestApp.Status value, params TestApp.Status[] values) + { + if (values == null) return false; + foreach (var v in values) if (value == v) return true; + return false; + } + } +} diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs new file mode 100644 index 00000000..ebd87525 --- /dev/null +++ b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs @@ -0,0 +1,27 @@ +// +using System; +namespace TestApp +{ + public static partial class PermissionsExtensions + { + /// 是否为 None + public static bool IsNone(this TestApp.Permissions value) => value == TestApp.Permissions.None; + + /// 是否为 Read + public static bool IsRead(this TestApp.Permissions value) => value == TestApp.Permissions.Read; + + /// 是否为 Write + public static bool IsWrite(this TestApp.Permissions value) => value == TestApp.Permissions.Write; + + /// 是否为 Execute + public static bool IsExecute(this TestApp.Permissions value) => value == TestApp.Permissions.Execute; + + /// 判断是否属于指定集合 + public static bool IsIn(this TestApp.Permissions value, params TestApp.Permissions[] values) + { + if (values == null) return false; + foreach (var v in values) if (value == v) return true; + return false; + } + } +} diff --git a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj index 885865ab..5bd55cf2 100644 --- a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj +++ b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj @@ -29,6 +29,8 @@ + + From 8e38afc6c426cd342ad48f1b1db9b1cbaaebbdfb Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 22:17:19 +0800 Subject: [PATCH 7/8] =?UTF-8?q?docs(generator):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=94=9F=E6=88=90=E5=99=A8=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 isDirectChildOfRoot 参数说明到 ParseProperty 方法 - 添加 isIndexedLookup 参数说明到 ParseArrayProperty 方法 --- .../Config/SchemaConfigGenerator.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs index aca981c8..f712ca0f 100644 --- a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs +++ b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs @@ -297,6 +297,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator /// 属性 JSON 节点。 /// 属性是否必填。 /// 逻辑字段路径。 + /// 属性是否为根对象下的直接子属性。 /// 解析后的属性信息或诊断。 private static ParsedPropertyResult ParseProperty( string filePath, @@ -954,6 +955,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator /// 标题元数据。 /// 说明元数据。 /// 目标引用表名称。 + /// 是否为索引查找。 /// 解析后的属性信息或诊断。 private static ParsedPropertyResult ParseArrayProperty( string filePath, From fe27dfe6096fbd9ad211e825b16fcce61c8c47d0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 22:34:09 +0800 Subject: [PATCH 8/8] =?UTF-8?q?test(generator):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=BA=90=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=E5=BF=AB?= =?UTF-8?q?=E7=85=A7=E6=B5=8B=E8=AF=95=E6=A1=86=E6=9E=B6=E5=92=8C=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E6=89=A9=E5=B1=95=E7=94=9F=E6=88=90=E5=99=A8=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 GeneratorSnapshotTest 类用于源代码生成器的快照测试功能 - 添加 EnumExtensionsGeneratorSnapshotTests 测试类验证各种枚举配置的输出 - 创建完整的快照测试基础设施支持生成器输出验证 - 配置测试项目依赖和快照文件管理规则 - 生成多个测试场景的快照文件验证枚举扩展生成功能 --- .../Core/GeneratorSnapshotTest.cs | 15 +++++----- .../EnumExtensionsGeneratorSnapshotTests.cs | 28 +++++++++++++++---- ...sions.g.cs => Status.EnumExtensions.g.txt} | 0 ...sions.g.cs => Status.EnumExtensions.g.txt} | 0 ...sions.g.cs => Status.EnumExtensions.g.txt} | 0 ...sions.g.cs => Status.EnumExtensions.g.txt} | 0 ...sions.g.cs => Status.EnumExtensions.g.txt} | 0 ....g.cs => Permissions.EnumExtensions.g.txt} | 0 .../GFramework.SourceGenerators.Tests.csproj | 2 ++ 9 files changed, 32 insertions(+), 13 deletions(-) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/{Status.EnumExtensions.g.cs => Status.EnumExtensions.g.txt} (100%) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/{Status.EnumExtensions.g.cs => Status.EnumExtensions.g.txt} (100%) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/{Status.EnumExtensions.g.cs => Status.EnumExtensions.g.txt} (100%) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/{Status.EnumExtensions.g.cs => Status.EnumExtensions.g.txt} (100%) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/{Status.EnumExtensions.g.cs => Status.EnumExtensions.g.txt} (100%) rename GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/{Permissions.EnumExtensions.g.cs => Permissions.EnumExtensions.g.txt} (100%) diff --git a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs index 129007fe..fcc0df3e 100644 --- a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs +++ b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs @@ -1,7 +1,4 @@ using System.IO; -using Microsoft.CodeAnalysis.CSharp.Testing; -using Microsoft.CodeAnalysis.Testing; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Core; @@ -17,10 +14,12 @@ public static class GeneratorSnapshotTest /// /// 输入的源代码字符串 /// 快照文件存储的文件夹路径 + /// 将生成文件名映射为快照文件名的规则;为空时使用原始生成文件名。 /// 异步任务 public static async Task RunAsync( string source, - string snapshotFolder) + string snapshotFolder, + Func? snapshotFileNameSelector = null) { var test = new CSharpSourceGeneratorTest { @@ -38,9 +37,11 @@ public static class GeneratorSnapshotTest foreach (var (filename, content) in generated) { + // 不同测试套件可能需要将生成文件映射到非 .cs 快照,以避免测试资产被当作可编译源码参与构建。 + var snapshotFileName = snapshotFileNameSelector?.Invoke(filename) ?? filename; var path = Path.Combine( snapshotFolder, - filename); + snapshotFileName); if (!File.Exists(path)) { @@ -57,7 +58,7 @@ public static class GeneratorSnapshotTest Assert.That( Normalize(expected), Is.EqualTo(Normalize(content.ToString())), - $"Snapshot mismatch: {filename}"); + $"Snapshot mismatch: {snapshotFileName}"); } } @@ -70,4 +71,4 @@ public static class GeneratorSnapshotTest { return text.Replace("\r\n", "\n").Trim(); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index ce109a36..459f4640 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -30,7 +30,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("BasicEnum_IsMethods")); + GetSnapshotFolder("BasicEnum_IsMethods"), + GetSnapshotFileName); } /// @@ -50,7 +51,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("BasicEnum_IsInMethod")); + GetSnapshotFolder("BasicEnum_IsInMethod"), + GetSnapshotFileName); } /// @@ -73,7 +75,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("EnumWithFlagValues")); + GetSnapshotFolder("EnumWithFlagValues"), + GetSnapshotFileName); } /// @@ -94,7 +97,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("DisableIsMethods")); + GetSnapshotFolder("DisableIsMethods"), + GetSnapshotFileName); } /// @@ -115,7 +119,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("DisableIsInMethod")); + GetSnapshotFolder("DisableIsInMethod"), + GetSnapshotFileName); } /// @@ -136,7 +141,8 @@ public class EnumExtensionsGeneratorSnapshotTests await GeneratorSnapshotTest.RunAsync( source, - GetSnapshotFolder("DisableAllGeneratedMethods")); + GetSnapshotFolder("DisableAllGeneratedMethods"), + GetSnapshotFileName); } /// @@ -158,6 +164,16 @@ public class EnumExtensionsGeneratorSnapshotTests scenarioName)); } + /// + /// 将生成器输出文件名映射为非 C# 快照文件名,避免快照资产被命名校验和项目编译误判为源码。 + /// + /// 生成器输出的提示文件名。 + /// 对应的快照文件名。 + private static string GetSnapshotFileName(string generatedFileName) + { + return Path.ChangeExtension(generatedFileName, ".txt"); + } + /// /// 构造最小自洽的测试输入源码,以稳定驱动枚举扩展生成器的快照测试。 /// diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsInMethod/Status.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/BasicEnum_IsMethods/Status.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableAllGeneratedMethods/Status.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsInMethod/Status.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/DisableIsMethods/Status.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs b/GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.txt similarity index 100% rename from GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.cs rename to GFramework.SourceGenerators.Tests/Enums/snapshots/EnumExtensionsGenerator/EnumWithFlagValues/Permissions.EnumExtensions.g.txt diff --git a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj index 5bd55cf2..e01f8c96 100644 --- a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj +++ b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj @@ -30,7 +30,9 @@ + +