From d0e86933cfb6261be746371cffc5fa806019fa47 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:22:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(sourcegenerators-tests):=20=E6=B8=85?= =?UTF-8?q?=E7=90=86=E4=BD=8E=E9=A3=8E=E9=99=A9=20warning=20=E5=9F=BA?= =?UTF-8?q?=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 GFramework.SourceGenerators.Tests 中低风险的 MA0004 与 MA0048,统一改为直接返回 Task 或在文件 I/O 上显式使用 ConfigureAwait(false) - 更新 AnalyzerTestDriver 文件名与类型名对齐,避免测试基础设施继续产生文件命名 warning - 更新 analyzer-warning-reduction 的 active tracking 与 trace,记录 RP-030 的 61 到 49 warnings-only 基线变化和验证结果 --- .../Config/SchemaConfigGeneratorEnumTests.cs | 16 ++++---- .../SchemaConfigGeneratorSnapshotTests.cs | 41 +++++++++++++++---- ...{AnalyzerTest.cs => AnalyzerTestDriver.cs} | 4 +- .../Core/GeneratorSnapshotTest.cs | 4 +- .../GeneratorSnapshotTestSecurityTests.cs | 8 ++-- .../Core/GeneratorTest.cs | 8 ++-- .../analyzer-warning-reduction-tracking.md | 38 +++++++++++------ .../analyzer-warning-reduction-trace.md | 37 +++++++++++++++++ 8 files changed, 115 insertions(+), 41 deletions(-) rename GFramework.SourceGenerators.Tests/Core/{AnalyzerTest.cs => AnalyzerTestDriver.cs} (93%) diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorEnumTests.cs b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorEnumTests.cs index 801a343c..7b123753 100644 --- a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorEnumTests.cs +++ b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorEnumTests.cs @@ -13,7 +13,7 @@ public class SchemaConfigGeneratorEnumTests /// 验证对象 enum 文档输出与快照保持一致。 /// [Test] - public async Task Snapshot_Should_Preserve_Object_Enum_Documentation() + public Task Snapshot_Should_Preserve_Object_Enum_Documentation() { const string source = """ namespace TestApp @@ -51,14 +51,14 @@ public class SchemaConfigGeneratorEnumTests ("monster.schema.json", schema)); Assert.That(result.Results.Single().Diagnostics, Is.Empty); - await AssertSnapshotAsync(result, "MonsterConfig.ObjectEnum.g.txt"); + return AssertSnapshotAsync(result, "MonsterConfig.ObjectEnum.g.txt"); } /// /// 验证数组项 enum 文档回退输出与快照保持一致。 /// [Test] - public async Task Snapshot_Should_Preserve_Array_Item_Enum_Documentation_Fallback() + public Task Snapshot_Should_Preserve_Array_Item_Enum_Documentation_Fallback() { const string source = """ namespace TestApp @@ -88,14 +88,14 @@ public class SchemaConfigGeneratorEnumTests ("monster.schema.json", schema)); Assert.That(result.Results.Single().Diagnostics, Is.Empty); - await AssertSnapshotAsync(result, "MonsterConfig.ArrayItemEnum.g.txt"); + return AssertSnapshotAsync(result, "MonsterConfig.ArrayItemEnum.g.txt"); } /// /// 验证对象数组项 enum 文档回退输出与快照保持一致。 /// [Test] - public async Task Snapshot_Should_Preserve_Array_Object_Item_Enum_Documentation_Fallback() + public Task Snapshot_Should_Preserve_Array_Object_Item_Enum_Documentation_Fallback() { const string source = """ namespace TestApp @@ -136,7 +136,7 @@ public class SchemaConfigGeneratorEnumTests ("monster.schema.json", schema)); Assert.That(result.Results.Single().Diagnostics, Is.Empty); - await AssertSnapshotAsync(result, "MonsterConfig.ArrayObjectItemEnum.g.txt"); + return AssertSnapshotAsync(result, "MonsterConfig.ArrayObjectItemEnum.g.txt"); } /// @@ -176,11 +176,11 @@ public class SchemaConfigGeneratorEnumTests if (!File.Exists(path)) { Directory.CreateDirectory(snapshotFolder); - await File.WriteAllTextAsync(path, actual); + await File.WriteAllTextAsync(path, actual).ConfigureAwait(false); Assert.Fail($"Snapshot not found. Generated new snapshot at:\n{path}"); } - var expected = await File.ReadAllTextAsync(path); + var expected = await File.ReadAllTextAsync(path).ConfigureAwait(false); Assert.That( Normalize(expected), Is.EqualTo(Normalize(actual)), diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs index 71c0065c..2d5cce4a 100644 --- a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs @@ -12,7 +12,7 @@ public class SchemaConfigGeneratorSnapshotTests /// 验证一个最小 monster schema 能生成配置类型、表包装和注册辅助。 /// [Test] - public async Task Snapshot_SchemaConfigGenerator() + public Task Snapshot_SchemaConfigGenerator() { const string source = """ using System; @@ -183,12 +183,7 @@ public class SchemaConfigGeneratorSnapshotTests "SchemaConfigGenerator"); snapshotFolder = Path.GetFullPath(snapshotFolder); - await AssertSnapshotAsync(generatedSources, snapshotFolder, "MonsterConfig.g.cs", "MonsterConfig.g.txt"); - await AssertSnapshotAsync(generatedSources, snapshotFolder, "MonsterTable.g.cs", "MonsterTable.g.txt"); - await AssertSnapshotAsync(generatedSources, snapshotFolder, "MonsterConfigBindings.g.cs", - "MonsterConfigBindings.g.txt"); - await AssertSnapshotAsync(generatedSources, snapshotFolder, "GeneratedConfigCatalog.g.cs", - "GeneratedConfigCatalog.g.txt"); + return AssertAllSnapshotsAsync(generatedSources, snapshotFolder); } /// @@ -213,17 +208,45 @@ public class SchemaConfigGeneratorSnapshotTests if (!File.Exists(path)) { Directory.CreateDirectory(snapshotFolder); - await File.WriteAllTextAsync(path, actual); + await File.WriteAllTextAsync(path, actual).ConfigureAwait(false); Assert.Fail($"Snapshot not found. Generated new snapshot at:\n{path}"); } - var expected = await File.ReadAllTextAsync(path); + var expected = await File.ReadAllTextAsync(path).ConfigureAwait(false); Assert.That( Normalize(expected), Is.EqualTo(Normalize(actual)), $"Snapshot mismatch: {generatedFileName}"); } + /// + /// 依次验证 schema 生成器产出的全部核心快照文件。 + /// + /// 生成结果字典。 + /// 快照目录。 + /// 全部快照断言完成后的异步任务。 + private static async Task AssertAllSnapshotsAsync( + IReadOnlyDictionary generatedSources, + string snapshotFolder) + { + await AssertSnapshotAsync(generatedSources, snapshotFolder, "MonsterConfig.g.cs", "MonsterConfig.g.txt") + .ConfigureAwait(false); + await AssertSnapshotAsync(generatedSources, snapshotFolder, "MonsterTable.g.cs", "MonsterTable.g.txt") + .ConfigureAwait(false); + await AssertSnapshotAsync( + generatedSources, + snapshotFolder, + "MonsterConfigBindings.g.cs", + "MonsterConfigBindings.g.txt") + .ConfigureAwait(false); + await AssertSnapshotAsync( + generatedSources, + snapshotFolder, + "GeneratedConfigCatalog.g.cs", + "GeneratedConfigCatalog.g.txt") + .ConfigureAwait(false); + } + /// /// 标准化快照文本以避免平台换行差异。 /// diff --git a/GFramework.SourceGenerators.Tests/Core/AnalyzerTest.cs b/GFramework.SourceGenerators.Tests/Core/AnalyzerTestDriver.cs similarity index 93% rename from GFramework.SourceGenerators.Tests/Core/AnalyzerTest.cs rename to GFramework.SourceGenerators.Tests/Core/AnalyzerTestDriver.cs index 9d9a0b73..b2f962d0 100644 --- a/GFramework.SourceGenerators.Tests/Core/AnalyzerTest.cs +++ b/GFramework.SourceGenerators.Tests/Core/AnalyzerTestDriver.cs @@ -15,7 +15,7 @@ public static class AnalyzerTestDriver /// 测试输入源码。 /// 期望诊断集合。 /// 异步测试任务。 - public static async Task RunAsync( + public static Task RunAsync( string source, params DiagnosticResult[] diagnostics) { @@ -29,6 +29,6 @@ public static class AnalyzerTestDriver }; test.ExpectedDiagnostics.AddRange(diagnostics); - await test.RunAsync(); + return test.RunAsync(); } } diff --git a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs index fe8b9bff..9587440b 100644 --- a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs +++ b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTest.cs @@ -83,13 +83,13 @@ public static class GeneratorSnapshotTest { // 第一次运行:生成 snapshot Directory.CreateDirectory(Path.GetDirectoryName(path)!); - await File.WriteAllTextAsync(path, content.ToString()); + await File.WriteAllTextAsync(path, content.ToString()).ConfigureAwait(false); Assert.Fail( $"未找到快照文件,已在以下路径生成新快照:\n{path}"); } - var expected = await File.ReadAllTextAsync(path); + var expected = await File.ReadAllTextAsync(path).ConfigureAwait(false); Assert.That( Normalize(expected), diff --git a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTestSecurityTests.cs b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTestSecurityTests.cs index b52fa027..d096a059 100644 --- a/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTestSecurityTests.cs +++ b/GFramework.SourceGenerators.Tests/Core/GeneratorSnapshotTestSecurityTests.cs @@ -20,8 +20,8 @@ public class GeneratorSnapshotTestSecurityTests var snapshotRoot = CreateSnapshotRoot(); var source = BuildSource(); - Assert.ThrowsAsync(async () => - await GeneratorSnapshotTest.RunAsync( + Assert.ThrowsAsync(() => + GeneratorSnapshotTest.RunAsync( source, snapshotRoot, _ => Path.Combine(snapshotRoot, "Status.EnumExtensions.g.cs"))); @@ -36,8 +36,8 @@ public class GeneratorSnapshotTestSecurityTests var snapshotRoot = CreateSnapshotRoot(); var source = BuildSource(); - Assert.ThrowsAsync(async () => - await GeneratorSnapshotTest.RunAsync( + Assert.ThrowsAsync(() => + GeneratorSnapshotTest.RunAsync( source, snapshotRoot, _ => Path.Combine("..", "escaped", "Status.EnumExtensions.g.cs"))); diff --git a/GFramework.SourceGenerators.Tests/Core/GeneratorTest.cs b/GFramework.SourceGenerators.Tests/Core/GeneratorTest.cs index bed493e7..e582fbd9 100644 --- a/GFramework.SourceGenerators.Tests/Core/GeneratorTest.cs +++ b/GFramework.SourceGenerators.Tests/Core/GeneratorTest.cs @@ -13,11 +13,11 @@ public static class GeneratorTest /// 输入的源代码 /// 期望生成的源文件集合,包含文件名和内容的元组 /// 异步操作任务 - public static async Task RunAsync( + public static Task RunAsync( string source, params (string filename, string content)[] generatedSources) { - await RunAsync( + return RunAsync( source, additionalReferences: [], generatedSources); @@ -30,7 +30,7 @@ public static class GeneratorTest /// 附加元数据引用,用于构造多程序集场景。 /// 期望生成的源文件集合,包含文件名和内容的元组。 /// 异步操作任务。 - public static async Task RunAsync( + public static Task RunAsync( string source, IEnumerable additionalReferences, params (string filename, string content)[] generatedSources) @@ -52,7 +52,7 @@ public static class GeneratorTest foreach (var additionalReference in additionalReferences) test.TestState.AdditionalReferences.Add(additionalReference); - await test.RunAsync(); + return test.RunAsync(); } /// 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 a4dfd97f..bf1ce29b 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-029` -- 当前阶段:`Phase 29` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-030` +- 当前阶段:`Phase 30` - 当前焦点: - 已完成 `GFramework.Core` 当前 `MA0016` / `MA0002` / `MA0015` / `MA0077` 低风险收口批次 - 已复核 `net10.0` 下的 `MA0158` 基线:`GFramework.Core` / `GFramework.Cqrs` 当前共有 `16` 个 object lock @@ -50,9 +50,12 @@ - 当前 `GFramework.Core.SourceGenerators` warnings-only 基线已降到 `0` 条 - 当前 `GFramework.Cqrs.SourceGenerators` warnings-only 基线已降到 `0` 条 - 当前 `GFramework.Game.SourceGenerators` warnings-only 基线已从 `46` 条降到 `0` 条 + - 已完成 `GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口:测试辅助器改为直接返回 `Task`, + 文件 I/O 显式补齐 `ConfigureAwait(false)`,`AnalyzerTestDriver` 文件名与类型名重新对齐 + - 当前 `GFramework.SourceGenerators.Tests` warnings-only 基线已从 `61` 条降到 `49` 条,剩余 warning 均为 `MA0051` - `GFramework.Godot` 的 `Timing.cs` 已同步适配新事件签名,但当前 worktree 的 Godot restore 资产仍受 Windows fallback package folder 干扰,独立 build 需在修复资产后补跑 - 后续继续按 warning 类型和数量批处理,而不是回退到按单文件切片推进 - - 下一轮默认继续拆分 `GFramework.Game.SourceGenerators` 的 `MA0051` 热点,或评估跨 target 的 `MA0158` + - 下一轮默认继续拆分 `GFramework.SourceGenerators.Tests` 的 `MA0051` 热点,或评估跨 target 的 `MA0158` 锁替换风险 - 单次 `boot` 的工作树改动上限控制在约 `100` 个文件以内,避免 recovery context 与 review 面同时失控 - 若任务边界互不冲突,允许使用不同模型的 subagent 并行处理不同 warning 类型或不同目录,但必须遵守显式 ownership @@ -87,6 +90,8 @@ - 已完成当前分支与 `main` 的 `CqrsHandlerRegistryGenerator.cs` 冲突化解:保留当前 partial 结构,并把 `main` 侧新增的模型文档合并到 `CqrsHandlerRegistryGenerator.Models.cs` - 已完成 `GFramework.Game.SourceGenerators` 中 `SchemaConfigGenerator` 的剩余 `MA0051` 收口;warnings-only 基线已降到 `0` 条 +- 已完成 `GFramework.SourceGenerators.Tests` 的首轮低风险 warning 清理;当前项目已清空 `MA0004` / `MA0048`,剩余 warning + 全部收敛为 `MA0051` ## 当前活跃事实 @@ -144,6 +149,9 @@ 并把“变更模块必须运行对应 build 且处理 warning”的治理规则写回 `AGENTS.md` - `RP-029` 已完成 `SchemaConfigGenerator` 剩余 `MA0051` 收口:`GFramework.Game.SourceGenerators` 独立 Release warnings-only build 已清零,并通过 `SchemaConfigGenerator` focused generator tests 锁定生成输出未回退 +- `RP-030` 已完成 `GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口:`AnalyzerTestDriver` 文件名已与 + 类型名一致,测试辅助器与 schema snapshot 断言路径已改为直接返回 `Task` 或显式使用 `ConfigureAwait(false)`; + 当前测试项目 warnings-only 基线从 `61` 条降到 `49` 条,剩余均为 `MA0051` - 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射 ## 当前风险 @@ -156,13 +164,12 @@ - 缓解措施:继续以唯一源位置和 warning 家族为主要决策依据,而不是只看原始 warning 总数 - net10 专属 warning 风险:`MA0158` 建议使用 `System.Threading.Lock`,但项目多 target 时需要确认兼容边界 - 缓解措施:下一轮先按 target framework 与 API 可用性评估,不直接批量替换共享源码中的 `object` lock -- source generator warning 外溢风险:运行 `GFramework.SourceGenerators.Tests` 会构建相邻 generator/test 项目并显示既有 - `GFramework.Game.SourceGenerators` 与测试项目 warning - - 缓解措施:继续以被修改 generator 项目的独立 warnings-only build 作为主验收,并用 focused generator test 验证行为 -- source generator test warning 治理风险:`GFramework.SourceGenerators.Tests` 当前仍有既有 `MA0051` / `MA0004` / `MA0048` - warning,本轮 focused test 已通过,但测试项目整包 warning 尚未进入本轮写集 - - 缓解措施:本轮已在 failed-test follow-up 的定向 `dotnet test` 中再次确认这些 warning 仍为既有基线;后续若继续修改该测试项目, - 应按新增 `AGENTS.md` 规则先明确 warning 收口范围,再决定是否进入专门清理切片 +- source generator warning 外溢风险:运行 `GFramework.SourceGenerators.Tests` 会构建相邻 generator/test 项目,并在输出中混入 + 测试项目自身的结构性 warning 基线 + - 缓解措施:继续以被修改项目的独立 warnings-only build 作为主验收,并用 focused generator test 验证行为 +- source generator test warning 治理风险:`GFramework.SourceGenerators.Tests` 当前仍有 `49` 条既有 `MA0051` warning; + 一旦继续进入该写集,就必须把测试项目 warning 一并纳入本轮完成条件 + - 缓解措施:已先清空低风险 `MA0004` / `MA0048`,后续继续保持“单 warning family、单测试域”的节奏推进 `MA0051` - ContextAware 基类命名隐藏风险:若生成器只看当前类型声明成员,派生规则会重新占用基类已声明的 `_gFrameworkContextAware*` 字段名,导致生成成员隐藏继承状态并让快照无法锁定后缀分配行为 - 缓解措施:本轮已改为遍历完整 base-type 链收集保留名,并用 inherited collision 快照用例锁定该行为 @@ -325,13 +332,20 @@ - 结果:`54 Passed`,`0 Failed` - 说明:测试项目构建仍显示既有 `GFramework.SourceGenerators.Tests` `MA0048` / `MA0051` / `MA0004` warning;不属于本轮 `GFramework.Game.SourceGenerators` 写集 +- `RP-030` 的验证结果: + - `dotnet restore GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -p:RestoreFallbackFolders="" -nologo` + - 结果:通过;刷新 Linux 侧 restore 资产以移除 Windows fallback package folder 干扰 + - `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"` + - 结果:`49 Warning(s)`,`0 Error(s)`;当前项目已不再出现 `MA0004` / `MA0048`,剩余 warning 全部为 `MA0051` + - `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~GeneratorSnapshotTestSecurityTests|FullyQualifiedName~SchemaConfigGeneratorSnapshotTests|FullyQualifiedName~SchemaConfigGeneratorEnumTests" -m:1 -p:RestoreFallbackFolders="" -nologo` + - 结果:`6 Passed`,`0 Failed` - active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史 ## 下一步 1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录 -2. 下一轮优先评估是否将 `GFramework.SourceGenerators.Tests` 的既有 `MA0051` / `MA0004` / `MA0048` 作为独立 warning - 清理切片;若进入该写集,需要先明确测试项目 warning 也属于本轮必须处理的模块范围 +2. 下一轮优先继续 `GFramework.SourceGenerators.Tests` 的 `MA0051` 收口,先在单一测试域内选择一个文件或一组同构 snapshot + 用例拆分,不再把已清零的 `MA0004` / `MA0048` 混回写集 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 c789f477..fae414cf 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,42 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-23 — RP-030 + +### 阶段:`GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口(RP-030) + +- 启动复核: + - 按 `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` + - 先对 `GFramework.SourceGenerators.Tests` 执行 + `dotnet restore GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -p:RestoreFallbackFolders="" -nologo`, + 刷新 Linux 侧 restore 资产,规避 Windows fallback package folder 干扰 + - 用 + `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"` + 复核当前基线,确认该测试项目共有 `61` 条 warning,其中低风险切片集中在 `MA0004` 与单个 `MA0048` +- 决策: + - 不直接进入大型 snapshot/test 方法的 `MA0051`,先收口纯 test-infrastructure 层的 `MA0004` / `MA0048` + - 对“只是转发异步调用”的 helper 直接返回 `Task`,只在真实文件 I/O 上显式补 `ConfigureAwait(false)`,避免无意义的 + `async/await` 包装 + - 将 `AnalyzerTestDriver` 所在文件改名为与类型一致,单独清理 `MA0048`,不改类型名与调用方契约 +- 实施调整: + - 将 `AnalyzerTestDriver.RunAsync(...)` 与 `GeneratorTest.RunAsync(...)` 改为直接返回下游 `Task` + - 为 `GeneratorSnapshotTest`、`SchemaConfigGeneratorSnapshotTests` 与 `SchemaConfigGeneratorEnumTests` 中的异步文件读写 + 显式补齐 `ConfigureAwait(false)`,并把仅作转发的测试方法改为直接返回 `Task` + - 将 `GeneratorSnapshotTestSecurityTests` 的 `Assert.ThrowsAsync(...)` 改为直接返回目标 `Task`,移除无收益的 + `async` 包装 + - 将 `GFramework.SourceGenerators.Tests/Core/AnalyzerTest.cs` 重命名为 + `GFramework.SourceGenerators.Tests/Core/AnalyzerTestDriver.cs` +- 验证结果: + - `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"` + - 结果:`49 Warning(s)`,`0 Error(s)`;当前项目已不再出现 `MA0004` / `MA0048`,剩余 warning 全部为 `MA0051` + - `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~GeneratorSnapshotTestSecurityTests|FullyQualifiedName~SchemaConfigGeneratorSnapshotTests|FullyQualifiedName~SchemaConfigGeneratorEnumTests" -m:1 -p:RestoreFallbackFolders="" -nologo` + - 结果:`6 Passed`,`0 Failed` +- 下一步建议: + - 若继续 analyzer warning reduction,继续把 `GFramework.SourceGenerators.Tests` 作为独立写集,只处理 `MA0051` + - 下一轮优先选择单一测试域的同构长方法,例如 `LoggerGeneratorSnapshotTests`、`AutoRegisterModuleGeneratorTests` + 或共享 helper `GeneratorSnapshotTest` + ## 2026-04-23 — RP-029 ### 阶段:`SchemaConfigGenerator.cs` 剩余 `MA0051` 收口(RP-029)