improve codelens
This commit is contained in:
+116
-1
@@ -974,7 +974,8 @@ stale=true 并触发 follow-up。处理(按用户建议的扩展名白名单
|
||||
|
||||
- w3x 文件名启发式定向扫描(按约定后续再做)。
|
||||
- `AssetIdList` 等“任意资产 ID 列表”的引用语义建模。
|
||||
- Find All References 目前仍是全文搜索,未走索引(对应需求 P1 高效搜索)。
|
||||
- Find All References 已改为语义引用索引(第十八轮,2026-08-05,见
|
||||
`docs/features-reference-counts.md`);通用内容搜索与索引复用仍属 P1 远期。
|
||||
|
||||
---
|
||||
|
||||
@@ -1509,3 +1510,117 @@ XSD 模型中共 **371 处“子元素是 simple type”的声明(149 个不
|
||||
若 Corona 上“输入 C 后菜单出现慢”仍然明显,下一个瓶颈大概率是
|
||||
`getScope()` 每次文档版本变化都重建完整局部 include 链 / 逻辑树;本轮先把
|
||||
候选截断与类型过滤造成的“列表错误”修掉,局部 scope 缓存优化留作独立一轮。
|
||||
|
||||
---
|
||||
|
||||
## 二十三、问题分析(2026-08-05):FAR 把定义行算作“自引用”;CodeLens 漏掉 manifest 源引用
|
||||
|
||||
### 问题 1:Find All References 把 id 定义行也算进结果
|
||||
|
||||
**现象**:对任意资产执行 FAR,结果里包含它自己的 `id="..."` 定义行,看起来
|
||||
像“自己引用自己”;CodeLens 计数没有这个问题。
|
||||
|
||||
**根因**:VS Code 的 FAR 默认带 `context.includeDeclaration = true`,旧实现
|
||||
把定义位置附加进返回结果。语义反向索引本身不含 id 定义点(records 提取时
|
||||
已排除),CodeLens 只读反向索引,所以两者不一致。
|
||||
|
||||
**修复**:`findReferenceLocations` 不再附加定义位置,无论 `includeDeclaration`
|
||||
取值;FAR 结果与 CodeLens 计数严格一致。
|
||||
|
||||
### 问题 2:CodeLens 不显示 manifest 定义的引用,FAR 却显示
|
||||
|
||||
**现象**:打开 SageXml 原版源码时,CodeLens 显示 0 引用,但从该资产执行
|
||||
FAR 能看到引用。
|
||||
|
||||
**根因**:反向索引的站点挂在“实际解析到的定义”上。当 SageXml 源码不在
|
||||
include 遍历里时,引用只解析到 manifest 定义(如 `static.manifest` 条目),
|
||||
站点挂在 manifest key;CodeLens 用“当前文档定义 key”精确查表所以是 0,
|
||||
FAR 把同 id/同类型的 manifest 定义也合并进来所以能看到。
|
||||
|
||||
**修复**:新增 `referenceSitesForDefinition`:除了精确 key,还把
|
||||
`manifestSource` 可解析到当前打开文件的 manifest 定义的站点并入计数——
|
||||
语义上把“manifest 引用”视作“SageXml 源码对该 asset 的引用”
|
||||
(Go to Definition 本来就会把 manifest 定义映射到 SageXml 源码)。
|
||||
|
||||
**验证**:AttachTest 中 326 个带引用的 manifest 定义此前全部没有对应
|
||||
`origin: "sdk"` 定义(源码未遍历),现在打开对应 SageXml 源码即可看到计数
|
||||
(如 `PlayerTemplate Allies` → 8 引用)。
|
||||
|
||||
### 举一反三的测试(146 → 147 全绿)
|
||||
|
||||
- `referenceProvider.test.mjs`:FAR 即使 `includeDeclaration = true` 也不返回
|
||||
定义行;从引用位置发起 FAR 结果一致;
|
||||
- `referenceIndex.test.mjs`:`referenceSitesForDefinition` 把 manifest 源
|
||||
站点并入 SageXml 源码定义,其他文件不串;
|
||||
- `codeLens.test.mjs`:打开 manifestSource 对应的源码文件时,CodeLens 显示
|
||||
manifest 定义上挂着的引用数。
|
||||
|
||||
版本 **0.1.16 → 0.1.17**。
|
||||
|
||||
---
|
||||
|
||||
## 二十四、问题分析(2026-08-06):引用索引与 records 缓存不同步 / 竞争
|
||||
|
||||
### 现象
|
||||
|
||||
Corona `Data/GlobalData/Weapon/Weapon_Allied.xml` 中的
|
||||
`AlliedCommandoDesertEaglesWarhead`(一个 WeaponTemplate)偶尔没有 CodeLens,
|
||||
FAR 显示无引用;它实际被同文件 WeaponTemplate 的 `ProjectileNugget
|
||||
WarheadTemplate="..."` 引用。该问题在移动硬盘重连 + 重新打开工作区 + 校验
|
||||
磁盘缓存 + 重新 indexing 之后出现;在 ProjectileNugget 里 Ctrl+点击一次后恢复;
|
||||
清缓存重载不复发。
|
||||
|
||||
### 调查
|
||||
|
||||
1. **模型核对**:`AlliedCommandoDesertEaglesWarhead` 的元素是
|
||||
`<WeaponTemplate>`,`ProjectileNuggetType@WarheadTemplate` 的 refType 是
|
||||
`WeaponTemplate`,语义匹配成立。
|
||||
2. **真实文件验证**:直接对 Weapon_Allied.xml 做 records 提取 + 反向索引,
|
||||
引用记录(line 1332)能正确挂到定义(line 1341)——**新鲜构建没有问题**。
|
||||
3. 因此问题不在提取/过滤逻辑,而在“引用索引与索引状态不同步”的缓存/竞争
|
||||
路径。
|
||||
|
||||
### 找到的不同步 / 竞争点
|
||||
|
||||
- **`buildReferences()` 读共享 recordsCache**(workspace 持有、跨重建复用),
|
||||
而不是 walk 实际消费的 records:
|
||||
- 外部盘重连 / 旧磁盘缓存条目“stat 全匹配但内容过时”(FAT32/exFAT 时间戳
|
||||
粒度 2s、同步工具保留 mtime、size 不变)→ 资产用旧 records 入库,而新
|
||||
引用缺失;watcher 事件在重连期间丢失时快照不会标 stale → 持久化问题;
|
||||
- 构建中途 watcher 失效、或 feature `readDom` 重写 recordsCache,都可能让
|
||||
快照的 references 与 assets 来自不同版本的 records。
|
||||
- **feature 在构建中调用 `readDom`**(定义跳转的精确定位)会改写同一个
|
||||
indexer 的 `files` / `recordsCache`,污染进行中的构建。
|
||||
- **force 重建(Re-index)之前只比 stat 信号**:stat 相同但内容不同的陈旧
|
||||
条目会被直接复用,只有清缓存才能修复。
|
||||
|
||||
### 修复
|
||||
|
||||
1. **构建期本地 records**:`ModIndexer.buildRecords` 记录本次 walk 实际消费的
|
||||
`{ file, records, recordsHash }`,`buildReferences()` 只从这里构建反向索引。
|
||||
中途失效 / feature 重读不再造成“资产在但引用缺失”。
|
||||
2. **构建期 readDom 闸门**:`assetDefLocation` 在 `ws.isBuilding` 时退化为
|
||||
行级位置,避免定义跳转改写进行中的构建。
|
||||
3. **force 重建内容校验**:full XML 的 records 缓存条目带 `contentHash`;
|
||||
`Re-index workspace` 对 stat 匹配的条目也读文件比对哈希,不一致才重解析
|
||||
(w3x 浅扫描不读,保持 2.6 GB 免读)。
|
||||
4. **打开文档自愈**:快照发布每文件 `recordsHashes`;CodeLens / FAR 对**已保存**
|
||||
文档比较当前文本的 records 哈希,不一致则定向 `invalidate` +
|
||||
`scheduleRebuild("records-desync")`。records 哈希忽略行尾/空白差异,
|
||||
未保存编辑不触发,避免误报和循环。
|
||||
5. **磁盘缓存 v2 → v3**:旧缓存没有哈希、无法校验/自愈,一次性重建后每文件
|
||||
都带哈希。
|
||||
|
||||
### 验证(147 → 151 全绿)
|
||||
|
||||
- 构建中途 invalidate 某文件的 recordsCache,最终快照仍保留该文件的引用;
|
||||
- force 重建:stat 全匹配但 contentHash 不同的条目被重新解析(trusted 路径
|
||||
仍复用缓存不读盘);
|
||||
- 自愈:records 哈希不一致时只对干净文件触发 invalidate + records-desync;
|
||||
- CodeLens 集成:打开文档与快照不同步时调度定向重建。
|
||||
|
||||
“Ctrl+点击后恢复”的精确时序无法在代码里复现;最可能是跳转前后恰好发生了一
|
||||
次重建(watcher 事件 / dirty-followup)。自愈检查让这类问题不再依赖巧合:
|
||||
只要文件被打开并触发 CodeLens / FAR,不一致就会被检测并定向修复。
|
||||
|
||||
版本 **0.1.17 → 0.1.18**。
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# 功能设计:引用计数、语义 Find All References 与未引用资产
|
||||
|
||||
> 状态:已实现(v0.1.16 起)。本文档记录需求分析结论、语义定义、数据流与
|
||||
> 已知边界;问题排查记录仍放在 `docs/analysis-issues.md`,功能设计单独成文。
|
||||
|
||||
## 一、需求与结论
|
||||
|
||||
原始需求:
|
||||
|
||||
1. 在每个顶部 asset 上显示它被引用了多少次,点击后直接打开“查找所有引用”,
|
||||
而不是必须通过右键菜单;
|
||||
2. 能查找“某一种类型中所有没被引用的顶部 asset”。
|
||||
|
||||
调研结论(2026-08-05):
|
||||
|
||||
- XSD 模型层面,292 个有模型类型的顶层资产中:73 个有类型化引用指向它们,
|
||||
28 个只能被 `inheritFrom` 指向,**191 个在模型里根本没有任何引用指向**
|
||||
(设置类、地图元数据、w3x 子结构等)。对这些类型,“0 引用”是唯一正常状态。
|
||||
- AttachTest 实测:625 个项目定义中 29% 是 0 引用、48% 是 1 引用。
|
||||
因此“所有资产一律显示计数”会制造大量噪音,也会让用户误以为资产是孤儿。
|
||||
- 结论:**计数按类型过滤**——只在“设计上应该被引用”的类型上显示
|
||||
(0 也显示,因为对 GameObject 这类类型 0 是有效信号);自动注册/结构类
|
||||
类型不显示。
|
||||
- 旧版 Find All References 是全文搜索(正则匹配 `"id"` / `>id<`),会把
|
||||
`id="X"` 定义本身、`EditorName="X"` 等非引用属性也算进去。计数如果和它
|
||||
同源,必然误导;如果不同源,点击后的结果又对不上。因此本轮把 FAR 一起
|
||||
升级为语义引用索引,计数与点击结果共用同一数据源。
|
||||
|
||||
## 二、语义定义:什么算一次“引用”
|
||||
|
||||
与补全 / hover / 跳转 / 诊断完全一致(`refs.ts` 是唯一判定来源):
|
||||
|
||||
- 带 `xas:refType` 的属性值(如 `CommandSet` → `LogicCommandSet`);
|
||||
- 带 `xas:refType` 的 simple-content 文本(如 `<CreateObject>ID</CreateObject>`);
|
||||
- `inheritFrom`(按元素自身类型过滤);
|
||||
- 无 `refType` 的 `isRef` 属性(按同名 ID 匹配任意声明类型)。
|
||||
|
||||
不算引用:
|
||||
|
||||
- 元素自己的 `id` 定义点(除非是 `RoadObject@id→Road` 这类跨类型 id 引用);
|
||||
- Poid 管线局部引用(`ModuleId`、`AttachModuleId`、`SoundRef` 等);
|
||||
- `$DEFINE` / `=` 常量值;
|
||||
- 枚举、文件路径、`Include@source` / `xi:include href`;
|
||||
- w3x 内部父子结构关系(`W3DMesh` 等靠结构归属,不走全局引用)。
|
||||
|
||||
引用索引按“类型 + id + 定义位置”精确归属,同名 ID 的不同类型定义互不串扰
|
||||
(`WeaponTemplate:X` 的引用不会计到 `GameObject:X` 头上)。
|
||||
|
||||
## 三、数据流
|
||||
|
||||
```
|
||||
parse DOM
|
||||
│ records.ts extractIndexRecords(parse, lineMap, text)
|
||||
▼
|
||||
IndexRecords.references[] 每文件紧凑记录(refType / selfType / value /
|
||||
│ 行号 / 起止偏移),随 records 缓存跨重建复用,
|
||||
│ 并持久化到磁盘缓存(缓存版本 v3,full XML
|
||||
│ 附带内容哈希;快照另发布每文件 records 哈希)
|
||||
▼
|
||||
indexer.ts buildReferences() 只解算本次 build 触及的文件,防止陈旧缓存泄漏
|
||||
│ referenceIndex.ts buildReferenceIndex()
|
||||
▼
|
||||
ModIndex.references Map<定义 key, ReferenceSite[]>
|
||||
├── CodeLens 计数(O(1) 查表)
|
||||
├── 语义 Find All References(返回精确位置)
|
||||
└── 未引用资产报告(0 引用 = 不在反向索引中)
|
||||
```
|
||||
|
||||
引用记录在解析期就把 `refType` / `selfType` 固化下来,反向索引构建时不需要
|
||||
再解析 DOM、也不需要上下文类型解析;只需对 `assetsById` 做一次查找并按类型
|
||||
过滤。快照发布时(XML 阶段 + art 阶段)各构建一次反向索引,Corona 规模下
|
||||
开销远小于 include 遍历。
|
||||
|
||||
反向索引只从**本次构建的 walk 实际消费的 records**(`ModIndexer.buildRecords`)
|
||||
构建,不读共享 recordsCache:中途 watcher 失效、或 feature 通过 `readDom`
|
||||
重读文件,都不会让“资产在但引用缺失”的快照出现。打开文档时 CodeLens / FAR
|
||||
还会比较当前文本的 records 哈希与快照,不一致就定向 invalidate 并触发
|
||||
`records-desync` 重建自愈(仅对已保存文档,未保存编辑不触发)。
|
||||
|
||||
## 四、CodeLens 规则
|
||||
|
||||
- 只对根级(`AssetDeclaration` 直接子元素)带 `id` 的资产显示;
|
||||
- 只对 `isReferenceTargetType()` 为真的类型显示(类型化引用目标 +
|
||||
`inheritFrom` 可继承类型;见 `refs.ts` 的 `referenceTargetTypes()`);
|
||||
- 0 也显示:`0 references` / `1 reference` / `N references`;
|
||||
- 点击执行 `ra3modxml.showReferences` → `editor.action.showReferences`
|
||||
打开 references peek,结果与计数完全一致(不含定义本身);
|
||||
- 计数除了当前定义自己的反向索引桶,还并入“manifestSource 可解析到当前
|
||||
文件”的 manifest 定义桶:manifest 资产有对应 SageXml 源码时,引用直接
|
||||
视作 SageXml 源码对该 asset 的引用(Go to Definition 同样把 manifest
|
||||
定义映射到 SageXml 源码);
|
||||
- 索引重建完成后自动 `editor.action.codeLens.refresh`,计数不会停留在旧值。
|
||||
|
||||
## 五、未引用资产
|
||||
|
||||
- 主入口:命令面板 `RA3 Mod XML: Find unreferenced assets…`
|
||||
第一步 QuickPick 选类型(只列“设计上应被引用”的类型,显示每种未引用数量),
|
||||
第二步列出资产(`id — 相对路径:行号`),点击跳转到定义;
|
||||
- 加速入口:编辑器右键菜单
|
||||
`RA3 Mod XML: Find unreferenced assets of this type`
|
||||
(仅 `editorLangId == xml && ra3modxml.active` 时显示),光标在顶部资产上
|
||||
时直接预选该类型,否则回退到类型选择;
|
||||
- 语义:只统计 `origin === "project"` 且非 `viaInstance` 的定义;
|
||||
manifest / SDK 定义永远不参与;如果某个 id 覆盖了原版资产,来自原版/其他
|
||||
流的引用同样计入(否则会把覆盖件误报成未使用)。
|
||||
|
||||
## 六、已知边界与后续
|
||||
|
||||
- 当前文档局部作用域(不在任何全局流里的文件)的引用不在全局反向索引中:
|
||||
这类文件打开后 CodeLens / FAR 只反映全局流;局部链内的引用暂不计数。
|
||||
- Find All References 不返回定义行本身(即使 VS Code 传入
|
||||
`includeDeclaration`),因此结果数量与 CodeLens 计数严格一致。
|
||||
- `AssetIdList` 等“任意资产 ID 列表”的引用语义仍未建模:整个属性值按一条
|
||||
引用记录处理,与现有补全/诊断保持一致(已知缺口,后续可在 records 层扩展)。
|
||||
- w3x 文件本身不提取引用记录(浅扫描无 DOM);对 w3x 资产的引用从引用它的
|
||||
XML 文件捕获。
|
||||
- manifest 二进制里包含 BAB 编译后的完整引用图(`AssetReferenceOffset/Count` +
|
||||
8 字节 `TypeId+InstanceId` 条目),目前仍跳过。将来可解析它给原版/manifest
|
||||
资产提供“编译器权威”计数;mod 源码资产在编译前没有 manifest,仍需源码级
|
||||
引用索引。
|
||||
- 未引用资产目前是命令 + QuickPick 的“查询”形态;如果之后想要常驻浏览,
|
||||
可以再加 Tree View(更重,暂不计划)。
|
||||
+66
-18
@@ -1,6 +1,6 @@
|
||||
# 调研结论与实施计划(已按最新代码同步更新)
|
||||
|
||||
> 说明:本文档随实现演进持续同步。最近一次同步(2026-08-04)对齐了实现过程中新增的模块与设计变更:BAB 精确搜索路径、manifest 类型/ID 推导、上下文感知元素类型、属性级 refType / Poid 局部引用(`id` 定义点)、精确跳转范围、嵌套 `xi:include`、注入式语法高亮、bit-flag 列表补全(空格触发 / 排除已用 / 追加模式)、simple-content 元素文本引用(补全 / hover / 跳转 / 诊断 / Find All References)等。
|
||||
> 说明:本文档随实现演进持续同步。最近一次同步(2026-08-05)对齐了实现过程中新增的模块与设计变更:BAB 精确搜索路径、manifest 类型/ID 推导、上下文感知元素类型、属性级 refType / Poid 局部引用(`id` 定义点)、精确跳转范围、嵌套 `xi:include`、注入式语法高亮、bit-flag 列表补全(空格触发 / 排除已用 / 追加模式)、simple-content 元素文本引用(补全 / hover / 跳转 / 诊断 / Find All References)、语义引用索引 / CodeLens 引用计数 / 未引用资产命令等。
|
||||
|
||||
## 一、调研结论(带证据)
|
||||
|
||||
@@ -86,9 +86,10 @@ src/
|
||||
manifestParser.ts .manifest 二进制解析 + 类型/ID 推导(纯 TS)
|
||||
fileScanner.ts 目录遍历缓存 + Include source 候选收集
|
||||
refs.ts 引用目标解析(属性 + 元素文本内容,按 refType / isRef /
|
||||
inheritFrom 过滤,纯 TS)
|
||||
inheritFrom 过滤,纯 TS)+ “设计上可被引用类型”判定
|
||||
referenceIndex.ts 引用记录 → 反向引用索引(定义 → 引用位置)+ 未引用报告
|
||||
shallowScan.ts 大体积美术资产(.w3x 等)顶层浅扫描(纯 TS,不建 DOM)
|
||||
records.ts 每文件紧凑索引记录(资产/Define/Include/xi + 行号)
|
||||
records.ts 每文件紧凑索引记录(资产/Define/Include/xi/引用 + 行号偏移)
|
||||
caches.ts 跨重建持久缓存(DocumentCache / IndexRecordsCache /
|
||||
IncludeResolveCache)+ 失效纪元 InvalidationsEpoch
|
||||
diskCache.ts 跨会话磁盘缓存(gzip JSON、原子写、多信号 stat 校验)
|
||||
@@ -99,6 +100,9 @@ src/
|
||||
completion.ts 补全 provider(元素/属性/值,上下文感知;xs:list 多值按当前段过滤)
|
||||
hover.ts hover provider
|
||||
navigation.ts 定义/引用/文档链接/大纲
|
||||
references.ts 语义 FAR / 引用上下文 / CodeLens 命令共享逻辑
|
||||
codeLens.ts CodeLens 引用计数(类型过滤,0 也显示,点击开 references peek)
|
||||
unreferenced.ts 未引用资产 QuickPick 命令 + 右键菜单入口
|
||||
diagnostics.ts 实时诊断
|
||||
semanticTokens.ts 语义 token provider(文档有解析错误时接管着色)
|
||||
syntaxes/
|
||||
@@ -108,9 +112,10 @@ tools/
|
||||
extract-asset-types.mjs OpenSAGE AssetType.cs → asset-types.json
|
||||
test/
|
||||
fixtures/minimod 样例 Mod(include 各种情形、同名 ID、嵌套 xi:include、manifest 回退)
|
||||
*.test.mjs 11 个测试文件(xmlParser / context / completion / semanticTokens /
|
||||
*.test.mjs 14 个测试文件(xmlParser / context / completion / semanticTokens /
|
||||
includeResolver / manifestParser / indexer / schemaModel / refs /
|
||||
typeContext / manifestTypes)
|
||||
typeContext / manifestTypes / referenceIndex / codeLens /
|
||||
referenceProvider)
|
||||
```
|
||||
|
||||
### 关键设计决策
|
||||
@@ -251,6 +256,27 @@ test/
|
||||
用 `<` 做过滤前缀导致菜单为空——改为保留已输入的 `<`、range 从 `<` 之后
|
||||
开始、插入文本不带开括号;`textContentTokenAt` 对未闭合元素用 `el.end`
|
||||
作内容边界。
|
||||
28. **语义引用索引 + CodeLens 计数 + 未引用资产(第十八轮,2026-08-05)**:
|
||||
- 动机与结论:292 个有模型类型的顶层资产中 191 个在 XSD 中没有任何
|
||||
类型化引用指向(设置/地图元数据/w3x 子结构等自动注册类型),
|
||||
AttachTest 实测 29% 项目定义 0 引用、48% 恰好 1 引用。因此 CodeLens
|
||||
计数只显示在 `isReferenceTargetType()` 为真的类型上(类型化引用目标 +
|
||||
`inheritFrom` 可继承类型),0 也显示;未引用报告默认也只列这些类型。
|
||||
- 数据:`IndexRecords` 增加 `references[]`
|
||||
(`kind / refType / selfType / value / line / start / end`),解析期固化
|
||||
引用上下文,反向索引构建零 DOM、零上下文重解析;`ModIndex.references`
|
||||
为“定义 key → 引用位置”的反向表,快照发布时构建;磁盘缓存版本
|
||||
v1 → v2(`index-records-v2.json.gz`),v3 起附加内容/records 哈希。
|
||||
- FAR 从全文搜索改为语义索引:不再把 `id="X"` 定义行、`EditorName="X"`
|
||||
等非引用属性计为引用;CodeLens 显示的计数与点击打开的 references peek
|
||||
严格一致;`includeDeclaration` 时才附加定义位置。
|
||||
- 未引用资产:命令面板 `Find unreferenced assets…` + 编辑器右键菜单
|
||||
`Find unreferenced assets of this type`;只统计 `origin === "project"`
|
||||
且非 `viaInstance` 的定义;覆盖原版 id 时来自原版/其他流的引用计入。
|
||||
- 边界:局部 scope(不在全局流里的文件)的引用不入全局反向索引;
|
||||
`AssetIdList` 等列表引用按整值记录;w3x 不提取引用记录(对 w3x 资产的
|
||||
引用从引用它的 XML 捕获);manifest 编译期引用图(AssetReference 缓冲)
|
||||
留作后续。设计文档:`docs/features-reference-counts.md`。
|
||||
|
||||
## 三、实施步骤
|
||||
|
||||
@@ -308,6 +334,24 @@ test/
|
||||
id/define/local/include 候选返回 `isIncomplete` 让 VS Code 随输入重请求;
|
||||
当前文档 local 资产优先、候选 top-N 用堆避免全量排序、Include source
|
||||
先排序再截断;测试 128 → 136。
|
||||
21. [x] 语义引用索引 + CodeLens + 未引用资产(第十八轮,2026-08-05):
|
||||
records 引用记录提取、`referenceIndex.ts` 反向索引、语义 FAR(替换全文
|
||||
搜索)、CodeLens 引用计数(类型过滤、0 也显示、点击开 references peek)、
|
||||
`findUnreferencedAssets` 命令 + 右键菜单、磁盘缓存 v2;
|
||||
测试 136 → 146;设计文档 `docs/features-reference-counts.md`。
|
||||
22. [x] FAR 定义行排除 + manifest 源引用归并(2026-08-05 修复轮):
|
||||
FAR 不再因 `includeDeclaration` 附加定义行(消除“自引用”观感);
|
||||
`referenceSitesForDefinition` 把 manifestSource 可解析到当前文件的
|
||||
manifest 定义站点并入 CodeLens 计数(AttachTest 326 个 manifest 定义
|
||||
受益);测试 146 → 147;版本 0.1.17;分析见
|
||||
`docs/analysis-issues.md` 二十三。
|
||||
23. [x] 引用索引与缓存同步加固(2026-08-06):反向索引改为从**构建期本地
|
||||
records**(`buildRecords`)构建,不再读共享 recordsCache——中途失效、
|
||||
feature `readDom` 重读都不再造成“资产在但引用缺失”;构建中 `readDom`
|
||||
不再被定义跳转调用(避免污染进行中的构建);force 重建(Re-index)
|
||||
对 stat 匹配的 full XML 做内容哈希校验;打开文档时比较 records 哈希,
|
||||
不一致则定向 invalidate + `records-desync` 重建自愈;磁盘缓存 v2 → v3;
|
||||
测试 147 → 151;分析见 `docs/analysis-issues.md` 二十四。
|
||||
|
||||
## 四、验证结果(实测)
|
||||
|
||||
@@ -320,19 +364,23 @@ test/
|
||||
单元测试覆盖:XML 解析(自闭合/容错/偏移/未闭合引号行尾恢复 + recovered
|
||||
标记)、补全上下文(未闭合引号仍为 attribute-value、多行未闭合引号、list 多值
|
||||
分段、闭合引号后为 attribute-name)、补全集成(vscode stub 下
|
||||
`LocomotorTemplate@Surfaces` 未闭合引号枚举补全、空格后第二段过滤与替换范围、
|
||||
空格后排除已用 flag、中间插入范围止于光标、闭合值末尾追加模式、`CAN_ATTACK`
|
||||
前缀保护、多行未闭合 `Disposition` 完整链路、闭合引号后补空格、一行一个属性
|
||||
换行缩进、新行缩进对齐、标量类型化默认值)、语义 token(标签/属性/值范围、
|
||||
合法文档返回空、malformed 返回兜底 token)、include 解析(BAB 顺序、SDK 根
|
||||
优先于 SageXml)、manifest 二进制解析(合成 v5 样本、类型/ID 推导)、索引器
|
||||
(资产/Define/流/缺失 include/嵌套 xi:include)、XSD 模型(上下文类型、
|
||||
`childTypeOf`、大小写规范化、属性级 refType、外来命名空间判定、`xs:list`
|
||||
枚举继承与 `isList` 标记)、引用过滤(`Weapon="X"` 只跳 `WeaponTemplate`、
|
||||
模块 `id` 定义点、Poid 局部引用、`xi:include` 不校验、`Side="Allies"` 命中
|
||||
manifest 的 `PlayerTemplate`)、simple-content 文本引用(`<` 后补全不产生
|
||||
`<<`、`<CreateObject>$1</CreateObject>` 片段、内容值按 refType 过滤、
|
||||
内容 hover / Ctrl 跳转 / 诊断)。
|
||||
`LocomotorTemplate@Surfaces` 未闭合引号枚举补全、空格后第二段过滤与替换范围、
|
||||
空格后排除已用 flag、中间插入范围止于光标、闭合值末尾追加模式、`CAN_ATTACK`
|
||||
前缀保护、多行未闭合 `Disposition` 完整链路、闭合引号后补空格、一行一个属性
|
||||
换行缩进、新行缩进对齐、标量类型化默认值)、语义 token(标签/属性/值范围、
|
||||
合法文档返回空、malformed 返回兜底 token)、include 解析(BAB 顺序、SDK 根
|
||||
优先于 SageXml)、manifest 二进制解析(合成 v5 样本、类型/ID 推导)、索引器
|
||||
(资产/Define/流/缺失 include/嵌套 xi:include)、XSD 模型(上下文类型、
|
||||
`childTypeOf`、大小写规范化、属性级 refType、外来命名空间判定、`xs:list`
|
||||
枚举继承与 `isList` 标记)、引用过滤(`Weapon="X"` 只跳 `WeaponTemplate`、
|
||||
模块 `id` 定义点、Poid 局部引用、`xi:include` 不校验、`Side="Allies"` 命中
|
||||
manifest 的 `PlayerTemplate`)、simple-content 文本引用(`<` 后补全不产生
|
||||
`<<`、`<CreateObject>$1</CreateObject>` 片段、内容值按 refType 过滤、
|
||||
内容 hover / Ctrl 跳转 / 诊断)、引用索引(records 引用提取:attr/content/
|
||||
inheritFrom、排除 id/Poid/`$DEFINE`/枚举;`buildReferenceIndex` 严格类型过滤
|
||||
不串同名 ID;minimod 集成:`CommandSet` / `inheritFrom` 反向命中;未引用过滤
|
||||
只含 project 非 viaInstance;CodeLens 类型过滤与 0 显示;语义 FAR 排除定义
|
||||
行与非引用属性)。
|
||||
|
||||
> 注:D: 盘移动硬盘已恢复连接;Corona 已在第八 / 九轮按上述新数据回归。
|
||||
|
||||
|
||||
@@ -86,9 +86,21 @@ XML 之间的组织靠 `<Include>` 标签,共有三种语义:
|
||||
美术资产目录(Corona 约 2.6 GB);索引记录与 include 解析结果同样跨重建缓存,
|
||||
保存触发的重建零 stat、零重读(Corona 实测约 2 秒)。
|
||||
|
||||
**补充(引用计数、语义 Find All References 与未引用资产,2026-08-05)**:
|
||||
- 每个顶部 asset 显示被引用次数(CodeLens,0 也显示),点击直接打开
|
||||
references peek;只在“设计上应被引用”的类型上显示,避免设置类/地图元数据/
|
||||
w3x 子结构等自动注册类型制造满屏 0;
|
||||
- Find All References 改为基于语义引用索引(属性引用 + simple-content 文本 +
|
||||
`inheritFrom`,排除 id 定义点 / Poid / `$DEFINE`),不再全文搜索;
|
||||
- 命令 `Find unreferenced assets…`:按类型列出所有零引用的项目定义并跳转;
|
||||
编辑器右键菜单 `Find unreferenced assets of this type` 预选光标所在类型;
|
||||
- 设计文档见 `docs/features-reference-counts.md`。
|
||||
|
||||
### P1:非近期目标(本期不做,但预留扩展点)
|
||||
|
||||
6. **高效搜索**:Mod 项目巨大(Corona 约 7500 个 XML、38MB)时直接全文搜索很慢,需要一个高效的 XML 内容索引机制。
|
||||
(2026-08-05:语义引用索引已落地,FAR / 引用计数 / 未引用报告不再全文搜索;
|
||||
通用内容搜索与索引复用仍属远期。)
|
||||
7. **索引机制的复用性**:希望索引不仅能服务 VS Code 插件,也能被其他工具(如搜索、静态分析)复用,因此索引/解析核心应设计成与编辑器无关的纯模块。
|
||||
|
||||
## 三、环境与参考资源
|
||||
|
||||
Reference in New Issue
Block a user