mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
refactor(sourcegenerators-tests): 收敛 Cqrs 注册测试首个长方法
- 重构 CqrsHandlerRegistryGeneratorTests 首个程序集级注册场景的共享 fixture,清理当前 MA0051 位点 - 更新 analyzer-warning-reduction 的 tracking 与 trace,记录 subagent 循环首个有效写集和基线降至 14 条
This commit is contained in:
parent
2915624e60
commit
8975ef1a20
@ -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<TResponse> { }
|
||||
public interface INotification { }
|
||||
public interface IStreamRequest<TResponse> { }
|
||||
|
||||
public interface IRequestHandler<in TRequest, TResponse> where TRequest : IRequest<TResponse> { }
|
||||
public interface INotificationHandler<in TNotification> where TNotification : INotification { }
|
||||
public interface IStreamRequestHandler<in TRequest, out TResponse> where TRequest : IStreamRequest<TResponse> { }
|
||||
}
|
||||
|
||||
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<string>;
|
||||
public sealed record DomainEvent() : INotification;
|
||||
public sealed record NumberStream() : IStreamRequest<int>;
|
||||
|
||||
public sealed class ZetaNotificationHandler : INotificationHandler<DomainEvent> { }
|
||||
public sealed class AlphaQueryHandler : IRequestHandler<PingQuery, string> { }
|
||||
public sealed class StreamHandler : IStreamRequestHandler<NumberStream, int> { }
|
||||
}
|
||||
""";
|
||||
|
||||
private const string AssemblyLevelCqrsHandlerRegistryExpected = """
|
||||
// <auto-generated />
|
||||
#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<global::TestApp.PingQuery, string>),
|
||||
typeof(global::TestApp.AlphaQueryHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.AlphaQueryHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<TestApp.PingQuery, string>.");
|
||||
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
|
||||
services,
|
||||
typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler<global::TestApp.NumberStream, int>),
|
||||
typeof(global::TestApp.StreamHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.StreamHandler as GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler<TestApp.NumberStream, int>.");
|
||||
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
|
||||
services,
|
||||
typeof(global::GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler<global::TestApp.DomainEvent>),
|
||||
typeof(global::TestApp.ZetaNotificationHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.ZetaNotificationHandler as GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler<TestApp.DomainEvent>.");
|
||||
}
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。
|
||||
/// </summary>
|
||||
[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<TResponse> { }
|
||||
public interface INotification { }
|
||||
public interface IStreamRequest<TResponse> { }
|
||||
|
||||
public interface IRequestHandler<in TRequest, TResponse> where TRequest : IRequest<TResponse> { }
|
||||
public interface INotificationHandler<in TNotification> where TNotification : INotification { }
|
||||
public interface IStreamRequestHandler<in TRequest, out TResponse> where TRequest : IStreamRequest<TResponse> { }
|
||||
}
|
||||
|
||||
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<string>;
|
||||
public sealed record DomainEvent() : INotification;
|
||||
public sealed record NumberStream() : IStreamRequest<int>;
|
||||
|
||||
public sealed class ZetaNotificationHandler : INotificationHandler<DomainEvent> { }
|
||||
public sealed class AlphaQueryHandler : IRequestHandler<PingQuery, string> { }
|
||||
public sealed class StreamHandler : IStreamRequestHandler<NumberStream, int> { }
|
||||
}
|
||||
""";
|
||||
|
||||
const string expected = """
|
||||
// <auto-generated />
|
||||
#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<global::TestApp.PingQuery, string>),
|
||||
typeof(global::TestApp.AlphaQueryHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.AlphaQueryHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<TestApp.PingQuery, string>.");
|
||||
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
|
||||
services,
|
||||
typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler<global::TestApp.NumberStream, int>),
|
||||
typeof(global::TestApp.StreamHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.StreamHandler as GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler<TestApp.NumberStream, int>.");
|
||||
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
|
||||
services,
|
||||
typeof(global::GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler<global::TestApp.DomainEvent>),
|
||||
typeof(global::TestApp.ZetaNotificationHandler));
|
||||
logger.Debug("Registered CQRS handler TestApp.ZetaNotificationHandler as GFramework.Cqrs.Abstractions.Cqrs.INotificationHandler<TestApp.DomainEvent>.");
|
||||
}
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
await GeneratorTest<CqrsHandlerRegistryGenerator>.RunAsync(
|
||||
source,
|
||||
("CqrsHandlerRegistry.g.cs", expected));
|
||||
AssemblyLevelCqrsHandlerRegistrySource,
|
||||
("CqrsHandlerRegistry.g.cs", AssemblyLevelCqrsHandlerRegistryExpected));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -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<T>` 补齐 `<remarks>`,并新增字段重名场景的生成器快照测试
|
||||
@ -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
|
||||
|
||||
@ -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<CqrsHandlerRegistryGenerator>.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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user