From 8975ef1a208b45d274a5f9792daf02c4f48a05ba Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 23 Apr 2026 20:03:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(sourcegenerators-tests):=20=E6=94=B6?= =?UTF-8?q?=E6=95=9B=20Cqrs=20=E6=B3=A8=E5=86=8C=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=A6=96=E4=B8=AA=E9=95=BF=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 CqrsHandlerRegistryGeneratorTests 首个程序集级注册场景的共享 fixture,清理当前 MA0051 位点 - 更新 analyzer-warning-reduction 的 tracking 与 trace,记录 subagent 循环首个有效写集和基线降至 14 条 --- .../Cqrs/CqrsHandlerRegistryGeneratorTests.cs | 212 +++++++++--------- .../analyzer-warning-reduction-tracking.md | 22 +- .../analyzer-warning-reduction-trace.md | 28 +++ 3 files changed, 153 insertions(+), 109 deletions(-) diff --git a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs index cb4ceaa8..b8a1c307 100644 --- a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs @@ -330,119 +330,119 @@ public class CqrsHandlerRegistryGeneratorTests """; + private const string AssemblyLevelCqrsHandlerRegistrySource = """ + using System; + using System.Collections.Generic; + + namespace Microsoft.Extensions.DependencyInjection + { + public interface IServiceCollection { } + + public static class ServiceCollectionServiceExtensions + { + public static void AddTransient(IServiceCollection services, Type serviceType, Type implementationType) { } + } + } + + namespace GFramework.Core.Abstractions.Logging + { + public interface ILogger + { + void Debug(string msg); + } + } + + namespace GFramework.Cqrs.Abstractions.Cqrs + { + public interface IRequest { } + public interface INotification { } + public interface IStreamRequest { } + + public interface IRequestHandler where TRequest : IRequest { } + public interface INotificationHandler where TNotification : INotification { } + public interface IStreamRequestHandler where TRequest : IStreamRequest { } + } + + namespace GFramework.Cqrs + { + public interface ICqrsHandlerRegistry + { + void Register(Microsoft.Extensions.DependencyInjection.IServiceCollection services, GFramework.Core.Abstractions.Logging.ILogger logger); + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class CqrsHandlerRegistryAttribute : Attribute + { + public CqrsHandlerRegistryAttribute(Type registryType) { } + } + + [AttributeUsage(AttributeTargets.Assembly)] + public sealed class CqrsReflectionFallbackAttribute : Attribute + { + public CqrsReflectionFallbackAttribute(params string[] fallbackHandlerTypeNames) { } + } + } + + namespace TestApp + { + using GFramework.Cqrs.Abstractions.Cqrs; + + public sealed record PingQuery() : IRequest; + public sealed record DomainEvent() : INotification; + public sealed record NumberStream() : IStreamRequest; + + public sealed class ZetaNotificationHandler : INotificationHandler { } + public sealed class AlphaQueryHandler : IRequestHandler { } + public sealed class StreamHandler : IStreamRequestHandler { } + } + """; + + private const string AssemblyLevelCqrsHandlerRegistryExpected = """ + // + #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)); + + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler), + typeof(global::TestApp.AlphaQueryHandler)); + logger.Debug("Registered CQRS handler TestApp.AlphaQueryHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler), + typeof(global::TestApp.StreamHandler)); + logger.Debug("Registered CQRS handler TestApp.StreamHandler as GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler."); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + typeof(global::GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler), + typeof(global::TestApp.ZetaNotificationHandler)); + logger.Debug("Registered CQRS handler TestApp.ZetaNotificationHandler as GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler."); + } + } + + """; + /// /// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。 /// [Test] public async Task Generates_Assembly_Level_Cqrs_Handler_Registry() { - const string source = """ - using System; - using System.Collections.Generic; - - namespace Microsoft.Extensions.DependencyInjection - { - public interface IServiceCollection { } - - public static class ServiceCollectionServiceExtensions - { - public static void AddTransient(IServiceCollection services, Type serviceType, Type implementationType) { } - } - } - - namespace GFramework.Core.Abstractions.Logging - { - public interface ILogger - { - void Debug(string msg); - } - } - - namespace GFramework.Cqrs.Abstractions.Cqrs - { - public interface IRequest { } - public interface INotification { } - public interface IStreamRequest { } - - public interface IRequestHandler where TRequest : IRequest { } - public interface INotificationHandler where TNotification : INotification { } - public interface IStreamRequestHandler where TRequest : IStreamRequest { } - } - - namespace GFramework.Cqrs - { - public interface ICqrsHandlerRegistry - { - void Register(Microsoft.Extensions.DependencyInjection.IServiceCollection services, GFramework.Core.Abstractions.Logging.ILogger logger); - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class CqrsHandlerRegistryAttribute : Attribute - { - public CqrsHandlerRegistryAttribute(Type registryType) { } - } - - [AttributeUsage(AttributeTargets.Assembly)] - public sealed class CqrsReflectionFallbackAttribute : Attribute - { - public CqrsReflectionFallbackAttribute(params string[] fallbackHandlerTypeNames) { } - } - } - - namespace TestApp - { - using GFramework.Cqrs.Abstractions.Cqrs; - - public sealed record PingQuery() : IRequest; - public sealed record DomainEvent() : INotification; - public sealed record NumberStream() : IStreamRequest; - - public sealed class ZetaNotificationHandler : INotificationHandler { } - public sealed class AlphaQueryHandler : IRequestHandler { } - public sealed class StreamHandler : IStreamRequestHandler { } - } - """; - - const string expected = """ - // - #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)); - - global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( - services, - typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler), - typeof(global::TestApp.AlphaQueryHandler)); - logger.Debug("Registered CQRS handler TestApp.AlphaQueryHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); - global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( - services, - typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler), - typeof(global::TestApp.StreamHandler)); - logger.Debug("Registered CQRS handler TestApp.StreamHandler as GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler."); - global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( - services, - typeof(global::GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler), - typeof(global::TestApp.ZetaNotificationHandler)); - logger.Debug("Registered CQRS handler TestApp.ZetaNotificationHandler as GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler."); - } - } - - """; - await GeneratorTest.RunAsync( - source, - ("CqrsHandlerRegistry.g.cs", expected)); + AssemblyLevelCqrsHandlerRegistrySource, + ("CqrsHandlerRegistry.g.cs", AssemblyLevelCqrsHandlerRegistryExpected)); } /// 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 06034cb3..090d2fb5 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,9 +7,18 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-036` -- 当前阶段:`Phase 36` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-037` +- 当前阶段:`Phase 37` - 当前焦点: + - 已通过 subagent 循环的首个可交付切片完成 + `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` + `Generates_Assembly_Level_Cqrs_Handler_Registry()` 的 `MA0051` 收口: + 将内联 `source` / `expected` 文本提取为类级常量,保持生成文本、断言语义和文件名不变 + - 当前 `GFramework.SourceGenerators.Tests` Release warnings-only 基线已从 `15` 条降到 `14` 条; + 行号 `337` 已从 `MA0051` 输出中消失,剩余热点仍全部集中在 + `CqrsHandlerRegistryGeneratorTests.cs` + - 已确认当前分支相对 `origin/main` 的唯一变更文件数仍只有 `3`;按该统计口径距离用户要求的 + “接近 `75` 个文件变更”仍很远,需要继续多轮切片 - 已完成 `GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs` 的 `MA0051` 收口: 将共享 consumer runtime fixture 提取到类级常量,并把生成结果收集与 catalog 契约断言拆成小 helper, 保持 schema 文本、断言语义与生成输出契约不变 @@ -147,6 +156,8 @@ `SchemaConfigGeneratorTests` 两个测试写集 - 已完成 `RP-036`:清空 `SchemaConfigGeneratorTests.cs` 当前 `MA0051`,并将 `GFramework.SourceGenerators.Tests` Release warnings-only 基线进一步降到 `15` 条 +- 已完成 `RP-037` 的首个 subagent 接收:`CqrsHandlerRegistryGeneratorTests.cs` 的 + `Generates_Assembly_Level_Cqrs_Handler_Registry()` 已抽出类级 fixture,当前测试项目基线进一步降到 `14` 条 ## 当前活跃事实 @@ -197,6 +208,8 @@ - `RP-036` 已完成 `SchemaConfigGeneratorTests` 的单文件 `MA0051` 收口:共享 runtime fixture、 generated-source 收集与 catalog 契约断言均已拆出 helper;当前测试项目剩余 `MA0051` 已全部收敛到 `CqrsHandlerRegistryGeneratorTests` +- `RP-037` 已验证 subagent 循环开始产生稳定吞吐,但当前一轮只消掉 `1` 个 warning 位点; + 若继续按“唯一变更文件数接近 `75`”推进,需要接受很多轮单文件、单方法级切片 - `RP-021` 使用 `$gframework-pr-review` 复核当前分支 PR #269 后,修复仍在本地成立的 4 个项:将 `CqrsHandlerRegistryGenerator` 拆分为职责清晰的 partial 文件、为 `ContextAwareGenerator` 生成字段增加稳定前缀并补上 `SetContextProvider` 的运行时 null 校验、为 `Option` 补齐 ``,并新增字段重名场景的生成器快照测试 @@ -432,13 +445,16 @@ - 结果:`15 Warning(s)`,`0 Error(s)`;`SchemaConfigGeneratorTests.cs` 已不再出现在 `MA0051` 列表中 - `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-build --disable-build-servers --filter FullyQualifiedName~SchemaConfigGeneratorTests -m:1 -p:RestoreFallbackFolders="" -nologo` - 结果:`50 Passed`,`0 Failed` +- `RP-037` 的验证结果: + - `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"` + - 结果:`14 Warning(s)`,`0 Error(s)`;`CqrsHandlerRegistryGeneratorTests.cs` 的行号 `337` 已不再出现在 `MA0051` 列表中 - active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史 ## 下一步 1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录 2. 下一轮优先继续 `GFramework.SourceGenerators.Tests` 的 `MA0051` 收口,并直接进入唯一剩余热点 - `CqrsHandlerRegistryGeneratorTests.cs` + `CqrsHandlerRegistryGeneratorTests.cs`;优先把行号 `454`、`536`、`607`、`680` 对应的前半段长方法继续拆小 3. 若改回推进 `MA0158`,先设计 `net8.0` / `net9.0` / `net10.0` 多 target 条件编译方案,不直接批量替换共享源码中的 `object` lock 4. 若后续继续改动 `GFramework.Godot`,先修复该项目的 Linux 侧 restore 资产,再补跑独立 build 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 fd20b9a3..af9fd023 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,33 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-23 — RP-037 + +### 阶段:subagent 循环首个有效写集(RP-037) + +- 启动复核: + - 在用户明确要求“循环调用 subagent 执行 `$gframework-boot`”后,先后尝试了多个 worker 边界; + 前几轮 subagent 只完成 boot 与热点确认,没有形成可验证 patch + - 将 subagent 边界进一步压缩到单方法级别后,首个有效切片落在 + `CqrsHandlerRegistryGeneratorTests.cs` 的 `Generates_Assembly_Level_Cqrs_Handler_Registry()` +- 决策: + - 接受当前 subagent 的最小可验证产出,而不是继续等待单轮覆盖多个 warning 点 + - 继续用“boot -> 单方法/小批量方法 -> 验证 -> 主线程记录恢复点”的节奏推进,以换取稳定吞吐 +- 实施调整: + - 为 `Generates_Assembly_Level_Cqrs_Handler_Registry()` 提取 + `AssemblyLevelCqrsHandlerRegistrySource` 与 `AssemblyLevelCqrsHandlerRegistryExpected` + 类级常量 + - 测试方法改为直接复用上述 fixture 调用 `GeneratorTest.RunAsync(...)` + - 不改断言语义、生成文本、方法名或快照/文件名 +- 验证结果: + - `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"` + - 结果:`14 Warning(s)`,`0 Error(s)`;原先位于行号 `337` 的 `MA0051` 已消失 +- 当前结论: + - subagent 循环在该仓库里可以产生产出,但目前吞吐偏低;若目标是把分支唯一变更文件数推近 `75`, + 还需要很多轮独立切片 +- 下一步建议: + - 下一轮继续 `CqrsHandlerRegistryGeneratorTests.cs` 前半段方法,优先处理当前剩余的 + `454`、`536`、`607`、`680` + ## 2026-04-23 — RP-036 ### 阶段:`SchemaConfigGeneratorTests.cs` `MA0051` 收口(RP-036)