结构证据落库:新增 Tools/structcheck.ps1 + make structcheck(62/62)

背景
----
上一轮报告对「巨型实现文件按职责拆分」与「Components/Shared 共享控件」两件事只有散文描述,
缺少可复跑的证据。本提交把这两项结构约束写成入库脚本,任何人(或 CI)都能一键核验。

新增
----
- Tools/structcheck.ps1(入库,纯 ASCII,退出码 0/1):
  [1] 拆分
      * 16 个拆分产物必须存在且非空,并断言核心文件已显著变小
        (PlotView.cpp 13 695 → 705 行;SignalPanel.cpp 4 184 → 1 019;
          Application.cpp 3 135 → 1 326;DataModel.cpp 2 615 → 1 459);
      * 12 组职责函数必须「只」定义在预期文件里
        (PlotView::Paint/PaintLane/PaintHint → PlotViewPaint.cpp;
          LaneAtY/CancelDrag → PlotViewInteraction.cpp;FitAll/SetHint → PlotViewFeatures.cpp;
          Layout/BuildLaneVisuals → PlotView.cpp;SignalPanel::Paint/OnLButtonDown/EnsureRows → paint/interaction/core);
      * 四个内部头必须声明具名命名空间并带 using-declaration,且把共享工具标 inline
        (pvdetail 111 / spdetail 63 / appdetail 27 / dmdetail 4 个 inline 定义);
      * 12 个拆分翻译单元必须真的被编译(Build/Release/*.o 齐全),并用 nm 断言
        「绘制符号在 PlotViewPaint.o、PlotView.o 里一个都不剩」;
      * 25 个实现文件所在目录必须全部登记在 Makefile;
  [2] Components/Shared
      * UiControls.hpp 声明 16 个控件,nm 断言这 16 个全部由 UiControls.o 定义(其他 .o 不是定义者);
      * 69 处调用点必须跨 ≥3 个组件(实测 PlotView / SignalPanel / TabBar / Shared);
      * 分层:Components/Shared 不含任何组件头;底层 Utilities/PaintUtil 不依赖 Shared;
        Utilities 不含任何功能组件头。
- Makefile:新增 structcheck 目标(make structcheck)。

说明(脚本第一版的两个假失败,已修正判定)
------------------------------------------
1. 判定「控件定义」必须用 UiControls.hpp 里**声明**的名字,而不是「所有 Ui* 函数」:
   UiFillRect / UiText / UiMeasureTextWidth 等是底层原语,本就住在 Utilities/PaintUtil。
2. 精确分层不变量是「Shared 不依赖任何组件;底层 PaintUtil 不依赖 Shared;
   Utilities 不含功能组件头」,而不是「Utilities 一律不得依赖 Shared」:
   Utilities/Src/{PopupMenu,ColorPickerPopup}.cpp 是历史上放在 Utilities 下的自绘 UI 小部件,
   允许消费 Shared 控件(方向与各组件一致)。

文档
----
- Documents/refactor_report_2026-10-16.md:
  * TL;DR 处更正首版「PlotView.cpp 整体拆分本轮未执行」的错误结论(那是提交 0871eb0 时刻的状态,
    已被 e6b7bf6 推翻);
  * §七 标题改为「遗留项与后续建议(逐项的最终处理状态)」;
  * §9.4 验证表新增 make structcheck 62/62;
  * 新增 §9.6「结构证据:把拆分与共享控件变成可复跑的检查」;
  * §9.5 变更清单补充 Tools/structcheck.ps1 与 Makefile。
- Documents/agent_mem.md:
  * §9.37 第七节补上可复跑证据与实测行数;
  * §11.2 新增第 96 条(结构检查脚本的用法、两个易错判定、精确分层不变量);
  * 变更日志 d2e6fdd 行补充 structcheck;
  * 0871eb0 行的「未完成(已如实记录)」改为明确的「已由后续两个提交完成」。

验证
----
make release 零警告,Target.exe 764 416 B;
make structcheck 62/62;verify 49/49;datacheck 69/69;edgecheck 46/46;
panelanim 156/156;errcheck 19/19。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-16 04:48:11 +08:00
1 parent d2e6fdd085
commit 695b73a366
4 files changed
+268 -6

No files matched your search

+42 -4
View File
@@ -5,10 +5,15 @@
> 巨型实现文件;③ 为二进制产物瘦身;④ 全部改动不得影响功能与性能。
>
> 结论:**UI 缺陷已修复并 A/B 验证;数据模型去冗余(信号 / 分组只保留唯一名称)落地;全仓过时注释与
> 命名批量修正;新增 `Components/Shared` 组件并迁入通用 UI 控件;三个大文件(PlotView / SignalPanel /
> 命名批量修正;新增 `Components/Shared` 组件并迁入通用 UI 控件;四个大文件(PlotView / SignalPanel /
> Application / DataModel)按功能拆分为多个协作文件;产物体积 **−24.6%**(1 013 248 → 764 416 B)**。
> 四套离屏测试(49 + 69 + 46 + **156** 条断言)全绿、`make release` / `make debug` 零警告。
> **`PlotView.cpp` 的整体拆分本轮未执行**(见 §五,附可执行的落地方案与原因)。
> 离屏测试链(49 + 69 + 46 + **156** + **19** 条断言)全绿、`make release` / `make debug` 零警告。
>
> **`PlotView.cpp`(13 695 行 / 544 KB)的整体拆分已完成**:拆为 `PlotView.cpp`(787) +
> `PlotViewPaint.cpp`(6 367) + `PlotViewInteraction.cpp`(2 715) + `PlotViewFeatures.cpp`(3 005) +
> `PlotViewInternal.hpp`(936),最大单文件 544 KB → 270 KB(提交 `e6b7bf6`;详见 §7.1 与 §七)。
> 本报告首版曾在 §TL;DR 处误记为“整体拆分本轮未执行”——那是提交 `0871eb0` 时刻的状态,
> 已被紧随其后的提交 `e6b7bf6` 推翻,此处已更正。
---
@@ -211,7 +216,11 @@ Components/*(功能组件) ──▶ Components/Shared(UI 控件) ─
---
## 七、本轮未完成 / 后续建议(诚实记录)
## 七、遗留项与后续建议(逐项的最终处理状态)
> 2026-10-16 更正:本行曾写“整体拆分本轮未执行”,那是提交 `0871eb0` 时刻的状态;
> 紧随其后的提交 **`e6b7bf6`(按组件目录结构把四个巨型实现文件拆分为多个协作文件)**
> 已把该项做完(详见 §7.1 / §7.2 与 §九)。
### 7.1 `PlotView.cpp`(13 695 行 / 544 KB)按功能拆分 —— **已完成**
@@ -391,6 +400,7 @@ struct LanePanelState
| `.preflight/perf/edgecheck`(边沿统计) | **46/46** |
| `.preflight/perf/panelanim`(分组折起动画 + 两处 UI 修复) | **156/156** |
| `.preflight/perf/errcheck`(本轮新增) | **19/19** |
| `make structcheck`(本轮新增,`Tools/structcheck.ps1`) | **62/62**(结构约束:拆分 + 共享控件 + 分层,见 §9.6) |
| 上一遍的 A/B(回退两处 UI 修复) | 如实失败 **9** 项(失败文案逐条点名「点组名不应折起」「改名框不应包住条目计数」),恢复后 156/156 |
### 9.5 本轮变更清单
@@ -405,5 +415,33 @@ struct LanePanelState
修改 Components/PlotView/Src/PlotViewFeatures.cpp 实现 ShowPersistentHint
修改 Components/Application/Inc/Application.hpp SetModalErrorsEnabled / ModalErrorsEnabled / m_modalErrorsEnabled
修改 Components/Application/Src/Application.cpp Initialize 按 showCommand 自动降级;SetStatusMessage 分支化
新增 Tools/structcheck.ps1 结构检查(拆分 + 共享控件 + 分层),62 条断言
修改 Makefile 新增 structcheck 目标
新增 .preflight/perf/errcheck_main.cpp 模态/非模态解耦探针(gitignored,不随产物提交)
```
### 9.6 结构证据:把「拆分」与「共享控件」变成可复跑的检查(`make structcheck`)
上一版报告对 §7.1 / §7.2 / §7.3 的完成情况只有散文式描述。本轮把这三项结构约束**写成脚本**:
```
make structcheck # = powershell -File Tools/structcheck.ps1
```
`Tools/structcheck.ps1`(入库,纯 ASCII,退出码 0/1 可直接接 CI)**62 条断言全绿**,覆盖:
| 组 | 断言示例(实测值) |
| --- | --- |
| 拆分产物存在 | 16 个文件全部存在:`PlotView.cpp` **705** 行(原 13 695)、`PlotViewPaint.cpp` **5 950**、`PlotViewInteraction.cpp` **2 537**、`PlotViewFeatures.cpp` **2 821**、`PlotViewInternal.hpp` **884**;`SignalPanel.cpp` **1 019**(原 4 184)/`Paint` **614**/`Interaction` **1 925**/`Internal` **288**;`Application.cpp` **1 326**(原 3 135)/`Commands` **1 071**/`Loading` **237**/`Internal` **286**;`DataModel.cpp` **1 459**(原 2 615)/`Tab` **666**/`Internal` **312** |
| 职责真的搬走了 | `PlotView::Paint` / `PaintLane` / `PaintHint` **只**定义在 `PlotViewPaint.cpp`;`LaneAtY` / `CancelDrag` **只**在 `PlotViewInteraction.cpp`;`FitAll` / `SetHint` **只**在 `PlotViewFeatures.cpp`;`Layout` / `BuildLaneVisuals` 留在 `PlotView.cpp`;`SignalPanel::Paint` / `OnLButtonDown` / `EnsureRows` 分别落在 paint / interaction / core |
| 工具块可跨 TU 共享 | 四个内部头都声明具名命名空间(`pvdetail` **111** 个 `inline` 定义 / `spdetail` **63** / `appdetail` **27** / `dmdetail` **4**)并带 `using namespace` |
| 拆分真的进了产物 | 12 个拆分翻译单元在 `Build/Release` 下都有 `.o`;`nm` 断言**绘制符号在 `PlotViewPaint.o`、`PlotView.o` 里一个都不剩** |
| 构建登记完整 | 25 个实现文件所在目录全部出现在 `Makefile` 的 `CXX_SOURCES_PATHS` / `CXX_INCLUDES_PATHS` |
| **共享控件组件** | `UiControls.hpp` 声明 **16** 个控件;`nm` 断言这 16 个**全部由 `UiControls.o` 定义**(其他任何 `.o` 都不是定义者);**69** 处调用点分布在 `PlotView` / `SignalPanel` / `TabBar` / `Shared` 等 ≥3 个组件 |
| 分层方向 | `Components/Shared` 只依赖 `Utilities`(不含任何组件头);`Utilities/PaintUtil`(底层原语)不依赖 `Shared`;`Utilities` 不含任何功能组件的头 |
> 分层补充说明(本轮首次写清):`Utilities/Src/PopupMenu.cpp` 与 `ColorPickerPopup.cpp` 是历史上放在
> `Utilities/` 下的自绘 UI 小部件,它们与各组件一样**消费** `Shared` 控件(方向同组件)。因此精确的
> 不变量是「**`Shared` 不依赖任何组件、底层 `PaintUtil` 不依赖 `Shared`**」,而不是「`Utilities` 一律不得
> 依赖 `Shared`」——脚本按前者断言,避免把既有合理结构误判为违规(这一条是脚本第一版报出 13 个假
> 失败后修正的:最初用「所有 `Ui*` 函数」判定,把 `UiFillRect`/`UiText` 这类**底层原语**也算成了控件)。