mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-13 14:14:29 +08:00
fix(analyzer): 收敛 CoroutineScheduler 长方法 warning
- 重构 CoroutineScheduler 的启动与完成清理阶段,降低 MA0051 并保持取消与完成语义 - 补充辅助方法注释,保留标签分组、统计和等待者唤醒顺序 - 更新 analyzer warning reduction 的恢复点与验证记录
This commit is contained in:
parent
ec0c9a7bc8
commit
f044aeb770
@ -211,58 +211,10 @@ public sealed class CoroutineScheduler(
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_nextSlot >= _slots.Length)
|
|
||||||
{
|
|
||||||
Expand();
|
|
||||||
}
|
|
||||||
|
|
||||||
var handle = new CoroutineHandle(instanceId);
|
var handle = new CoroutineHandle(instanceId);
|
||||||
var slotIndex = _nextSlot++;
|
var slotIndex = AllocateSlotIndex();
|
||||||
|
var slot = CreateRunningSlot(handle, coroutine, priority, cancellationToken);
|
||||||
var slot = new CoroutineSlot
|
RegisterStartedCoroutine(handle, slotIndex, slot, priority, tag, group);
|
||||||
{
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
Enumerator = coroutine,
|
|
||||||
State = CoroutineState.Running,
|
|
||||||
Handle = handle,
|
|
||||||
Priority = priority
|
|
||||||
};
|
|
||||||
|
|
||||||
if (cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
// 取消回调可能在任意线程触发,因此这里只做排队,真正清理由 Update 主线程完成。
|
|
||||||
slot.CancellationRegistration = cancellationToken.Register(() => _pendingKills.Enqueue(handle));
|
|
||||||
}
|
|
||||||
|
|
||||||
_slots[slotIndex] = slot;
|
|
||||||
_metadata[handle] = new CoroutineMetadata
|
|
||||||
{
|
|
||||||
ExecutionStage = executionStage,
|
|
||||||
Group = group,
|
|
||||||
Priority = priority,
|
|
||||||
SlotIndex = slotIndex,
|
|
||||||
StartTime = _timeSource.CurrentTime * 1000,
|
|
||||||
State = CoroutineState.Running,
|
|
||||||
Tag = tag
|
|
||||||
};
|
|
||||||
|
|
||||||
_completionSources[handle] =
|
|
||||||
new TaskCompletionSource<CoroutineCompletionStatus>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
||||||
_completionStatuses.Remove(handle);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tag))
|
|
||||||
{
|
|
||||||
AddTag(tag, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(group))
|
|
||||||
{
|
|
||||||
AddGroup(group, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
_statistics?.RecordStart(priority, tag);
|
|
||||||
ActiveCoroutineCount++;
|
|
||||||
|
|
||||||
Prewarm(slotIndex);
|
Prewarm(slotIndex);
|
||||||
UpdateStatisticsSnapshot();
|
UpdateStatisticsSnapshot();
|
||||||
|
|
||||||
@ -662,70 +614,14 @@ public sealed class CoroutineScheduler(
|
|||||||
CoroutineCompletionStatus completionStatus,
|
CoroutineCompletionStatus completionStatus,
|
||||||
Exception? exception = null)
|
Exception? exception = null)
|
||||||
{
|
{
|
||||||
var slot = _slots[slotIndex];
|
if (!TryGetFinalizableCoroutine(slotIndex, out var slot, out var handle))
|
||||||
if (slot == null)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var handle = slot.Handle;
|
UpdateCompletionMetadata(handle, completionStatus);
|
||||||
if (!handle.IsValid)
|
ReleaseCompletedCoroutine(slotIndex, slot, handle);
|
||||||
{
|
CompleteCoroutineLifecycle(handle, completionStatus);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_metadata.TryGetValue(handle, out var meta))
|
|
||||||
{
|
|
||||||
if (meta.State == CoroutineState.Paused && _pausedCount > 0)
|
|
||||||
{
|
|
||||||
_pausedCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
var executionTime = _timeSource.CurrentTime * 1000 - meta.StartTime;
|
|
||||||
switch (completionStatus)
|
|
||||||
{
|
|
||||||
case CoroutineCompletionStatus.Completed:
|
|
||||||
meta.State = CoroutineState.Completed;
|
|
||||||
_statistics?.RecordComplete(executionTime, meta.Priority, meta.Tag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CoroutineCompletionStatus.Faulted:
|
|
||||||
meta.State = CoroutineState.Completed;
|
|
||||||
_statistics?.RecordFailure(meta.Priority, meta.Tag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CoroutineCompletionStatus.Cancelled:
|
|
||||||
meta.State = CoroutineState.Cancelled;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(
|
|
||||||
nameof(completionStatus),
|
|
||||||
completionStatus,
|
|
||||||
"Unsupported coroutine completion status.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposeSlotResources(slot);
|
|
||||||
|
|
||||||
_slots[slotIndex] = null;
|
|
||||||
if (ActiveCoroutineCount > 0)
|
|
||||||
{
|
|
||||||
ActiveCoroutineCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveTag(handle);
|
|
||||||
RemoveGroup(handle);
|
|
||||||
_metadata.Remove(handle);
|
|
||||||
|
|
||||||
WakeWaiters(handle);
|
|
||||||
|
|
||||||
if (_completionSources.Remove(handle, out var source))
|
|
||||||
{
|
|
||||||
source.TrySetResult(completionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordCompletionStatus(handle, completionStatus);
|
|
||||||
OnCoroutineFinished?.Invoke(handle, completionStatus, exception);
|
OnCoroutineFinished?.Invoke(handle, completionStatus, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,6 +695,139 @@ public sealed class CoroutineScheduler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为新协程分配槽位索引,并在需要时扩容槽位数组。
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>可写入的新槽位索引。</returns>
|
||||||
|
private int AllocateSlotIndex()
|
||||||
|
{
|
||||||
|
if (_nextSlot >= _slots.Length)
|
||||||
|
{
|
||||||
|
Expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _nextSlot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建处于运行态的协程槽位,并在需要时挂接跨线程取消回调。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">新协程句柄。</param>
|
||||||
|
/// <param name="coroutine">协程枚举器。</param>
|
||||||
|
/// <param name="priority">协程优先级。</param>
|
||||||
|
/// <param name="cancellationToken">外部取消令牌。</param>
|
||||||
|
/// <returns>已初始化的协程槽位。</returns>
|
||||||
|
private CoroutineSlot CreateRunningSlot(
|
||||||
|
CoroutineHandle handle,
|
||||||
|
IEnumerator<IYieldInstruction> coroutine,
|
||||||
|
CoroutinePriority priority,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var slot = new CoroutineSlot
|
||||||
|
{
|
||||||
|
CancellationToken = cancellationToken,
|
||||||
|
Enumerator = coroutine,
|
||||||
|
State = CoroutineState.Running,
|
||||||
|
Handle = handle,
|
||||||
|
Priority = priority
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterCancellationCallback(slot, handle, cancellationToken);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为支持取消的协程注册待终止排队回调。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slot">目标协程槽位。</param>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
/// <param name="cancellationToken">外部取消令牌。</param>
|
||||||
|
private void RegisterCancellationCallback(
|
||||||
|
CoroutineSlot slot,
|
||||||
|
CoroutineHandle handle,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消回调可能在任意线程触发,因此这里只做排队,真正清理由 Update 主线程完成。
|
||||||
|
slot.CancellationRegistration = cancellationToken.Register(() => _pendingKills.Enqueue(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将新协程写入调度器的槽位、元数据、标签分组和完成状态跟踪结构。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
/// <param name="slotIndex">槽位索引。</param>
|
||||||
|
/// <param name="slot">已初始化的协程槽位。</param>
|
||||||
|
/// <param name="priority">协程优先级。</param>
|
||||||
|
/// <param name="tag">可选标签。</param>
|
||||||
|
/// <param name="group">可选分组。</param>
|
||||||
|
private void RegisterStartedCoroutine(
|
||||||
|
CoroutineHandle handle,
|
||||||
|
int slotIndex,
|
||||||
|
CoroutineSlot slot,
|
||||||
|
CoroutinePriority priority,
|
||||||
|
string? tag,
|
||||||
|
string? group)
|
||||||
|
{
|
||||||
|
_slots[slotIndex] = slot;
|
||||||
|
_metadata[handle] = CreateCoroutineMetadata(slotIndex, priority, tag, group);
|
||||||
|
ResetCompletionTracking(handle);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(tag))
|
||||||
|
{
|
||||||
|
AddTag(tag, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(group))
|
||||||
|
{
|
||||||
|
AddGroup(group, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
_statistics?.RecordStart(priority, tag);
|
||||||
|
ActiveCoroutineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建新协程的初始元数据。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slotIndex">槽位索引。</param>
|
||||||
|
/// <param name="priority">协程优先级。</param>
|
||||||
|
/// <param name="tag">可选标签。</param>
|
||||||
|
/// <param name="group">可选分组。</param>
|
||||||
|
/// <returns>与新槽位对应的元数据对象。</returns>
|
||||||
|
private CoroutineMetadata CreateCoroutineMetadata(
|
||||||
|
int slotIndex,
|
||||||
|
CoroutinePriority priority,
|
||||||
|
string? tag,
|
||||||
|
string? group)
|
||||||
|
{
|
||||||
|
return new CoroutineMetadata
|
||||||
|
{
|
||||||
|
ExecutionStage = executionStage,
|
||||||
|
Group = group,
|
||||||
|
Priority = priority,
|
||||||
|
SlotIndex = slotIndex,
|
||||||
|
StartTime = _timeSource.CurrentTime * 1000,
|
||||||
|
State = CoroutineState.Running,
|
||||||
|
Tag = tag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置协程完成跟踪,使复用句柄不会携带上一轮完成结果。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
private void ResetCompletionTracking(CoroutineHandle handle)
|
||||||
|
{
|
||||||
|
_completionSources[handle] =
|
||||||
|
new TaskCompletionSource<CoroutineCompletionStatus>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
_completionStatuses.Remove(handle);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 释放单个槽位持有的资源。
|
/// 释放单个槽位持有的资源。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -824,6 +853,125 @@ public sealed class CoroutineScheduler(
|
|||||||
slot.Waiting = null;
|
slot.Waiting = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取可被完成处理的协程槽位与句柄。
|
||||||
|
/// 当槽位已空或句柄已失效时,说明该协程已经被其他路径清理,无需重复执行结束逻辑。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slotIndex">槽位索引。</param>
|
||||||
|
/// <param name="slot">若成功则返回槽位。</param>
|
||||||
|
/// <param name="handle">若成功则返回句柄。</param>
|
||||||
|
/// <returns>当存在可完成的协程时返回 <see langword="true" />。</returns>
|
||||||
|
private bool TryGetFinalizableCoroutine(int slotIndex, out CoroutineSlot slot, out CoroutineHandle handle)
|
||||||
|
{
|
||||||
|
var candidate = _slots[slotIndex];
|
||||||
|
if (candidate == null)
|
||||||
|
{
|
||||||
|
slot = null!;
|
||||||
|
handle = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = candidate.Handle;
|
||||||
|
if (!handle.IsValid)
|
||||||
|
{
|
||||||
|
slot = null!;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = candidate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据最终状态更新协程元数据与统计信息。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
/// <param name="completionStatus">最终结果。</param>
|
||||||
|
private void UpdateCompletionMetadata(CoroutineHandle handle, CoroutineCompletionStatus completionStatus)
|
||||||
|
{
|
||||||
|
if (!_metadata.TryGetValue(handle, out var meta))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta.State == CoroutineState.Paused && _pausedCount > 0)
|
||||||
|
{
|
||||||
|
_pausedCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyCompletionMetadata(meta, completionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将最终结果映射到元数据状态和统计记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="meta">协程元数据。</param>
|
||||||
|
/// <param name="completionStatus">最终结果。</param>
|
||||||
|
private void ApplyCompletionMetadata(CoroutineMetadata meta, CoroutineCompletionStatus completionStatus)
|
||||||
|
{
|
||||||
|
var executionTime = _timeSource.CurrentTime * 1000 - meta.StartTime;
|
||||||
|
switch (completionStatus)
|
||||||
|
{
|
||||||
|
case CoroutineCompletionStatus.Completed:
|
||||||
|
meta.State = CoroutineState.Completed;
|
||||||
|
_statistics?.RecordComplete(executionTime, meta.Priority, meta.Tag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CoroutineCompletionStatus.Faulted:
|
||||||
|
meta.State = CoroutineState.Completed;
|
||||||
|
_statistics?.RecordFailure(meta.Priority, meta.Tag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CoroutineCompletionStatus.Cancelled:
|
||||||
|
meta.State = CoroutineState.Cancelled;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(completionStatus),
|
||||||
|
completionStatus,
|
||||||
|
"Unsupported coroutine completion status.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放已结束协程占用的槽位和索引结构。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slotIndex">槽位索引。</param>
|
||||||
|
/// <param name="slot">已结束的协程槽位。</param>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
private void ReleaseCompletedCoroutine(int slotIndex, CoroutineSlot slot, CoroutineHandle handle)
|
||||||
|
{
|
||||||
|
DisposeSlotResources(slot);
|
||||||
|
|
||||||
|
_slots[slotIndex] = null;
|
||||||
|
if (ActiveCoroutineCount > 0)
|
||||||
|
{
|
||||||
|
ActiveCoroutineCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveTag(handle);
|
||||||
|
RemoveGroup(handle);
|
||||||
|
_metadata.Remove(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 完成协程的等待者唤醒、任务结果和完成历史记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">协程句柄。</param>
|
||||||
|
/// <param name="completionStatus">最终结果。</param>
|
||||||
|
private void CompleteCoroutineLifecycle(CoroutineHandle handle, CoroutineCompletionStatus completionStatus)
|
||||||
|
{
|
||||||
|
WakeWaiters(handle);
|
||||||
|
|
||||||
|
if (_completionSources.Remove(handle, out var source))
|
||||||
|
{
|
||||||
|
source.TrySetResult(completionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordCompletionStatus(handle, completionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 唤醒所有等待目标协程完成的协程。
|
/// 唤醒所有等待目标协程完成的协程。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -7,21 +7,20 @@
|
|||||||
|
|
||||||
## 当前恢复点
|
## 当前恢复点
|
||||||
|
|
||||||
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-006`
|
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-007`
|
||||||
- 当前阶段:`Phase 6`
|
- 当前阶段:`Phase 7`
|
||||||
- 当前焦点:
|
- 当前焦点:
|
||||||
- 已完成 `GFramework.Core/StateManagement/Store.cs` 的 `MA0051` 收口:将 `Dispatch` 拆分为“进入分发域 / 提交结果 / 退出分发域”
|
- 已完成 `GFramework.Core/Coroutine/CoroutineScheduler.cs` 的 `MA0051` 收口:将 `Run` 拆分为槽位分配、运行槽创建和启动注册阶段,
|
||||||
三个辅助阶段,并将 reducer 快照创建拆分为精确匹配与多态匹配两条路径
|
将 `FinalizeCoroutine` 拆分为可完成目标读取、完成元数据更新、资源释放和生命周期收尾阶段
|
||||||
- 本轮保持 `Store` 的锁顺序、middleware 执行时机、batch 通知折叠和多态 reducer 排序规则不变,未改公共 API
|
- 本轮保持取消回调入队、统计记录、标签/分组清理、等待者唤醒和完成任务语义不变,未改公共 API
|
||||||
- 下一轮若继续推进,优先只处理 `GFramework.Core/Coroutine/CoroutineScheduler.cs` 的剩余 `MA0051`,不回到已完成的
|
- 当前 `MA0051` 主线已完成;下一轮若继续推进,应先判断剩余 `MA0048`、`MA0046`、`MA0002`、`MA0016` 是否值得继续低风险收敛
|
||||||
`Store` 或 `PauseStackManager`
|
|
||||||
|
|
||||||
## 当前状态摘要
|
## 当前状态摘要
|
||||||
|
|
||||||
- 已完成 `GFramework.Core`、`GFramework.Cqrs`、`GFramework.Godot` 与部分 source generator 的低风险 warning 清理
|
- 已完成 `GFramework.Core`、`GFramework.Cqrs`、`GFramework.Godot` 与部分 source generator 的低风险 warning 清理
|
||||||
- 已完成多轮 CodeRabbit follow-up 修复,并用定向测试与项目/解决方案构建验证了关键回归风险
|
- 已完成多轮 CodeRabbit follow-up 修复,并用定向测试与项目/解决方案构建验证了关键回归风险
|
||||||
- 当前 `PauseStackManager` 与 `Store` 的长方法 warning 已从 active 入口移除;主题内剩余 warning 主要集中在
|
- 当前 `PauseStackManager`、`Store` 与 `CoroutineScheduler` 的长方法 warning 已从 active 入口移除;主题内剩余 warning
|
||||||
`GFramework.Core/Coroutine/CoroutineScheduler.cs`、文件/类型命名冲突、delegate 形状和少量公共集合抽象接口问题
|
主要集中在文件/类型命名冲突、delegate 形状、字符串 comparer 重载和少量公共集合抽象接口问题
|
||||||
|
|
||||||
## 当前活跃事实
|
## 当前活跃事实
|
||||||
|
|
||||||
@ -33,6 +32,8 @@
|
|||||||
- `RP-005` 已在不改公共 API 的前提下完成 `PauseStackManager` 两个 `MA0051` 的结构拆分,并补充销毁通知回归测试
|
- `RP-005` 已在不改公共 API 的前提下完成 `PauseStackManager` 两个 `MA0051` 的结构拆分,并补充销毁通知回归测试
|
||||||
- `RP-006` 已在不改公共 API 的前提下完成 `Store` 两个 `MA0051` 的结构拆分,并通过定向 build/test 验证 dispatch、
|
- `RP-006` 已在不改公共 API 的前提下完成 `Store` 两个 `MA0051` 的结构拆分,并通过定向 build/test 验证 dispatch、
|
||||||
多态 reducer 匹配与历史语义未回归
|
多态 reducer 匹配与历史语义未回归
|
||||||
|
- `RP-007` 已在不改公共 API 的前提下完成 `CoroutineScheduler` 两个 `MA0051` 的结构拆分,并通过定向 build/test 验证
|
||||||
|
调度、取消与完成状态语义未回归
|
||||||
- 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射
|
- 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射
|
||||||
|
|
||||||
## 当前风险
|
## 当前风险
|
||||||
@ -71,11 +72,16 @@
|
|||||||
- 结果:`25 Warning(s)`,`0 Error(s)`;`Store.cs` 已不再出现在 `MA0051` 列表中
|
- 结果:`25 Warning(s)`,`0 Error(s)`;`Store.cs` 已不再出现在 `MA0051` 列表中
|
||||||
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter FullyQualifiedName~StoreTests -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo`
|
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter FullyQualifiedName~StoreTests -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo`
|
||||||
- 结果:`30 Passed`,`0 Failed`
|
- 结果:`30 Passed`,`0 Failed`
|
||||||
|
- `RP-007` 的定向验证结果:
|
||||||
|
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo -clp:"Summary;WarningsOnly"`
|
||||||
|
- 结果:`23 Warning(s)`,`0 Error(s)`;`CoroutineScheduler.cs` 已不再出现在 `MA0051` 列表中
|
||||||
|
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter FullyQualifiedName~CoroutineScheduler -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo`
|
||||||
|
- 结果:`34 Passed`,`0 Failed`
|
||||||
- active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史
|
- active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史
|
||||||
|
|
||||||
## 下一步
|
## 下一步
|
||||||
|
|
||||||
1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录
|
1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录
|
||||||
2. 优先在 `GFramework.Core/Coroutine/CoroutineScheduler.cs` 的 `Run` 与 `FinalizeCoroutine` 两个 `MA0051`
|
2. 先基于当前 `23 Warning(s)` 的唯一源位置清单,判断 `MA0048` 文件命名冲突与 `MA0046` delegate 形状是否存在低风险切入点,
|
||||||
中继续,保持“单文件、单 warning family”的节奏
|
再决定是否开启下一轮 warning family 收敛
|
||||||
3. 若本主题确认暂缓,可保持当前归档状态,不需要再恢复 `local-plan/`
|
3. 若本主题确认暂缓,可保持当前归档状态,不需要再恢复 `local-plan/`
|
||||||
|
|||||||
@ -1,5 +1,35 @@
|
|||||||
# Analyzer Warning Reduction 追踪
|
# Analyzer Warning Reduction 追踪
|
||||||
|
|
||||||
|
## 2026-04-21 — RP-007
|
||||||
|
|
||||||
|
### 阶段:CoroutineScheduler `MA0051` 收口(RP-007)
|
||||||
|
|
||||||
|
- 依据 active tracking 中“继续只选一个 `GFramework.Core` 结构性切入点”的约束,本轮选择
|
||||||
|
`GFramework.Core/Coroutine/CoroutineScheduler.cs`,因为剩余两个 `MA0051` 都集中在协程启动与完成清理路径,且已有
|
||||||
|
`CoroutineSchedulerTests`、`CoroutineSchedulerAdvancedTests` 覆盖句柄创建、取消、完成状态、标签分组和等待语义
|
||||||
|
- 将 `Run` 拆分为:
|
||||||
|
- `AllocateSlotIndex`
|
||||||
|
- `CreateRunningSlot`
|
||||||
|
- `RegisterCancellationCallback`
|
||||||
|
- `RegisterStartedCoroutine`
|
||||||
|
- `CreateCoroutineMetadata`
|
||||||
|
- `ResetCompletionTracking`
|
||||||
|
- 将 `FinalizeCoroutine` 拆分为:
|
||||||
|
- `TryGetFinalizableCoroutine`
|
||||||
|
- `UpdateCompletionMetadata`
|
||||||
|
- `ApplyCompletionMetadata`
|
||||||
|
- `ReleaseCompletedCoroutine`
|
||||||
|
- `CompleteCoroutineLifecycle`
|
||||||
|
- 保持取消回调只做跨线程入队、`Prewarm` 时机、统计记录文本、`RemoveTag` / `RemoveGroup` / `WakeWaiters` 顺序以及
|
||||||
|
`OnCoroutineFinished` 的同步触发时机不变,只收缩主方法长度并补齐辅助方法意图注释
|
||||||
|
- 验证通过:
|
||||||
|
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo -clp:"Summary;WarningsOnly"`
|
||||||
|
- 结果:`23 Warning(s)`,`0 Error(s)`;`CoroutineScheduler.cs` 已不再出现在 `MA0051` 列表
|
||||||
|
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter FullyQualifiedName~CoroutineScheduler -p:RestoreFallbackFolders="" -p:RestorePackagesPath=<linux-nuget-cache> -nologo`
|
||||||
|
- 结果:`34 Passed`,`0 Failed`
|
||||||
|
- 当前 `MA0051` 主线已经在本主题下完成;下一步若继续,应先重新评估剩余 `MA0048`、`MA0046`、`MA0002`、`MA0016` 的
|
||||||
|
收敛价值与改动风险,再决定是否开启下一轮 warning family
|
||||||
|
|
||||||
## 2026-04-21 — RP-006
|
## 2026-04-21 — RP-006
|
||||||
|
|
||||||
### 阶段:Store `MA0051` 收口(RP-006)
|
### 阶段:Store `MA0051` 收口(RP-006)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user