Skip to content

代码优化建议 #22

@cyfung1031

Description

@cyfung1031

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 onDidChangeonDidCreate 都呼叫 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 错误、连线数限制等 ★★☆ 小型工具可接受,但生产级应加限制

整体架构层级问题建议

  1. 多窗口竞争与接管问题
    目前靠 port + 档案锁,基本可行,但极不稳定(例如主窗口 crash 没清理 portFile)。
    → 考虑改用更稳定的方案:

    • 固定端口 + 选举机制(第一个启动的为主)
    • 或使用本地 socket 文件(unix domain socket)
    • 或干脆改用 VS Code 内建的 Named Pipe / IPC(但较复杂)
  2. 缺少日志与错误回馈
    大量使用 console.log,建议引入简单的 output channel。

  3. 缺少测试
    几乎不可能单元测试目前架构,建议至少把 parser / hover 逻辑抽出来测。


目前最优先修复的项目:

  1. extension.ts 格式化 provider 的测试代码移除
  2. globalWebSocketManager 的 stop() 时机与 portFile 清理
  3. sync.ts 的 debounce 与 onDidDelete 处理
  4. Synchronizer 实作 Disposable 并正确 dispose watcher

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions