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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions