diff --git a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs
index 5eafa7c2..1ad31c14 100644
--- a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs
+++ b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs
@@ -4,109 +4,323 @@ using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Architectures;
[TestFixture]
+///
+/// 验证 在模块自动注册场景下的生成契约与输出顺序。
+///
public class AutoRegisterModuleGeneratorTests
{
+ private const string AttributeOrderSource = """
+ using System;
+ using GFramework.Core.SourceGenerators.Abstractions.Architectures;
+
+ namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
+ {
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class AutoRegisterModuleAttribute : Attribute { }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterModelAttribute : Attribute
+ {
+ public RegisterModelAttribute(Type modelType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterSystemAttribute : Attribute
+ {
+ public RegisterSystemAttribute(Type systemType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterUtilityAttribute : Attribute
+ {
+ public RegisterUtilityAttribute(Type utilityType) { }
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Architectures
+ {
+ public interface IArchitecture
+ {
+ T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
+ T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
+ T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Model
+ {
+ public interface IModel { }
+ }
+
+ namespace GFramework.Core.Abstractions.Systems
+ {
+ public interface ISystem { }
+ }
+
+ namespace GFramework.Core.Abstractions.Utility
+ {
+ public interface IUtility { }
+ }
+
+ namespace TestApp
+ {
+ using GFramework.Core.Abstractions.Model;
+ using GFramework.Core.Abstractions.Systems;
+ using GFramework.Core.Abstractions.Utility;
+ using GFramework.Core.SourceGenerators.Abstractions.Architectures;
+
+ public sealed class PlayerModel : IModel { }
+ public sealed class CombatSystem : ISystem { }
+ public sealed class AudioUtility : IUtility { }
+
+ [AutoRegisterModule]
+ [RegisterSystem(typeof(CombatSystem))]
+ [RegisterModel(typeof(PlayerModel))]
+ [RegisterUtility(typeof(AudioUtility))]
+ public partial class GameplayModule
+ {
+ }
+ }
+ """;
+
+ private const string AttributeOrderExpected = """
+ //
+ #nullable enable
+
+ namespace TestApp;
+
+ partial class GameplayModule
+ {
+ public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
+ {
+ architecture.RegisterSystem(new global::TestApp.CombatSystem());
+ architecture.RegisterModel(new global::TestApp.PlayerModel());
+ architecture.RegisterUtility(new global::TestApp.AudioUtility());
+ }
+ }
+
+ """;
+
+ private const string DeterministicOrderCommonSource = """
+ using System;
+
+ namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
+ {
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class AutoRegisterModuleAttribute : Attribute { }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterModelAttribute : Attribute
+ {
+ public RegisterModelAttribute(Type modelType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterSystemAttribute : Attribute
+ {
+ public RegisterSystemAttribute(Type systemType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterUtilityAttribute : Attribute
+ {
+ public RegisterUtilityAttribute(Type utilityType) { }
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Architectures
+ {
+ public interface IArchitecture
+ {
+ T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
+ T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
+ T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Model
+ {
+ public interface IModel { }
+ }
+
+ namespace GFramework.Core.Abstractions.Systems
+ {
+ public interface ISystem { }
+ }
+
+ namespace GFramework.Core.Abstractions.Utility
+ {
+ public interface IUtility { }
+ }
+
+ namespace TestApp
+ {
+ using GFramework.Core.Abstractions.Model;
+ using GFramework.Core.Abstractions.Systems;
+ using GFramework.Core.Abstractions.Utility;
+
+ public sealed class PlayerModel : IModel { }
+ public sealed class CombatSystem : ISystem { }
+ public sealed class AudioUtility : IUtility { }
+ }
+ """;
+
+ private const string DeterministicOrderPartASource = """
+ namespace TestApp
+ {
+ 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.
+ // 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
+ {
+ }
+ }
+ """;
+
+ private const string DeterministicOrderPartBSource = """
+ namespace TestApp
+ {
+ using GFramework.Core.SourceGenerators.Abstractions.Architectures;
+
+ [RegisterSystem(typeof(CombatSystem))]
+ [RegisterModel(typeof(PlayerModel))]
+ public partial class GameplayModule
+ {
+ }
+ }
+ """;
+
+ private const string DeterministicOrderExpected = """
+ //
+ #nullable enable
+
+ namespace TestApp;
+
+ partial class GameplayModule
+ {
+ public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
+ {
+ architecture.RegisterUtility(new global::TestApp.AudioUtility());
+ architecture.RegisterSystem(new global::TestApp.CombatSystem());
+ architecture.RegisterModel(new global::TestApp.PlayerModel());
+ }
+ }
+
+ """;
+
+ private const string TypeConstraintSource = """
+ #nullable enable
+ using System;
+ using GFramework.Core.SourceGenerators.Abstractions.Architectures;
+
+ namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
+ {
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class AutoRegisterModuleAttribute : Attribute { }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterModelAttribute : Attribute
+ {
+ public RegisterModelAttribute(Type modelType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterSystemAttribute : Attribute
+ {
+ public RegisterSystemAttribute(Type systemType) { }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ public sealed class RegisterUtilityAttribute : Attribute
+ {
+ public RegisterUtilityAttribute(Type utilityType) { }
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Architectures
+ {
+ public interface IArchitecture
+ {
+ T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
+ T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
+ T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
+ }
+ }
+
+ namespace GFramework.Core.Abstractions.Model
+ {
+ public interface IModel { }
+ }
+
+ namespace GFramework.Core.Abstractions.Systems
+ {
+ public interface ISystem { }
+ }
+
+ namespace GFramework.Core.Abstractions.Utility
+ {
+ public interface IUtility { }
+ }
+
+ namespace TestApp
+ {
+ using GFramework.Core.Abstractions.Model;
+ using GFramework.Core.SourceGenerators.Abstractions.Architectures;
+
+ public sealed class PlayerModel : IModel { }
+
+ [AutoRegisterModule]
+ [RegisterModel(typeof(PlayerModel))]
+ public partial class GameplayModule
+ where TNullableRef : class?
+ where TNotNull : notnull
+ where TUnmanaged : unmanaged
+ {
+ }
+ }
+ """;
+
+ private const string TypeConstraintExpected = """
+ //
+ #nullable enable
+
+ namespace TestApp;
+
+ partial class GameplayModule
+ where TNullableRef : class?
+ where TNotNull : notnull
+ where TUnmanaged : unmanaged
+ {
+ public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
+ {
+ architecture.RegisterModel(new global::TestApp.PlayerModel());
+ }
+ }
+
+ """;
+
///
/// 验证同一声明上的注册特性会按照源码中的书写顺序生成安装代码。
///
[Test]
- public async Task Generates_Module_Install_Method_In_Attribute_Order()
+ public Task Generates_Module_Install_Method_In_Attribute_Order()
{
- const string source = """
- using System;
- using GFramework.Core.SourceGenerators.Abstractions.Architectures;
-
- namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
- {
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
- public sealed class AutoRegisterModuleAttribute : Attribute { }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterModelAttribute : Attribute
- {
- public RegisterModelAttribute(Type modelType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterSystemAttribute : Attribute
- {
- public RegisterSystemAttribute(Type systemType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterUtilityAttribute : Attribute
- {
- public RegisterUtilityAttribute(Type utilityType) { }
- }
- }
-
- namespace GFramework.Core.Abstractions.Architectures
- {
- public interface IArchitecture
- {
- T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
- T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
- T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
- }
- }
-
- namespace GFramework.Core.Abstractions.Model
- {
- public interface IModel { }
- }
-
- namespace GFramework.Core.Abstractions.Systems
- {
- public interface ISystem { }
- }
-
- namespace GFramework.Core.Abstractions.Utility
- {
- public interface IUtility { }
- }
-
- namespace TestApp
- {
- using GFramework.Core.Abstractions.Model;
- using GFramework.Core.Abstractions.Systems;
- using GFramework.Core.Abstractions.Utility;
- using GFramework.Core.SourceGenerators.Abstractions.Architectures;
-
- public sealed class PlayerModel : IModel { }
- public sealed class CombatSystem : ISystem { }
- public sealed class AudioUtility : IUtility { }
-
- [AutoRegisterModule]
- [RegisterSystem(typeof(CombatSystem))]
- [RegisterModel(typeof(PlayerModel))]
- [RegisterUtility(typeof(AudioUtility))]
- public partial class GameplayModule
- {
- }
- }
- """;
-
- const string expected = """
- //
- #nullable enable
-
- namespace TestApp;
-
- partial class GameplayModule
- {
- public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
- {
- architecture.RegisterSystem(new global::TestApp.CombatSystem());
- architecture.RegisterModel(new global::TestApp.PlayerModel());
- architecture.RegisterUtility(new global::TestApp.AudioUtility());
- }
- }
-
- """;
-
- await GeneratorTest.RunAsync(
- source,
- ("TestApp_GameplayModule.AutoRegisterModule.g.cs", expected));
+ return GeneratorTest.RunAsync(
+ AttributeOrderSource,
+ ("TestApp_GameplayModule.AutoRegisterModule.g.cs", AttributeOrderExpected));
}
///
@@ -115,140 +329,20 @@ public class AutoRegisterModuleGeneratorTests
[Test]
public async Task Generates_Module_Install_Method_In_Deterministic_Order_Across_Partial_Declarations()
{
- const string commonSource = """
- using System;
-
- namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
- {
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
- public sealed class AutoRegisterModuleAttribute : Attribute { }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterModelAttribute : Attribute
- {
- public RegisterModelAttribute(Type modelType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterSystemAttribute : Attribute
- {
- public RegisterSystemAttribute(Type systemType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterUtilityAttribute : Attribute
- {
- public RegisterUtilityAttribute(Type utilityType) { }
- }
- }
-
- namespace GFramework.Core.Abstractions.Architectures
- {
- public interface IArchitecture
- {
- T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
- T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
- T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
- }
- }
-
- namespace GFramework.Core.Abstractions.Model
- {
- public interface IModel { }
- }
-
- namespace GFramework.Core.Abstractions.Systems
- {
- public interface ISystem { }
- }
-
- namespace GFramework.Core.Abstractions.Utility
- {
- public interface IUtility { }
- }
-
- namespace TestApp
- {
- using GFramework.Core.Abstractions.Model;
- using GFramework.Core.Abstractions.Systems;
- using GFramework.Core.Abstractions.Utility;
-
- public sealed class PlayerModel : IModel { }
- public sealed class CombatSystem : ISystem { }
- public sealed class AudioUtility : IUtility { }
- }
- """;
-
- const string partASource = """
- namespace TestApp
- {
- 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.
- // 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.Core.SourceGenerators.Abstractions.Architectures;
-
- [RegisterSystem(typeof(CombatSystem))]
- [RegisterModel(typeof(PlayerModel))]
- public partial class GameplayModule
- {
- }
- }
- """;
-
- const string expected = """
- //
- #nullable enable
-
- namespace TestApp;
-
- partial class GameplayModule
- {
- public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
- {
- architecture.RegisterUtility(new global::TestApp.AudioUtility());
- architecture.RegisterSystem(new global::TestApp.CombatSystem());
- architecture.RegisterModel(new global::TestApp.PlayerModel());
- }
- }
-
- """;
-
var test = new CSharpSourceGeneratorTest
{
TestState =
{
Sources =
{
- ("Common.cs", commonSource),
- ("GameplayModule.PartA.cs", partASource),
- ("GameplayModule.PartB.cs", partBSource)
+ ("Common.cs", DeterministicOrderCommonSource),
+ ("GameplayModule.PartA.cs", DeterministicOrderPartASource),
+ ("GameplayModule.PartB.cs", DeterministicOrderPartBSource)
},
GeneratedSources =
{
(typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs",
- NormalizeLineEndings(expected))
+ NormalizeLineEndings(DeterministicOrderExpected))
}
},
DisabledDiagnostics = { "GF_Common_Trace_001" }
@@ -261,102 +355,11 @@ public class AutoRegisterModuleGeneratorTests
/// 验证生成器会保留可空引用、notnull 与 unmanaged 约束。
///
[Test]
- public async Task Generates_Type_Constraints_For_NullableReference_NotNull_And_Unmanaged()
+ public Task Generates_Type_Constraints_For_NullableReference_NotNull_And_Unmanaged()
{
- const string source = """
- #nullable enable
- using System;
- using GFramework.Core.SourceGenerators.Abstractions.Architectures;
-
- namespace GFramework.Core.SourceGenerators.Abstractions.Architectures
- {
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
- public sealed class AutoRegisterModuleAttribute : Attribute { }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterModelAttribute : Attribute
- {
- public RegisterModelAttribute(Type modelType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterSystemAttribute : Attribute
- {
- public RegisterSystemAttribute(Type systemType) { }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
- public sealed class RegisterUtilityAttribute : Attribute
- {
- public RegisterUtilityAttribute(Type utilityType) { }
- }
- }
-
- namespace GFramework.Core.Abstractions.Architectures
- {
- public interface IArchitecture
- {
- T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel;
- T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
- T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
- }
- }
-
- namespace GFramework.Core.Abstractions.Model
- {
- public interface IModel { }
- }
-
- namespace GFramework.Core.Abstractions.Systems
- {
- public interface ISystem { }
- }
-
- namespace GFramework.Core.Abstractions.Utility
- {
- public interface IUtility { }
- }
-
- namespace TestApp
- {
- using GFramework.Core.Abstractions.Model;
- using GFramework.Core.SourceGenerators.Abstractions.Architectures;
-
- public sealed class PlayerModel : IModel { }
-
- [AutoRegisterModule]
- [RegisterModel(typeof(PlayerModel))]
- public partial class GameplayModule
- where TNullableRef : class?
- where TNotNull : notnull
- where TUnmanaged : unmanaged
- {
- }
- }
- """;
-
- const string expected = """
- //
- #nullable enable
-
- namespace TestApp;
-
- partial class GameplayModule
- where TNullableRef : class?
- where TNotNull : notnull
- where TUnmanaged : unmanaged
- {
- public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
- {
- architecture.RegisterModel(new global::TestApp.PlayerModel());
- }
- }
-
- """;
-
- await GeneratorTest.RunAsync(
- source,
- ("TestApp_GameplayModule.AutoRegisterModule.g.cs", expected));
+ return GeneratorTest.RunAsync(
+ TypeConstraintSource,
+ ("TestApp_GameplayModule.AutoRegisterModule.g.cs", TypeConstraintExpected));
}
///
diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
index 74e10eb3..0f4721ad 100644
--- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
+++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
@@ -7,8 +7,8 @@
## 当前恢复点
-- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-031`
-- 当前阶段:`Phase 31`
+- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-032`
+- 当前阶段:`Phase 32`
- 当前焦点:
- 已完成 `GFramework.Core` 当前 `MA0016` / `MA0002` / `MA0015` / `MA0077` 低风险收口批次
- 已复核 `net10.0` 下的 `MA0158` 基线:`GFramework.Core` / `GFramework.Cqrs` 当前共有 `16` 个 object lock
@@ -57,10 +57,14 @@
场景已收敛为模板化 helper,保留原有快照目录与生成器输入语义不变
- 当前 `GFramework.SourceGenerators.Tests` Release build 基线已从 `49` 条降到 `43` 条;`LoggerGeneratorSnapshotTests.cs`
已不再出现在 `MA0051` 列表中
+ - 已完成 `GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs` 的 `MA0051` 收口:
+ 将内联测试源码与期望快照抽到类级常量、补齐测试类 XML 文档,并将仅作转发的异步测试改为直接返回 `Task`
+ - 当前 `GFramework.SourceGenerators.Tests` Release build 基线已从 `43` 条降到 `40` 条;
+ `AutoRegisterModuleGeneratorTests.cs` 已不再出现在 `MA0051` 列表中
- `GFramework.Godot` 的 `Timing.cs` 已同步适配新事件签名,但当前 worktree 的 Godot restore 资产仍受 Windows fallback package folder 干扰,独立 build 需在修复资产后补跑
- 后续继续按 warning 类型和数量批处理,而不是回退到按单文件切片推进
- 下一轮默认继续拆分 `GFramework.SourceGenerators.Tests` 的 `MA0051` 热点,优先处理
- `AutoRegisterModuleGeneratorTests`、`GeneratorSnapshotTest` 或 `ContextGetGeneratorTests`
+ `GeneratorSnapshotTest` 或 `ContextGetGeneratorTests`
- 单次 `boot` 的工作树改动上限控制在约 `100` 个文件以内,避免 recovery context 与 review 面同时失控
- 若任务边界互不冲突,允许使用不同模型的 subagent 并行处理不同 warning 类型或不同目录,但必须遵守显式 ownership
@@ -98,6 +102,8 @@
全部收敛为 `MA0051`
- 已完成 `LoggerGeneratorSnapshotTests` 的单文件 `MA0051` 收口;当前 `GFramework.SourceGenerators.Tests` Release build 基线已降到
`43` 条,并通过 focused snapshot tests 保持行为不变
+- 已完成 `AutoRegisterModuleGeneratorTests` 的单文件 `MA0051` 收口;当前 `GFramework.SourceGenerators.Tests` Release build 基线已降到
+ `40` 条,并通过 focused generator tests 保持输出契约不变
## 当前活跃事实
@@ -138,6 +144,8 @@
通过 schema 类型比较 helper 与显式 `StringComparison.Ordinal` 清空当前项目的 `MA0006`
- `RP-020` 继续拆分 `SchemaConfigGenerator.cs` 的 `MA0051` 热点,将当前项目 warnings-only 基线从 `19` 条降到 `9` 条,
并用 focused schema generator tests 验证 50 个用例通过
+- `RP-032` 已完成 `AutoRegisterModuleGeneratorTests` 的 3 个 `MA0051` 收口:通过提取类级常量承载测试源码与快照,保持
+ 生成文件名、断言路径与源生成输出不变;`GFramework.SourceGenerators.Tests` warnings-only 基线由 `43` 降至 `40`
- `RP-021` 使用 `$gframework-pr-review` 复核当前分支 PR #269 后,修复仍在本地成立的 4 个项:将
`CqrsHandlerRegistryGenerator` 拆分为职责清晰的 partial 文件、为 `ContextAwareGenerator` 生成字段增加稳定前缀并补上
`SetContextProvider` 的运行时 null 校验、为 `Option` 补齐 ``,并新增字段重名场景的生成器快照测试
diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
index b5c9fdde..d2b8a5d5 100644
--- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
+++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
@@ -1,5 +1,34 @@
# Analyzer Warning Reduction 追踪
+## 2026-04-23 — RP-032
+
+### 阶段:`AutoRegisterModuleGeneratorTests.cs` `MA0051` 收口(RP-032)
+
+- 启动复核:
+ - 按 `gframework-boot` 流程恢复当前 worktree,读取 `AGENTS.md`、`.ai/environment/tools.ai.yaml`、
+ `ai-plan/public/README.md` 与 active topic 跟踪文件,确认当前分支 `fix/analyzer-warning-reduction-batch`
+ 仍映射到 `analyzer-warning-reduction`
+ - 先用
+ `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release -t:Rebuild --no-restore --disable-build-servers -m:1 -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"`
+ 复核当前 `MA0051` 热点,确认 `AutoRegisterModuleGeneratorTests.cs` 仍有 `3` 个超长方法,适合作为单文件低风险写集
+- 决策:
+ - 保持 `AutoRegisterModuleGeneratorTests` 的测试输入、生成文件名、快照文本与断言结构不变,只收敛方法长度
+ - 采用“提取类级常量承载大段测试源码与期望输出”的方式,避免引入新的共享 helper 或改变场景组装顺序
+ - 验证阶段改为串行执行 build/test;避免和同项目并行运行时拿到不完整 `bin/Release` 输出
+- 实施调整:
+ - 为 `AutoRegisterModuleGeneratorTests` 补齐测试类 XML 文档
+ - 将 3 个长测试方法中的源码与期望快照提取为类级 `const string`,保留原有生成文件名与断言目标
+ - 将仅转发 `GeneratorTest.RunAsync(...)` 的两个异步测试改为直接返回 `Task`
+- 验证结果:
+ - `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release -t:Rebuild --no-restore --disable-build-servers -m:1 -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"`
+ - 结果:`40 Warning(s)`,`0 Error(s)`;`AutoRegisterModuleGeneratorTests.cs` 已不再出现在 `MA0051` 列表中
+ - `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --disable-build-servers --filter FullyQualifiedName~AutoRegisterModuleGeneratorTests -m:1 -p:RestoreFallbackFolders="" -nologo`
+ - 结果:`3 Passed`,`0 Failed`
+- 下一步建议:
+ - 若继续压缩 `GFramework.SourceGenerators.Tests` 的 `MA0051`,优先处理仅剩单个超长方法的
+ `GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs`
+ - 若希望单次继续多降几条 warning,则改选 `ContextGetGeneratorTests.cs`,但需要接受更大的单文件写集
+
## 2026-04-23 — RP-031
### 阶段:`LoggerGeneratorSnapshotTests.cs` `MA0051` 收口(RP-031)