From 2187f179c36d9befd0b617e4b957729c655171f1 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Fri, 24 Apr 2026 16:39:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(pr-review):=20=E4=BF=AE=E5=A4=8D=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=BF=AB=E7=85=A7=E6=AF=94=E8=BE=83=E5=99=A8=E5=A5=91?= =?UTF-8?q?=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 UnifiedSettingsFile 与 UnifiedSettingsDataRepository 的 comparer 契约,在无法恢复原比较器时显式回退到 StringComparer.Ordinal - 统一 AutoRegisterExportedCollectionsGeneratorTests 中剩余的 RunAsync 异步等待写法,并补齐 ConfigureAwait(false) - 更新 analyzer-warning-reduction 跟踪文档,记录 PR follow-up 的验证结果与恢复点 --- .../Data/UnifiedSettingsDataRepository.cs | 6 ++--- GFramework.Game/Data/UnifiedSettingsFile.cs | 6 ++++- ...gisterExportedCollectionsGeneratorTests.cs | 14 +++++----- .../analyzer-warning-reduction-tracking.md | 26 ++++++++++++------ .../analyzer-warning-reduction-trace.md | 27 +++++++++++++++++++ 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/GFramework.Game/Data/UnifiedSettingsDataRepository.cs b/GFramework.Game/Data/UnifiedSettingsDataRepository.cs index 7412c948..99672301 100644 --- a/GFramework.Game/Data/UnifiedSettingsDataRepository.cs +++ b/GFramework.Game/Data/UnifiedSettingsDataRepository.cs @@ -288,11 +288,11 @@ public class UnifiedSettingsDataRepository( { ArgumentNullException.ThrowIfNull(source); - // 反序列化后的运行时类型可能只是 IDictionary 实现;若底层仍是 Dictionary,则保留其 comparer, - // 否则退回到按当前内容复制,避免因为 API 抽象化而改变持久化前后的键比较语义。 + // 反序列化后的运行时类型可能只是 IDictionary 实现;若底层仍是 Dictionary,则保留其 comparer。 + // 若 comparer 已因接口抽象而不可恢复,则显式回退到 Ordinal,避免让默认 comparer 语义继续隐式存在。 var sections = source.Sections is Dictionary dictionary ? new Dictionary(dictionary, dictionary.Comparer) - : new Dictionary(source.Sections); + : new Dictionary(source.Sections, StringComparer.Ordinal); return new UnifiedSettingsFile { diff --git a/GFramework.Game/Data/UnifiedSettingsFile.cs b/GFramework.Game/Data/UnifiedSettingsFile.cs index 89e1425b..02fd66b6 100644 --- a/GFramework.Game/Data/UnifiedSettingsFile.cs +++ b/GFramework.Game/Data/UnifiedSettingsFile.cs @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Collections.Generic; using GFramework.Core.Abstractions.Versioning; @@ -28,8 +29,11 @@ internal sealed class UnifiedSettingsFile : IVersioned /// /// 这里公开为 而不是具体的 , /// 以避免暴露可替换的具体集合实现,同时继续兼容 Newtonsoft.Json 对字典对象的序列化与反序列化。 + /// 默认实例使用 ;若调用方提供其他实现,仓库在可以识别底层 + /// comparer 时会保留原语义,否则克隆快照时会显式回退到 + /// 。 /// - public IDictionary Sections { get; set; } = new Dictionary(); + public IDictionary Sections { get; set; } = new Dictionary(StringComparer.Ordinal); /// /// 配置文件版本号,用于版本控制和兼容性检查 diff --git a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs index d57a74c6..ded1bb0b 100644 --- a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs +++ b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs @@ -135,7 +135,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests .WithLocation(0) .WithArguments("Values")); - await test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } [Test] @@ -302,7 +302,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests .WithLocation(0) .WithArguments("Register", "_registry", "Values")); - await test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } [Test] @@ -500,7 +500,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests .WithLocation(0) .WithArguments("_registry", "Values")); - await test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } [Test] @@ -555,7 +555,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests .WithLocation(0) .WithArguments("Register", "_registry", "Values")); - await test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } [Test] @@ -610,7 +610,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests .WithLocation(0) .WithArguments("Values")); - await test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } [Test] @@ -694,7 +694,7 @@ public class AutoRegisterExportedCollectionsGeneratorTests """; } - private static Task VerifyDiagnosticsAsync( + private static async Task VerifyDiagnosticsAsync( string source, bool skipGeneratedSourcesCheck = false, params DiagnosticResult[] expectedDiagnostics) @@ -718,6 +718,6 @@ public class AutoRegisterExportedCollectionsGeneratorTests test.ExpectedDiagnostics.Add(expectedDiagnostic); } - return test.RunAsync(); + await test.RunAsync().ConfigureAwait(false); } } 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 1ee133e9..3fa5eb3a 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 @@ -6,13 +6,13 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-051` -- 当前阶段:`Phase 51` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-052` +- 当前阶段:`Phase 52` - 当前焦点: - - `2026-04-24` 本轮已完成 `GFramework.Godot.SourceGenerators.Tests` warning 清理 - - 当前主线程切片从生成器实现转到对应测试项目,并已把 `GFramework.Godot.SourceGenerators.Tests` 从 `24` 个 warning 降到 `0` - - 当前批次按 `origin/main` merge-base 计算的累计分支 diff 预计为 `23` 个文件,仍低于 `$gframework-batch-boot 75` 的主阈值 - - 当前工作树除未跟踪的 `.codex` 目录外,还存在与本批次无关的既有文档 / 跟踪文件修改;提交当前批次时必须只包含本 topic 相关文件 + - `2026-04-24` 本轮从当前 PR review 的未解决线程回切到 `GFramework.Game` / `GFramework.Godot.SourceGenerators.Tests` + - `UnifiedSettingsFile.Sections` 与 `CloneFile` fallback 已对齐为“可保留原 comparer 时保留,否则显式回退到 `StringComparer.Ordinal`”的文档与实现契约 + - `AutoRegisterExportedCollectionsGeneratorTests` 中剩余的 `await test.RunAsync();` 已统一补齐 `.ConfigureAwait(false)`,并同步让 `VerifyDiagnosticsAsync` 内部消费异步等待 + - 当前批次仍需避免混入与 analyzer-warning-reduction 无关的既有工作树改动 ## 当前活跃事实 @@ -23,6 +23,8 @@ - 本轮直接执行仓库根目录 `dotnet build` 成功,并给出 `1184 warning(s)` 的真实输出 - `GFramework.Godot.SourceGenerators.Tests` 已通过测试辅助模板抽取与 `ConfigureAwait(false)` 修正,当前 `Debug` / `Release` 构建均为 `0 Warning(s)` - 本轮已验证 `dotnet test GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release --no-build`,结果为 `Passed: 48` +- 本轮已把 PR #283 中仍打开的 `UnifiedSettingsDataRepository.cs` comparer 契约线程落到代码与 XML 注释,避免 fallback 语义继续依赖隐式默认 comparer +- 本轮已确认 `AutoRegisterExportedCollectionsGeneratorTests` 的 5 处裸 `await test.RunAsync();` 不是当前 Release build 告警来源,但仍作为 PR review 一致性项一并修正 ## 当前风险 @@ -32,6 +34,8 @@ - 缓解措施:若下一轮继续做整仓 warning reduction,先定位 `dotnet clean` 的 solution-level 失败原因,或明确继续沿用用户确认的 `1193 warning(s)` clean 基线与本轮 `1184 warning(s)` direct build 观测值 - 当前 worktree 已存在与本批次无关的未提交改动 - 缓解措施:提交当前批次时只暂存 `GFramework.Godot.SourceGenerators.Tests` 与对应 `ai-plan` 文件,避免混入其他 topic 变更 +- `GFramework.Game` 当前 `Release` build 仍带有既有 analyzer warning 基线 + - 缓解措施:本轮仅验证改动未新增 `UnifiedSettingsDataRepository` / `UnifiedSettingsFile` 相关 warning;若继续在该模块做 warning reduction,需要另开切片处理现存基线 ## 活跃文档 @@ -58,8 +62,14 @@ - 结果:成功;`0 Warning(s)`、`0 Error(s)` - `dotnet test GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release --no-build` - 结果:成功;`Passed: 48`、`Failed: 0` +- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`533 Warning(s)`、`0 Error(s)`;模块仍存在既有 warning 基线,本轮 follow-up 仅处理 PR review 指向的 comparer 契约与测试异步等待一致性 +- `dotnet build GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` +- `dotnet test GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release --no-build` + - 结果:成功;`Passed: 48`、`Failed: 0` ## 下一步建议 -1. 提交当前 `GFramework.Godot.SourceGenerators.Tests` 清理批次,并确认提交只包含本 topic 相关文件 -2. 如果继续 warning reduction,优先重新评估仓库根目录 `dotnet clean` 的 solution-level 失败,再决定是继续从整仓 `dotnet build` 输出挑热点,还是先修复 clean 基线采集问题 +1. 提交当前 comparer 契约与 `ConfigureAwait(false)` PR follow-up,并确认只纳入本 topic 相关文件 +2. 视 PR review 反馈决定是否继续收敛 `GFramework.Game` 现有 warning 基线,或返回下一轮整仓 warning 热点筛选 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 b9393bd8..95ac513a 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,32 @@ # Analyzer Warning Reduction 追踪 +# Analyzer Warning Reduction 追踪 + +## 2026-04-24 — RP-052 + +### 阶段:PR review follow-up(comparer 契约 + `ConfigureAwait(false)` 收尾) + +- 触发背景: + - 当前分支 PR #283 的最新 review 中,`greptile-apps[bot]` 仍有一个未解决线程,指出 `UnifiedSettingsDataRepository.CloneFile` fallback 会静默丢失原 comparer + - CodeRabbit 另指出 `AutoRegisterExportedCollectionsGeneratorTests.cs` 中还残留 5 处 `await test.RunAsync();`,与同项目其他测试文件的 `.ConfigureAwait(false)` 风格不一致 +- 主线程实施: + - 复核 PR review JSON、`UnifiedSettingsDataRepository.cs`、`UnifiedSettingsFile.cs` 与 `AutoRegisterExportedCollectionsGeneratorTests.cs` 的当前代码,确认只有 comparer 契约线程仍属最新 head 上的实质问题 + - 将 `UnifiedSettingsFile.Sections` 的 XML 注释补充为显式 comparer 契约,并把默认字典初始化改为 `StringComparer.Ordinal` + - 将 `CloneFile` fallback 从隐式默认 comparer 改为显式 `StringComparer.Ordinal`,并同步修正文档注释,避免继续暗含“保留原语义”的错误表述 + - 把 `AutoRegisterExportedCollectionsGeneratorTests` 中剩余的 5 处 `await test.RunAsync();` 统一为 `.ConfigureAwait(false)`,同时让 `VerifyDiagnosticsAsync` 内部也消费 `ConfigureAwait(false)` +- 验证里程碑: + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`533 Warning(s)`、`0 Error(s)`;`GFramework.Game` 仍有既有 warning 基线,本轮 follow-up 仅处理 PR review 指向的 comparer 契约与测试异步等待一致性 + - `dotnet build GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj -c Release --no-build` + - 首次并行复验:失败;`FileNotFoundException`,原因是 `--no-build` 测试在 Release DLL 落盘前启动 + - 串行复验:成功;`Passed: 48`、`Failed: 0` +- 当前结论: + - PR #283 当前仍打开的 comparer review thread 已在本地代码与 XML 注释层面得到对应修复 + - `AutoRegisterExportedCollectionsGeneratorTests` 的异步等待风格已与同项目其他测试保持一致 + - 当前改动已通过直接受影响测试项目的 Release build 与串行 Release test 复验,可进入提交阶段 + ## 2026-04-24 — RP-051 ### 阶段:`GFramework.Godot.SourceGenerators.Tests` warning 清零