-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
1. extension.ts
| # | 问题 | 严重度 | 说明与建议 |
|---|---|---|---|
| 1 | let watcher = null; 后续没有明确赋值就使用,虽然逻辑上一定会赋值,但 TypeScript 会抱怨可能为 null |
★★☆ | 改用 let watcher: vscode.FileSystemWatcher; 并确保两个分支都赋值 |
| 2 | import { existsSync, fstat } from "fs"; 却没用到 fstat,而且下面又 import "fs";(无效写法) |
★★☆ | 移除无用 import,统一使用 import * as fs from "fs"; 或只 import 需要的 |
| 3 | 格式化 provider 硬编码检查 firstLine.text !== "42" 并插入 "42\n",这明显是测试/占位代码 |
★★★ | 应移除或注解掉,否则会破坏正常 js 档案格式化 |
| 4 | context.subscriptions.push(metaProvideHover()); 只在「没有指定 target」时注册,指定 target 后就不注册 hover → 不一致体验 |
★★☆ | 建议无论是否指定 target 都注册 hover(hover 是语言层级功能,与同步目标无关) |
| 5 | deactivate() 完全空实作,没有清理任何资源 |
★★☆ | 至少把主要的 watcher、同步器等 dispose(虽然有 push subscriptions,但不够明确) |
| 6 | mSync.changeTargetScript() 传入全新 watcher,但旧 watcher 没有 dispose |
★★★ | 旧 watcher 会持续监听,造成泄漏 |
建议修正片段(重点部分)
// extension.ts 开头
import * as vscode from "vscode";
import * as fs from "fs"; // 统一
import { metaProvideHover } from "./provide";
// ... 其他 import
export function activate(context: vscode.ExtensionContext) {
const signatureFileCommand = "scriptcat.target";
const autoTargetCommand = "scriptcat.autoTarget";
let watcher: vscode.FileSystemWatcher;
const target = context.workspaceState.get<string>("target");
const registerCommonProviders = () => {
context.subscriptions.push(metaProvideHover());
context.subscriptions.push(registerUserScriptHighlighter());
context.subscriptions.push(...registerUserScriptDiagnostics());
};
if (target && fs.existsSync(target)) {
vscode.window.showInformationMessage(`工作区已选定脚本:${target}`);
watcher = vscode.workspace.createFileSystemWatcher(
new vscode.RelativePattern(target, "*"),
false, false, false
);
} else {
watcher = vscode.workspace.createFileSystemWatcher("**/*.user.js", false, false, false);
registerCommonProviders(); // 统一注册
}
const mSync = new Synchronizer(watcher, context);
context.subscriptions.push(mSync); // 如果 Synchronizer 实作 Disposable 更好
// 无论如何都注册这些(比较合理)
registerCommonProviders();
checkAndPromptSemanticHighlighting();
// 格式化 provider 应移除或改成真的 formatter
// vscode.languages.registerDocumentFormattingEditProvider(...) ← 建议注解或移除
// command 里的 changeTargetScript 前应先 dispose 旧 watcher
// ...
}2. sync.ts
| # | 问题 | 严重度 | 说明与建议 |
|---|---|---|---|
| 1 | onDidChange 与 onDidCreate 都呼叫 onChange,但没处理 onDidDelete(脚本删除时不通知) |
★★☆ | 补上 watcher.onDidDelete 发送 delete 事件 |
| 2 | 快速连续保存时会多次读档、多次发送相同内容,没有 debounce | ★★☆ | 加 debounce (例如 300ms) |
| 3 | sendMessageViaFile 使用 Date.now() + Math.random() 档名,极低机率仍可能 collision |
★☆☆ | 可改用 uuid 或递增序号 |
| 4 | 档案清理使用 setTimeout(5000),但如果 VSCode 这段时间关闭,垃圾档案会残留 |
★★☆ | 启动时扫描并清理旧 message-*.json |
| 5 | messageHandler 完全没实作,注册了却什么都不做 |
★★☆ | 如果暂时不需要,应移除;若未来要用,应明确定义讯息类型 |
| 6 | Synchronizer 本身没有实作 Disposable,但被 push 进去 dispose: () => mSync.close() |
★★☆ | 建议让 Synchronizer 实作 vscode.Disposable |
3. provide.ts (目前最干净,但功能极简)
| # | 问题 | 严重度 | 说明与建议 |
|---|---|---|---|
| 1 | 正则 `^//\s*@(\w+?)(\s+(.*?) | )$无法处理@grant GM_xmlhttpRequest` 后面的多余空格 |
★★☆ |
| 2 | 只支援 // @key 单行,不支援 /* @key ... */ 多行注解 |
★★☆ | 目前多数现代油猴脚本仍用 //,但应考虑支援 |
| 3 | hover 内容只是中文名称,资讯量极低 | ★☆☆ | 可加入官方文件连结或更详细说明 |
| 4 | 没有处理 @ 后面不是标准 key 的情况(会显示 undefined) |
★☆☆ | 加 fallback 提示「未知的元数据」 |
4. globalWebSocketManager.ts (最复杂、最多问题)
这是目前最容易出问题的部分。
| # | 问题 | 严重度 | 说明与建议 |
|---|---|---|---|
| 1 | 没有真正的心跳 + pong 处理,val.ping() 发出但没监听 pong,无法侦测真正断线 |
★★★ | 应实作 ping/pong 机制,并在超时时主动 close |
| 2 | setupFileWatcher 只在主窗口启动,但从窗口也需要监听 sharedDir 来转发消息?目前设计是只有主窗口监听 |
★★★ | 目前从窗口发文件 → 主窗口监听并广播,设计合理;但应在 start() 失败时也让从窗口监听一次(防主窗口意外关闭) |
| 3 | checkExistingServer 读 portFile 后只检查端口是否占用,没验证是不是真的 scriptcat 服务 |
★★☆ | 低风险,但可接受 |
| 4 | stop() 没被任何人呼叫,导致多开关闭后 portFile 残留,下次启动误判 |
★★★ | 在 deactivate() 或最后一个窗口关闭时呼叫 GlobalWebSocketManager.getInstance().stop() |
| 5 | broadcast 没检查 client.readyState,虽然有但写法不够严谨 |
★☆☆ | 已写,但可改成 if (client.readyState === WebSocket.OPEN) |
| 6 | 完全没有处理 WebSocket upgrade 错误、连线数限制等 | ★★☆ | 小型工具可接受,但生产级应加限制 |
整体架构层级问题建议
-
多窗口竞争与接管问题
目前靠 port + 档案锁,基本可行,但极不稳定(例如主窗口 crash 没清理 portFile)。
→ 考虑改用更稳定的方案:- 固定端口 + 选举机制(第一个启动的为主)
- 或使用本地 socket 文件(unix domain socket)
- 或干脆改用 VS Code 内建的 Named Pipe / IPC(但较复杂)
-
缺少日志与错误回馈
大量使用console.log,建议引入简单的 output channel。 -
缺少测试
几乎不可能单元测试目前架构,建议至少把 parser / hover 逻辑抽出来测。
目前最优先修复的项目:
- extension.ts 格式化 provider 的测试代码移除
- globalWebSocketManager 的 stop() 时机与 portFile 清理
- sync.ts 的 debounce 与 onDidDelete 处理
- Synchronizer 实作 Disposable 并正确 dispose watcher
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels