@ohos-cpf/3rdloop 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/cli.js +2 -2
  2. package/package.json +1 -1
  3. package/vendor/Server/Routes/controllers/LoopEngineController.js +36 -3
  4. package/vendor/Server/Routes/controllers/OrchestratorController.js +193 -9
  5. package/vendor/Server/Skills/flutter-build-test/SKILL.md +252 -0
  6. package/vendor/Server/Skills/flutter-build-test/assets/BUILDENV_TEMPLATE.md +42 -0
  7. package/vendor/Server/Skills/flutter-build-test/assets/BUILD_REPORT_TEMPLATE.md +64 -0
  8. package/vendor/Server/Skills/flutter-build-test/assets/README_SECTION_TEMPLATE.md +78 -0
  9. package/vendor/Server/Skills/flutter-build-test/references/BUILD_TROUBLESHOOTING.md +128 -0
  10. package/vendor/Server/Skills/flutter-build-test/references/DOC_UPDATE_GUIDE.md +119 -0
  11. package/vendor/Server/Skills/flutter-build-test/references/FLVM_GUIDE.md +89 -0
  12. package/vendor/Server/Skills/flutter-build-test/scripts/build-matrix.cjs +374 -0
  13. package/vendor/Server/Skills/flutter-build-test/scripts/locate-example.cjs +189 -0
  14. package/vendor/Server/Skills/flutter-build-test/scripts/update-buildenv.cjs +171 -0
  15. package/vendor/Server/Skills/flutter-code-use/SKILL.md +316 -0
  16. package/vendor/Server/Skills/flutter-code-use/references/event-channel.md +440 -0
  17. package/vendor/Server/Skills/flutter-code-use/references/federated.md +295 -0
  18. package/vendor/Server/Skills/flutter-code-use/references/ffi-binding-translate.md +130 -0
  19. package/vendor/Server/Skills/flutter-code-use/references/ffi-compile-from-source.md +169 -0
  20. package/vendor/Server/Skills/flutter-code-use/references/ffi-fetch-at-build.md +161 -0
  21. package/vendor/Server/Skills/flutter-code-use/references/ffi-prebuilt-bundle.md +175 -0
  22. package/vendor/Server/Skills/flutter-code-use/references/ffi-rhttp-guide.md +235 -0
  23. package/vendor/Server/Skills/flutter-code-use/references/ffi-rust-cross-compile.md +514 -0
  24. package/vendor/Server/Skills/flutter-code-use/references/ffi.md +220 -0
  25. package/vendor/Server/Skills/flutter-code-use/references/method-channel.md +643 -0
  26. package/vendor/Server/Skills/flutter-code-use/references/monorepo.md +188 -0
  27. package/vendor/Server/Skills/flutter-code-use/references/ohos-api-pitfalls.md +717 -0
  28. package/vendor/Server/Skills/flutter-code-use/references/platform-view.md +448 -0
  29. package/vendor/Server/Skills/flutter-code-use/references/pure-dart.md +180 -0
  30. package/vendor/Server/Skills/flutter-code-use/references/texture.md +459 -0
  31. package/vendor/Server/Skills/flutter-demo-code-generator/SKILL.md +270 -0
  32. package/vendor/Server/Skills/flutter-demo-code-generator/assets/PAGE_TEMPLATES.md +544 -0
  33. package/vendor/Server/Skills/flutter-demo-code-generator/references/CODE_STANDARDS.md +328 -0
  34. package/vendor/Server/Skills/flutter-demo-code-generator/references/DEMO_DOC_PARSING.md +126 -0
  35. package/vendor/Server/Skills/flutter-demo-code-generator/references/EXAMPLES.md +629 -0
  36. package/vendor/Server/Skills/flutter-demo-code-generator/scripts/validate-flutter-demo.cjs +268 -0
  37. package/vendor/Server/Skills/flutter-demo-doc-generator/SKILL.md +227 -0
  38. package/vendor/Server/Skills/flutter-demo-doc-generator/assets/DEMO_DOC_TEMPLATE.md +78 -0
  39. package/vendor/Server/Skills/flutter-demo-doc-generator/references/COVERAGE_REPORT_PARSING.md +174 -0
  40. package/vendor/Server/Skills/flutter-demo-doc-generator/references/EXAMPLES.md +162 -0
  41. package/vendor/Server/Skills/flutter-demo-doc-generator/references/MCP_TOOL_GUIDE.md +123 -0
  42. package/vendor/Server/Skills/flutter-demo-doc-generator/references/OUTPUT_FORMAT.md +190 -0
  43. package/vendor/Server/Skills/flutter-demo-doc-generator/references/QUALITY_CHECKLIST.md +83 -0
  44. package/vendor/Server/Skills/flutter-demo-doc-generator/scripts/validate-skill.cjs +259 -0
  45. package/vendor/Server/Skills/flutter-library-demo-coverage/SKILL.md +175 -0
  46. package/vendor/VERSION +3 -3
@@ -0,0 +1,174 @@
1
+ # 覆盖率报告解析指南
2
+
3
+ > 本文档定义 `flutter-analyze-demo-coverage.cjs` 生成的 Demo 覆盖率报告的结构、各章节解析方法与边界处理,是 SKILL.md Phase 2 的详细展开。
4
+
5
+ ---
6
+
7
+ ## 1. 报告来源
8
+
9
+ - **生成方**:`flutter-library-demo-coverage` 技能(脚本 `MCP/scripts/flutter-analyze-demo-coverage.cjs`)
10
+ - **产物形态**:单份最终 Markdown 报告(默认 `02-{库名}-Demo覆盖率报告.md`),无中间 JSON
11
+ - **分析口径**:静态 import 分析 + 正则匹配(`show`/`hide`/`as` 别名解析、实例变量类型追踪、命名参数兜底),扫描范围默认 `example/lib`(或 `examples/lib`、`demo/lib`)
12
+
13
+ ---
14
+
15
+ ## 2. 报告章节结构
16
+
17
+ | # | 章节 | 内容 | 本技能用途 |
18
+ |---|------|------|-----------|
19
+ | 1 | 基本信息 | 库名、源文件数、生成时间 | `libName` 核对 |
20
+ | 2 | 覆盖率总览 | 方法级覆盖率百分比、S/N/M 统计、排除类型说明、进度条 | 概述统计引用 |
21
+ | 3 | 按接口类型统计 | method/constructor/property/field/constant/enumValue/function/type/variable 分组覆盖率 | 辅助参考 |
22
+ | 4 | 类级覆盖率 | 每个类/接口的覆盖统计(按覆盖率升序) | 功能域划分参考 |
23
+ | 5 | 未覆盖接口详情 | 按类分组的未覆盖接口清单 | 附录数据源(`uncoveredList`) |
24
+ | 6 | 已覆盖接口详情 | 按类分组的已覆盖接口(含签名、覆盖文件) | **签名来源 + 映射关系**(`coveredList`) |
25
+ | 7 | 文件覆盖详情 | 每个 Demo 文件覆盖的接口列表 | **Demo 单元清单**(`demoFileMap`) |
26
+
27
+ ---
28
+
29
+ ## 3. 关键章节的精确格式
30
+
31
+ ### 3.1 覆盖率总览
32
+
33
+ ```markdown
34
+ ### 方法级覆盖率: 76.92% (良好)
35
+
36
+ | 统计项 | 数量 |
37
+ |--------|------|
38
+ | 类/接口总数 (S) | 3 |
39
+ | 方法/属性总数 (N) | 13 |
40
+ | 已覆盖 (M) | 10 |
41
+ | 未覆盖 | 3 |
42
+ | 排除类型 | 常量 (constant) / 枚举值 (enumValue) / 构造函数 (constructor) / 类型别名 (type) / 框架方法 (createState) / Object 内置方法 (hashCode/toString/noSuchMethod/runtimeType) |
43
+ ```
44
+
45
+ **提取**:N(分母)、M(已覆盖数)、方法级覆盖率百分比 → 用于输出文档概述与 Demo 总览。
46
+
47
+ ### 3.2 未覆盖接口详情
48
+
49
+ ```markdown
50
+ ### 1. VideoPlayerController (3 个未覆盖)
51
+
52
+ | # | 接口 | 类型 | 静态 | 参数 | 返回类型 | 说明 |
53
+ |---|------|------|------|------|----------|------|
54
+ | 1 | `seekTo` | method | 否 | positionMs: int | void | 跳转到指定时间位置 |
55
+ ```
56
+
57
+ - 按类分组,组标题格式 `### {序号}. {类名} ({N} 个未覆盖)`;顶层函数/变量归入 `(顶层)` 组
58
+ - **提取**:接口名、类型、静态、参数、返回类型、说明 → `uncoveredList`(附录直接复用此表格式)
59
+
60
+ ### 3.3 已覆盖接口详情
61
+
62
+ ```markdown
63
+ ### 1. VideoPlayerController
64
+
65
+ | # | 接口 | 类型 | 静态 | 签名 | 覆盖文件 |
66
+ |---|------|------|------|------|----------|
67
+ | 1 | `initialize` | method | 否 | `initialize(): Future<void>` | `example/lib/video_demo_page.dart` |
68
+ ```
69
+
70
+ - 按类分组;**签名**列为 Demo 描述"对应函数接口"的唯一来源
71
+ - **覆盖文件**列:最多显示 3 个文件(反引号包裹、逗号分隔),超出部分显示 `+N` → 接口→文件映射的正向来源
72
+
73
+ ### 3.4 文件覆盖详情
74
+
75
+ ```markdown
76
+ | # | 文件 | 覆盖接口数 | 覆盖的接口 |
77
+ |---|------|-----------|-----------|
78
+ | 1 | `example/lib/video_demo_page.dart` | 6 | `initialize`, `play`, `pause`, `addListener`, `removeListener`, `dispose` |
79
+ ```
80
+
81
+ - 按覆盖接口数降序;每个文件至少 1 个覆盖接口(无覆盖的文件不出现)
82
+ - **覆盖的接口**列:最多显示 10 个,超出显示 `... (+N)` → Demo 单元清单来源
83
+
84
+ ---
85
+
86
+ ## 4. 解析步骤
87
+
88
+ ```
89
+ 1. 读入报告全文(read_file)
90
+ 2. 解析"基本信息" → 核对库名与 libName
91
+ 3. 解析"覆盖率总览" → 记录 S/N/M、方法级覆盖率
92
+ 4. 解析"已覆盖接口详情" → 逐行提取:
93
+ { 接口名, 类型, 静态, 签名, 覆盖文件[] } → coveredList
94
+ 5. 解析"未覆盖接口详情" → 逐行提取:
95
+ { 接口名, 类型, 静态, 参数, 返回类型, 说明, 所属类 } → uncoveredList
96
+ 6. 解析"文件覆盖详情" → 逐行提取:
97
+ { 文件, 覆盖接口数, 接口列表 } → demoFileMap(初始,可能被截断)
98
+ 7. 截断重建(见 §5)→ 完整 demoFileMap
99
+ 8. 一致性核对:Σ(demoFileMap 各文件接口数) 与各接口覆盖文件数对账
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 5. 截断重建规则
105
+
106
+ ### 5.1 两处截断
107
+
108
+ | 位置 | 规则 | 表现 |
109
+ |------|------|------|
110
+ | 文件覆盖详情 · 覆盖的接口 | 每文件最多 10 个 | `... (+5)` |
111
+ | 已覆盖接口详情 · 覆盖文件 | 每接口最多 3 个 | `+2` |
112
+
113
+ ### 5.2 交叉重建算法
114
+
115
+ ```
116
+ 对 demoFileMap 中每个出现 "... (+N)" 的文件 F:
117
+ 遍历 coveredList 中每个接口 I:
118
+ 若 I.覆盖文件(含 +N 展开前的显式部分)包含 F → 将 I 归入 F 的接口集
119
+ 若归集数量 < 覆盖接口数(列值)→ 存在未知归属,执行 5.3 补救
120
+ ```
121
+
122
+ ### 5.3 grep 补救(仅限截断导致的归属不确定)
123
+
124
+ ```bash
125
+ # 对归属不确定的接口名,在 Demo 文件中确认是否调用
126
+ grep -n "接口名" "{demoDir}/{文件}"
127
+ ```
128
+
129
+ > ⚠️ 边界:grep 仅用于确认"接口是否出现在该文件",**不得**展开为源码阅读或补充报告外信息(接口签名、参数默认值等仍以报告为准)。
130
+
131
+ ---
132
+
133
+ ## 6. 特殊标记处理
134
+
135
+ | 标记 | 位置 | 含义 | 处理 |
136
+ |------|------|------|------|
137
+ | `*所有接口均已覆盖!*` | 未覆盖接口详情 | 无未覆盖接口 | 附录输出"无未覆盖接口" |
138
+ | `*暂无已覆盖接口*` | 已覆盖接口详情 | 无任何覆盖 | **终止**:无 Demo 可描述 |
139
+ | `(顶层)` 分组 | 已覆盖/未覆盖详情 | 全局函数/变量(无所属类) | 正常解析,类名记为空 |
140
+ | `不计入覆盖率` 备注 | 按接口类型统计 | constant/enumValue/constructor/type 被排除 | 这些接口不进入任何描述/矩阵 |
141
+
142
+ ---
143
+
144
+ ## 7. 统计口径(对齐规则)
145
+
146
+ 以下接口**不计入**覆盖率分母,同样**不得出现**在 Demo 描述列表、映射矩阵中:
147
+
148
+ | 排除类型 | 理由 |
149
+ |----------|------|
150
+ | `constant`(const/final 常量) | 低价值,不为纯常量类生成"常量展示页" |
151
+ | `enumValue`(枚举常量) | 同上 |
152
+ | `constructor`(构造函数) | Demo 中常通过间接方式获得对象 |
153
+ | `type`(typedef 类型别名) | 非可调用接口 |
154
+ | `createState` | 框架生命周期方法 |
155
+ | `hashCode`/`toString`/`noSuchMethod`/`runtimeType` | Object 基类内置成员 |
156
+
157
+ 生成代码排除:`.g.dart` / `.freezed.dart` 生成文件的接口不计入,报告中不会出现。
158
+
159
+ ---
160
+
161
+ ## 8. 报告可信度边界(解读须知)
162
+
163
+ 报告基于正则匹配,存在固有精度边界,解析时留意:
164
+
165
+ | 场景 | 方向 | 影响 | 处理 |
166
+ |------|------|------|------|
167
+ | 方法 tear-off(`final f = obj.method;`) | 低估 | 实际调用未计入 | 覆盖率异常低时按 flutter-library-demo-coverage Phase 3 交叉验证 |
168
+ | 动态调用(`Function.apply`/反射) | 低估 | 同上 | 同上 |
169
+ | 多级链式(`A().b().c()` 中 `c` 非 A 直接成员) | 低估 | 同上 | 同上 |
170
+ | 命名参数兜底(`propertyName:` 同名误判) | 高估 | 类级覆盖率接近 100% 时可能有误报 | 抽样核对可疑接口 |
171
+
172
+ **触发交叉验证的条件**(源自 flutter-library-demo-coverage Phase 3):
173
+ - 方法级覆盖率 < 10% 或 = 0%,且 `example/lib` 确有 `import 'package:{包名}/...'`
174
+ - 快速诊断口诀:"import 有、覆盖无 → 查 import 是否带 `as` 别名或 `show` 列表;部分漏、变量追踪失败 → 查变量是否声明为 `dynamic`/复杂表达式赋值"
@@ -0,0 +1,162 @@
1
+ # 示例:覆盖率报告 → Demo 描述文档
2
+
3
+ 本示例展示使用 `flutter-demo-doc-generator` 技能基于 Demo 覆盖率报告(`flutter-library-demo-coverage` 产物)生成 Demo 描述文档的完整过程。
4
+
5
+ > 📌 注意:以下库与接口均为示范用途,实际生成时严格依据真实覆盖率报告。
6
+
7
+ ---
8
+
9
+ ## 1. 输入:Demo 覆盖率报告(节选)
10
+
11
+ ```markdown
12
+ # flutter_video_player Demo 覆盖率分析报告
13
+
14
+ ## 基本信息
15
+
16
+ | 属性 | 值 |
17
+ |------|----|
18
+ | 库名 | `flutter_video_player` |
19
+ | 源文件数 | 3 |
20
+ | 生成时间 | 2026-09-05 ... |
21
+
22
+ ## 覆盖率总览
23
+
24
+ ### 方法级覆盖率: 76.92% (良好)
25
+
26
+ | 统计项 | 数量 |
27
+ |--------|------|
28
+ | 类/接口总数 (S) | 3 |
29
+ | 方法/属性总数 (N) | 13 |
30
+ | 已覆盖 (M) | 10 |
31
+ | 未覆盖 | 3 |
32
+ | 排除类型 | 常量 (constant) / 枚举值 (enumValue) / 构造函数 (constructor) / ... |
33
+
34
+ ## 类级覆盖率
35
+
36
+ | # | 类名 | 总数 | 已覆盖 | 未覆盖 | 覆盖率 | 状态 |
37
+ |---|------|------|--------|--------|--------|------|
38
+ | 1 | `VideoPlayerController` | 9 | 6 | 3 | 66.67% | ⚠️ 一般 |
39
+ | 2 | `VideoPlayerManager` | 2 | 2 | 0 | 100% | ✅ 优秀 |
40
+ | 3 | `(顶层)` | 2 | 2 | 0 | 100% | ✅ 优秀 |
41
+
42
+ ## 未覆盖接口详情
43
+
44
+ ### 1. VideoPlayerController (3 个未覆盖)
45
+
46
+ | # | 接口 | 类型 | 静态 | 参数 | 返回类型 | 说明 |
47
+ |---|------|------|------|------|----------|------|
48
+ | 1 | `seekTo` | method | 否 | positionMs: int | void | 跳转到指定时间位置(毫秒) |
49
+ | 2 | `currentPosition` | property | 否 | — | int | 当前播放位置(毫秒) |
50
+ | 3 | `duration` | property | 否 | — | int | 视频总时长(毫秒),未初始化时返回 0 |
51
+
52
+ ## 已覆盖接口详情
53
+
54
+ ### 1. VideoPlayerController
55
+
56
+ | # | 接口 | 类型 | 静态 | 签名 | 覆盖文件 |
57
+ |---|------|------|------|------|----------|
58
+ | 1 | `initialize` | method | 否 | `initialize(): Future<void>` | `example/lib/video_demo_page.dart` |
59
+ | 2 | `play` | method | 否 | `play(): void` | `example/lib/video_demo_page.dart` |
60
+ | 3 | `pause` | method | 否 | `pause(): void` | `example/lib/video_demo_page.dart` |
61
+ | 4 | `addListener` | method | 否 | `addListener(listener: VoidCallback): void` | `example/lib/video_demo_page.dart` |
62
+ | 5 | `removeListener` | method | 否 | `removeListener(listener: VoidCallback): void` | `example/lib/video_demo_page.dart` |
63
+ | 6 | `dispose` | method | 否 | `dispose(): Future<void>` | `example/lib/video_demo_page.dart` |
64
+
65
+ ### 2. VideoPlayerManager
66
+
67
+ | # | 接口 | 类型 | 静态 | 签名 | 覆盖文件 |
68
+ |---|------|------|------|------|----------|
69
+ | 1 | `setVolume` | method | 是 | `setVolume(volume: double): void` | `example/lib/volume_demo_page.dart` |
70
+ | 2 | `volume` | property | 是 | `volume: double` | `example/lib/volume_demo_page.dart` |
71
+
72
+ ### 3. (顶层)
73
+
74
+ | # | 接口 | 类型 | 静态 | 签名 | 覆盖文件 |
75
+ |---|------|------|------|------|----------|
76
+ | 1 | `isHardwareDecodingSupported` | function | — | `isHardwareDecodingSupported(): bool` | `example/lib/env_check_page.dart` |
77
+ | 2 | `getSDKVersion` | function | — | `getSDKVersion(): String` | `example/lib/env_check_page.dart` |
78
+
79
+ ## 文件覆盖详情
80
+
81
+ | # | 文件 | 覆盖接口数 | 覆盖的接口 |
82
+ |---|------|-----------|-----------|
83
+ | 1 | `example/lib/video_demo_page.dart` | 6 | `initialize`, `play`, `pause`, `addListener`, `removeListener`, `dispose` |
84
+ | 2 | `example/lib/volume_demo_page.dart` | 2 | `setVolume`, `volume` |
85
+ | 3 | `example/lib/env_check_page.dart` | 2 | `isHardwareDecodingSupported`, `getSDKVersion` |
86
+ ```
87
+
88
+ ---
89
+
90
+ ## 2. 输出:flutter_video_playerFlutter测试demo描述.md
91
+
92
+ ```markdown
93
+ # flutter_video_player Flutter 测试 Demo 描述文档
94
+
95
+ ## 概述
96
+
97
+ 本文档基于 `flutter_video_player` 库的 Demo 覆盖率报告(`02-flutter_video_player-Demo覆盖率报告.md`)生成,
98
+ 以 Demo 文件为单位描述各 Demo 覆盖的接口能力,供 QA 与开发者了解 Demo 验证范围并参考实现/验证 Demo 页面。
99
+
100
+ > **数据来源**:Demo 覆盖率报告(方法级覆盖率 76.92%,已覆盖 10/13 个接口)
101
+ >
102
+ > **说明**:步骤与预期结果为基于接口签名的验证设计,实际 Demo 实现以源码为准。
103
+
104
+ ## Demo 总览
105
+
106
+ | Demo 数量 | 覆盖接口数量 | 生成日期 |
107
+ |----------|------------|---------|
108
+ | 3 个 | 10 个 | 2026-09-05 |
109
+
110
+ ## 测试 Demo 描述列表
111
+
112
+ | 序号 | 测试 Demo 名称 | 测试 Demo 描述 | 测试 Demo 步骤 | 测试 Demo 预期结果 | 对应函数接口 | 源码位置 |
113
+ |-----|--------------|--------------|--------------|-----------------|------------|---------|
114
+ | 1 | 控制器生命周期与播放控制Demo | 覆盖 `VideoPlayerController` 的完整生命周期(初始化、监听注册/注销、释放)与播放/暂停控制,共 6 个接口。演示"初始化 → 播放控制 → 释放"的完整调用链路。 | 1. 创建 StatefulWidget Demo 页面,声明状态变量 `VideoPlayerController? _controller`、`String _status = '未初始化'`、`int _initCallCount = 0`、`int _initDoneCount = 0`,添加"初始化""播放""暂停""释放"按钮及状态/双计数器 Text 展示区。<br>2. 点击"初始化":`setState(() { _initCallCount++; _status = '加载中'; })`,随后 `await controller.initialize()`,完成后 `setState(() { _initDoneCount++; _status = '已就绪'; })`。<br>3. 点击"播放":调用 `controller.play()`,在状态监听回调 `addListener` 注册的 listener 中 `setState(() { _status = '播放中'; })`。<br>4. 点击"暂停":调用 `controller.pause()`,listener 回调触发 `setState(() { _status = '已暂停'; })`。<br>5. 点击"释放":先 `removeListener` 注销监听,再 `await controller.dispose()`,完成后 `setState(() { _controller = null; _status = '已释放'; })`。<br>6. 验证区展示 `Text('初始化调用: $_initCallCount')` 与 `Text('初始化完成: $_initDoneCount')`(均须在 `setState()` 中更新)。 | 1. 点击"初始化"后,状态 Text 更新为"加载中",`_initCallCount` 为 1;初始化完成后状态更新为"已就绪",`_initDoneCount` 为 1(两计数器相等表明异步链路正常)。<br>2. 点击"播放"/"暂停"后,listener 回调触发,状态 Text 相应更新为"播放中"/"已暂停"。<br>3. 点击"释放"后状态更新为"已释放",`dispose()` 无异常。<br>4. 全程无 Flutter 框架红屏报错。 | `initialize(): Future<void>`<br>`play(): void`<br>`pause(): void`<br>`addListener(listener: VoidCallback): void`<br>`removeListener(listener: VoidCallback): void`<br>`dispose(): Future<void>` | `example/lib/video_demo_page.dart` |
115
+ | 2 | 音量设置与回读Demo | 覆盖 `VideoPlayerManager` 的静态音量接口(设置与读取),共 2 个接口。验证音量参数范围(0.0~1.0)与读写一致性。 | 1. 创建 StatefulWidget Demo 页面,声明 `double _volume = 1.0`、`String _readback = ''`,添加音量 Slider(0.0~1.0)、"应用音量"按钮及回读 Text 展示区。<br>2. 拖动 Slider 调整目标音量,`setState(() { _volume = value; })`。<br>3. 点击"应用音量":调用 `VideoPlayerManager.setVolume(_volume)`(静态方法),随后 `setState(() { _readback = '当前音量: ${VideoPlayerManager.volume}'; })` 回读展示。 | 1. Slider 在 0.0~1.0 范围内可正常拖动。<br>2. 点击"应用音量"后,回读 Text 显示非空音量值,且与 Slider 设置值一致(读写一致性)。<br>3. 边界值 0.0 / 1.0 设置无异常抛出。 | `setVolume(volume: double): void`<br>`volume: double` | `example/lib/volume_demo_page.dart` |
116
+ | 3 | 环境检测与版本查询Demo | 覆盖两个顶层工具函数:硬件解码支持检测与 SDK 版本号查询。演示使用前置条件检查与平台信息展示。 | 1. 创建 StatefulWidget Demo 页面,声明 `String _sdkVersion = ''`、`bool? _hwSupported`,添加"检测硬件解码""查询版本号"按钮及结果 Text 展示区。<br>2. 点击"检测硬件解码":`setState(() { _hwSupported = isHardwareDecodingSupported(); })`,Text 依据返回值显示"支持 ✅"或"不支持 ❌"。<br>3. 点击"查询版本号":`setState(() { _sdkVersion = getSDKVersion(); })`,Text 显示"SDK 版本: {版本号}"。 | 1. 点击"检测硬件解码"后,Text 立即显示明确的支持/不支持文案,无异常。<br>2. 点击"查询版本号"后,Text 显示非空版本号字符串。<br>3. 两次操作均无框架红屏报错。 | `isHardwareDecodingSupported(): bool`<br>`getSDKVersion(): String` | `example/lib/env_check_page.dart` |
117
+
118
+ ## 接口映射矩阵
119
+
120
+ | 序号 | 接口名称 | 所在 Demo | 覆盖来源文件 |
121
+ |-----|---------|----------|------------|
122
+ | 1 | `initialize(): Future<void>` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
123
+ | 2 | `play(): void` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
124
+ | 3 | `pause(): void` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
125
+ | 4 | `addListener(listener: VoidCallback): void` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
126
+ | 5 | `removeListener(listener: VoidCallback): void` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
127
+ | 6 | `dispose(): Future<void>` | 控制器生命周期与播放控制Demo | `example/lib/video_demo_page.dart` |
128
+ | 7 | `setVolume(volume: double): void` | 音量设置与回读Demo | `example/lib/volume_demo_page.dart` |
129
+ | 8 | `volume: double` | 音量设置与回读Demo | `example/lib/volume_demo_page.dart` |
130
+ | 9 | `isHardwareDecodingSupported(): bool` | 环境检测与版本查询Demo | `example/lib/env_check_page.dart` |
131
+ | 10 | `getSDKVersion(): String` | 环境检测与版本查询Demo | `example/lib/env_check_page.dart` |
132
+
133
+ ## 附录:未覆盖接口清单
134
+
135
+ 以下接口在 Demo 覆盖率报告中被标记为未覆盖(3 个),供后续 Demo 补全参考:
136
+
137
+ | # | 接口 | 类型 | 静态 | 参数 | 返回类型 | 说明 |
138
+ |---|------|------|------|------|----------|------|
139
+ | 1 | `seekTo` | method | 否 | positionMs: int | void | 跳转到指定时间位置(毫秒) |
140
+ | 2 | `currentPosition` | property | 否 | — | int | 当前播放位置(毫秒) |
141
+ | 3 | `duration` | property | 否 | — | int | 视频总时长(毫秒),未初始化时返回 0 |
142
+ ```
143
+
144
+ ---
145
+
146
+ ## 3. 关键生成规则说明
147
+
148
+ 上述示例体现了以下规则的应用:
149
+
150
+ 1. **文件 → Demo 单元**:报告"文件覆盖详情"中 3 个 Demo 文件对应 3 条描述,无跨文件合并、无遗漏。
151
+
152
+ 2. **签名忠实于报告**:"对应函数接口"列的签名逐字取自报告"已覆盖接口详情"(如 `addListener(listener: VoidCallback): void`),参数类型未做任何改写。
153
+
154
+ 3. **双计数器设计**:"控制器初始化"涉及 `initialize(): Future<void>` 异步链路,设计了 `_initCallCount`/`_initDoneCount` 双计数器,均要求 `setState()` 更新,用于诊断 Future 链路完整性。
155
+
156
+ 4. **无死按钮**:每个按钮(初始化/播放/暂停/释放/应用音量/检测/查询)都有对应的可观测预期结果。
157
+
158
+ 5. **未覆盖接口仅入附录**:`seekTo`、`currentPosition`、`duration` 未出现在任何 Demo 描述中,仅在附录列出供补全参考——本技能不为未覆盖接口生成 Demo 描述。
159
+
160
+ 6. **口径对齐**:`PlayerConfig` 构造函数、`PlayerState` 枚举值被报告排除(不计入分母),因此描述与矩阵中均不出现。
161
+
162
+ 7. **来源声明准确**:概述声明"基于 Demo 覆盖率报告生成"并引用统计(76.92%、10/13),同时声明步骤为验证设计、实际实现以源码为准。
@@ -0,0 +1,123 @@
1
+ # MCP 工具使用指南
2
+
3
+ > 本文档定义覆盖率分析工具的调用方式、参数与已知限制。覆盖率分析能力复用 `flutter-library-demo-coverage` 技能,本技能不重复实现。
4
+
5
+ ---
6
+
7
+ ## 1. 工具总览
8
+
9
+ | 工具 / 脚本 | 调用方式 | 在本技能中的用途 | 调用阶段 |
10
+ |-------------|----------|-----------------|----------|
11
+ | `script_flutter_analyze_demo_coverage` | MCP 工具(Gateway) | 生成 Demo 覆盖率报告(核心输入) | Phase 1(报告缺失时) |
12
+ | `flutter-analyze-demo-coverage.cjs` | CLI 直调(node) | 同上(无 Gateway 时的等价方式) | Phase 1(报告缺失时) |
13
+ | `script_flutter_extract_interfaces` | MCP 工具 | 生成 `interface-spec.json`(供覆盖率脚本的 `--spec` 参数复用) | 可选 |
14
+ | `script_flutter_render_spec_doc` | MCP 工具 | 渲染人类可读接口说明书(辅助理解接口语义) | 可选 |
15
+
16
+ ---
17
+
18
+ ## 2. 覆盖率分析(核心工具)
19
+
20
+ ### 2.1 MCP 工具调用
21
+
22
+ ```
23
+ 调用 script_flutter_analyze_demo_coverage:
24
+ - libroot: {{libroot}}
25
+ - spec: {{spec}}(可选,已有 interface-spec.json 时传入)
26
+ - output: {{libroot}}/02-{libName}-Demo覆盖率报告.md
27
+ ```
28
+
29
+ ### 2.2 CLI 直调(等价方式)
30
+
31
+ ```bash
32
+ node "{{skillDir}}/../../../MCP/scripts/flutter-analyze-demo-coverage.cjs" \
33
+ --libroot "{{libroot}}" \
34
+ --spec "{{specPath}}" \
35
+ --output "{{libroot}}/02-{{libName}}-Demo覆盖率报告.md"
36
+ ```
37
+
38
+ 其中 `{{skillDir}}` = 本 SKILL.md 所在目录。
39
+
40
+ ### 2.3 参数说明
41
+
42
+ | 参数 | 必填 | 默认值 | 说明 |
43
+ |------|------|--------|------|
44
+ | `--libroot` | ✅(与 --spec 至少其一) | — | 库根目录(含 `lib/` 和 `example/`,支持 monorepo 自动定位主包) |
45
+ | `--spec` | ❌ | 自动从源码提取 | 已有 `interface-spec.json` 路径(`flutter-interface` 技能产物) |
46
+ | `--output` | ❌ | `02-{库名}-Demo覆盖率报告.md` | 报告输出路径 |
47
+ | `--title` | ❌ | `{库名} Demo 覆盖率分析报告` | 报告标题 |
48
+ | `--lib` | ❌ | 从 `pubspec.yaml` 提取 | 包名覆盖(import 匹配用) |
49
+ | `--src` | ❌ | 自动探测 `example/lib` | Demo 源码目录覆盖 |
50
+
51
+ ### 2.4 脚本自动完成的事
52
+
53
+ 1. 获取接口规格(`--spec` JSON 或源码自动提取)
54
+ 2. 定位 Demo 源码目录(`example/lib` → `examples/lib` → `demo/lib`),递归扫描 `.dart`(排除 `.g.dart`/`.freezed.dart` 及平台目录)
55
+ 3. 解析 import(`show`/`hide`/`as` 别名)并追踪实例变量 → 类名映射
56
+ 4. 正则匹配覆盖率(静态/构造/枚举值/实例方法/链式调用)
57
+ 5. 对象字面量/命名参数兜底、aliased import 兜底
58
+ 6. 过滤低价值接口(constant/enumValue/constructor/type 不计入分母)
59
+ 7. 直接生成最终 Markdown 报告(无中间文件)
60
+
61
+ ### 2.5 退出码处理
62
+
63
+ | 退出码 | 处理 |
64
+ |--------|------|
65
+ | `0` | 成功,进入报告解析(Phase 2) |
66
+ | 非 `0` | **终止**,标注 `状态: 失败`;报 `Demo 源码目录不存在` 时先确认 `libroot` 下有 `example/lib` 等目录 |
67
+
68
+ ---
69
+
70
+ ## 3. 已知匹配限制(报告解读必读)
71
+
72
+ 报告基于正则匹配,存在以下精度边界:
73
+
74
+ | 限制场景 | 方向 | 说明 |
75
+ |----------|------|------|
76
+ | 方法 tear-off:`final f = obj.method;` | 低估 | 不带调用括号的方法引用无法识别 |
77
+ | 动态调用:`Function.apply`、反射 | 低估 | 无法静态识别 |
78
+ | 多级链式:`A().b().c()` 中 `c()` 非 `A` 直接成员 | 低估 | 中间返回类型不可见 |
79
+ | 命名参数兜底:`propertyName:` 同名属性 | **高估** | 类级覆盖率接近 100% 时建议抽样核对 |
80
+
81
+ **交叉验证触发条件**(覆盖率 < 10% 或 = 0% 且 Demo 确有库 import):
82
+
83
+ ```bash
84
+ # 对报告中"未覆盖"的接口,统计真实调用数比对
85
+ grep -rh "\.方法名(" example/lib/ --include="*.dart" | wc -l
86
+ ```
87
+
88
+ 诊断口诀:"import 有、覆盖无 → 查 import 是否带 `as` 别名或 `show` 列表;部分漏、变量追踪失败 → 查变量是否声明为 `dynamic`/复杂表达式赋值"。
89
+
90
+ > 详细解读规则参见 [覆盖率报告解析指南](COVERAGE_REPORT_PARSING.md) §8
91
+
92
+ ---
93
+
94
+ ## 4. 接口规格提取(可选)
95
+
96
+ 覆盖率脚本未传 `--spec` 时会自动从源码提取接口规格,通常无需单独调用 `script_flutter_extract_interfaces`。仅当:
97
+
98
+ - 需要 `interface-spec.json` 作为独立产物留存,或
99
+ - monorepo 多子包场景需先确认主包规格
100
+
101
+ 时调用:
102
+
103
+ ```
104
+ 调用 script_flutter_extract_interfaces:
105
+ - libroot: {{libroot}}
106
+ - output: {{libroot}}/interface-spec.json
107
+ ```
108
+
109
+ 产物可同时供 `flutter-library-demo-coverage`(`--spec` 参数)与本技能复核接口签名使用。
110
+
111
+ ---
112
+
113
+ ## 5. 接口说明书渲染(可选)
114
+
115
+ 需要阅读接口的详细语义(参数含义、枚举取值)辅助编写 Demo 描述时:
116
+
117
+ ```
118
+ 调用 script_flutter_render_spec_doc:
119
+ - spec: {{libroot}}/interface-spec.json
120
+ - output: {{libroot}}/{libName}接口规格说明.md
121
+ ```
122
+
123
+ 本技能主流程不依赖该产物,仅作辅助阅读。
@@ -0,0 +1,190 @@
1
+ # 输出格式规范
2
+
3
+ > 本文档定义 Demo 描述文档的输出结构、表格格式和各字段填写规范,是 SKILL.md Phase 5 的详细展开。
4
+
5
+ ---
6
+
7
+ ## 1. 输出文件命名
8
+
9
+ **文件名**:`{库名}Flutter测试demo描述.md`
10
+
11
+ - 库名从 `pubspec.yaml` 的 `name` 字段提取(与覆盖率报告"基本信息"的库名一致)
12
+ - 放置在 `libroot` 目录下(或 `output` 参数指定路径)
13
+ - 示例:`flutter_video_player` 库 → `flutter_video_playerFlutter测试demo描述.md`
14
+
15
+ ---
16
+
17
+ ## 2. 文档结构
18
+
19
+ ```markdown
20
+ # {库名} Flutter 测试 Demo 描述文档
21
+
22
+ ## 概述
23
+
24
+ 本文档基于 `{库名}` 库的 Demo 覆盖率报告(`{reportPath}`)生成,以 Demo 文件为单位描述
25
+ 各 Demo 覆盖的接口能力,供 QA 与开发者了解 Demo 验证范围并参考实现/验证 Demo 页面。
26
+
27
+ > **数据来源**:Demo 覆盖率报告 `{reportPath}`(方法级覆盖率 {M}%,已覆盖 {M'}/{N} 个接口)
28
+ >
29
+ > **说明**:步骤与预期结果为基于接口签名的验证设计,实际 Demo 实现以源码为准。
30
+
31
+ ## Demo 总览
32
+
33
+ | Demo 数量 | 覆盖接口数量 | 生成日期 |
34
+ |----------|------------|---------|
35
+ | N 个 | M 个 | YYYY-MM-DD |
36
+
37
+ ## 测试 Demo 描述列表
38
+
39
+ | 序号 | 测试 Demo 名称 | 测试 Demo 描述 | 测试 Demo 步骤 | 测试 Demo 预期结果 | 对应函数接口 | 源码位置 |
40
+ |-----|--------------|--------------|--------------|-----------------|------------|---------|
41
+ | 1 | ... | ... | ... | ... | ... | ... |
42
+
43
+ ## 接口映射矩阵
44
+
45
+ | 序号 | 接口名称 | 所在 Demo | 覆盖来源文件 |
46
+ |-----|---------|----------|------------|
47
+ | 1 | ... | ... | ... |
48
+
49
+ ## 附录:未覆盖接口清单
50
+
51
+ (来自覆盖率报告"未覆盖接口详情",供 Demo 补全参考)
52
+
53
+ | # | 接口 | 类型 | 静态 | 参数 | 返回类型 | 说明 |
54
+ |---|------|------|------|------|----------|------|
55
+ | 1 | ... | ... | ... | ... | ... | ... |
56
+ ```
57
+
58
+ **章节取舍规则**:概述、Demo 总览、描述列表、映射矩阵**必选**;附录在未覆盖接口为 0 时输出"所有接口均已覆盖"。
59
+
60
+ ---
61
+
62
+ ## 3. 描述列表字段规范(七列表格)
63
+
64
+ ### 3.1 序号
65
+
66
+ - 从 1 开始的自增整数,全文档唯一且连续
67
+ - 描述列表与映射矩阵分别独立编号
68
+
69
+ ### 3.2 测试 Demo 名称
70
+
71
+ - 简洁明了,不超过 20 字
72
+ - 格式:`[功能动词/名词][操作对象][场景]Demo`
73
+ - 提炼来源优先级:Demo 文件覆盖接口的功能簇 > 文件名语义 > 所属类名语义
74
+ - 避免泛化词语(如"基础Demo"、"测试Demo")
75
+ - 同一文件超量拆分为多条时,名称须体现功能簇差异(如"播放控制Demo"、"状态监听Demo")
76
+
77
+ ### 3.3 测试 Demo 描述
78
+
79
+ - 2-4 句话
80
+ - 必须包含:该 Demo(文件)覆盖的接口能力范围、验证目的
81
+ - 可选包含:接口间的调用关系(如"初始化 → 操作 → 释放"完整链路)
82
+ - 涉及多个接口的 Demo 建议注明接口数量与功能域
83
+
84
+ ### 3.4 测试 Demo 步骤
85
+
86
+ - 编号列表,每步骤一行,以 Flutter Demo 页面(StatefulWidget)为视角
87
+ - 步骤维度:页面构建(State 类状态变量、UI 组件)、交互触发(按钮/输入框)、接口调用(含参数)、`setState()` 更新、结果展示(Text/展示区)
88
+ - 接口调用与报告签名一致:`调用 xxx(参数: 类型)`;参数类型不得篡改,无默认值信息时不得编造
89
+ - 异步链路步骤按双计数器模式编写(见 §4.3)
90
+
91
+ ### 3.5 测试 Demo 预期结果
92
+
93
+ - 编号列表,具体可观测指标
94
+ - 表述维度:UI 展示内容、返回值格式/范围、状态变化、无异常崩溃
95
+ - 每个接口调用步骤至少对应一条预期结果(禁止死按钮)
96
+
97
+ ### 3.6 对应函数接口
98
+
99
+ - 列出该 Demo 覆盖的所有接口签名,**取自报告"已覆盖接口详情"的签名列**,逐字一致
100
+ - 格式:`` `方法名(参数类型): 返回类型` ``;属性/字段格式:`` `属性名: 类型` ``
101
+ - 多个接口用 `<br>` 分隔(表格内换行)
102
+ - 不得出现报告排除类型(constant/enumValue/constructor/type)与 Object 内置成员
103
+
104
+ ### 3.7 源码位置
105
+
106
+ - 格式:`` {Demo 文件路径} ``(报告"文件覆盖详情"的文件列,含 `example/lib/` 前缀)
107
+ - 超量拆分为多条描述时,各条源码位置相同(同一文件),可在描述中注明功能簇
108
+
109
+ ---
110
+
111
+ ## 4. 验证设计规则(步骤与预期结果强制规则)
112
+
113
+ ### 4.1 可验证性前置规则
114
+
115
+ 为任何接口编写步骤前,先判断该接口能否产生可观测输出:
116
+
117
+ | 情况 | 处理方式 |
118
+ |------|----------|
119
+ | 有直接返回值、状态变更或 Widget 更新 | 正常作为主步骤,预期结果描述可观测指标 |
120
+ | 依赖平台事件回调,且该事件在测试设备上已知不触发 | 不作为主步骤;标注「平台限制」,建议通过日志验证 |
121
+ | 无任何可观测输出(无返回值、无回调) | 合并到相关流程 Demo,通过其他接口的状态变化间接验证 |
122
+
123
+ ### 4.2 setState 强制规则
124
+
125
+ 步骤中包含「计数器(回调次数、调用次数)」或「状态标志(是否已初始化)」等运行时变化量时,必须注明:**该变量须在 `setState()` 中更新**——否则 Flutter 不触发重建,计数器恒显示初始值,验证逻辑失效。
126
+
127
+ ### 4.3 异步回调链双计数器
128
+
129
+ 涉及「调用库函数 → 等待回调/Future」的异步链路,必须设计双计数器:
130
+
131
+ | 计数器位置 | 变量名建议 | 含义 |
132
+ |-----------|----------|------|
133
+ | 调用/分发前(触发代码中) | `_xxxCallCount` | 调用动作的执行次数 |
134
+ | 回调内部(`onXxx` / `.then()` 中) | `_xxxCallbackCount` | 回调实际触发次数 |
135
+
136
+ - 两个计数器均在验证区展示(`Text` Widget)且通过 `setState()` 更新
137
+ - 诊断规则:`_callCount > 0` 且 `_callbackCount = 0` → 调用成功但回调未触发(回调注册/事件链问题);`_callCount = 0` → 触发逻辑未执行;两者相等且 > 0 → 链路正常
138
+
139
+ **步骤写作模板**:
140
+
141
+ ```
142
+ 1. 在 State 类中声明计数器:int _xxxCallCount = 0; int _xxxCallbackCount = 0;
143
+ 2. 触发按钮:setState(() => _xxxCallCount++),然后调用 xxx()
144
+ 3. 在回调/then 中:setState(() => _xxxCallbackCount++),更新其他 UI 状态
145
+ 4. 验证区域展示:Text('调用次数: $_xxxCallCount') 与 Text('回调次数: $_xxxCallbackCount')
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 5. 接口映射矩阵规范
151
+
152
+ ```markdown
153
+ | 序号 | 接口名称 | 所在 Demo | 覆盖来源文件 |
154
+ |-----|---------|----------|------------|
155
+ | 1 | `play(): void` | 播放控制Demo | `example/lib/video_demo_page.dart` |
156
+ | 2 | `initialize(): Future<void>` | 控制器初始化Demo | `example/lib/video_demo_page.dart` |
157
+ ```
158
+
159
+ **规则**:
160
+ - 每行一个已覆盖接口(计入统计口径),与报告"已覆盖接口详情"一一对应
161
+ - "所在 Demo"与描述列表中的 Demo 名称严格一致
162
+ - "覆盖来源文件"取自报告"覆盖文件"列(接口被多个文件覆盖时逐行列出或用"/"分隔 Demo 名)
163
+ - 超量拆分场景:接口归属拆分后的具体功能簇 Demo
164
+
165
+ ---
166
+
167
+ ## 6. 来源声明规则
168
+
169
+ 概述章节必须包含且仅包含真实使用的数据源:
170
+
171
+ | 场景 | 声明内容 |
172
+ |------|----------|
173
+ | 一致通用 | "基于 `{库名}` 库的 Demo 覆盖率报告(`{reportPath}`)生成" |
174
+ | 统计引用 | 方法级覆盖率、已覆盖数/总数(取自报告"覆盖率总览") |
175
+ | 设计性质声明 | "步骤与预期结果为基于接口签名的验证设计,实际 Demo 实现以源码为准" |
176
+
177
+ > ⚠️ 禁止声称"基于 Demo 源码分析生成"或"基于接口规格说明文档生成"——本文档的唯一数据源是覆盖率报告。
178
+
179
+ ---
180
+
181
+ ## 7. 表格内换行与内联格式
182
+
183
+ - 单元格内换行使用 `<br>` 标签
184
+ - 引用代码使用反引号:函数签名 `` `play(): void` ``、变量 `` `_status` ``、组件 `` `ElevatedButton` ``
185
+
186
+ **示例**:
187
+
188
+ ```markdown
189
+ | 1 | 播放控制Demo | 展示播放/暂停接口的调用与状态验证。 | 1. 构建页面,声明 `_playCallCount` 等状态变量<br>2. 点击"播放"按钮,`setState(() => _playCallCount++)` 后调用 `play()`<br>3. 验证区展示调用次数与状态 | 1. 点击后状态 Text 更新<br>2. 计数 +1<br>3. 无异常抛出 | `play(): void`<br>`pause(): void` | `example/lib/video_demo_page.dart` |
190
+ ```