同时用 VSCode 和 JetBrains 开发?这款插件让文件和光标 “无缝同步”

不知道大家在日常开发中有没有希望同时使用vscode和jetbrains家的ide写同一个项目的需求,之前一直都是用webstorm来做前端开发,最近在编码中使用上了copilot来辅助编码,但又同时很喜欢webstorm的智能提示和代码补全。但是又会面临这样一个痛点,在不同ide之间进行的文件的打开以及光标位置无法同步,这里给大家推荐一个插件:IDE Sync - VSCode-JetBrains IDE Sync

需要在idea和vscode里同时安装

idea里安装下面这个插件

vscode里安装这个插件

装上以后在两个ide的底部菜单栏都打开这个按钮,连接上后会有同步成功的提示

然后就可以愉快的跨ide编码啦

知其然,更要知其所以然,很好奇他们之间是怎么进行同步的,于是我去看了一部分他们的实现整理了下面的内容

一、核心原理

  1. 双向状态监听:在 VSCode 和 JetBrains IDE 中分别部署插件,实时监听当前激活文件、光标位置及窗口焦点变化。
  2. WebSocket 通信:以 WebSocket 作为通信协议,建立 VSCode(服务端)与 JetBrains IDE(客户端)的长连接,实现状态数据的实时传输。
  3. 状态同步逻辑:当一方 IDE 发生文件切换或光标移动时,主动将状态数据发送给另一方,接收方根据数据更新自身状态(打开对应文件、定位光标)。

二、技术实现细节

1. 组件架构

插件包含两个核心组件,分别对应两种 IDE:

  • VSCode 扩展/vscode-extension):作为 WebSocket 服务端,监听自身文件和光标变化,并接收 JetBrains 客户端的状态更新。
  • JetBrains 插件/jetbrains-plugin):作为 WebSocket 客户端,监听自身状态变化,并向 VSCode 服务端发送更新。

2. 数据传输格式

双方通过 JSON 格式传输状态数据,核心字段包括:

typescript 复制代码
interface SyncState {
  filePath: string;       // 当前激活文件的本地路径
  line: number;           // 光标所在行(从零开始)
  column: number;         // 光标所在列(从零开始)
  source: 'vscode' | 'jetbrains';  // 数据来源,避免自身状态回环处理
  isActive: boolean;      // 当前 IDE 是否处于活跃状态(有窗口焦点)
}

3. VSCode 扩展实现(TypeScript)

  • WebSocket 服务端 :使用 ws 库创建 WebSocket 服务端(默认端口 3000),等待 JetBrains 客户端连接。

    javascript 复制代码
    // 启动 WebSocket 服务
    const wss = new WebSocketServer({ port: 3000 });
    wss.on('connection', (ws) => {
      // 处理客户端连接,接收 JetBrains 发送的状态
      ws.on('message', (data) => {
        const state = JSON.parse(data.toString());
        handleIncomingState(state); // 处理并更新 VSCode 状态
      });
    });
  • 状态监听:通过 VSCode 扩展 API 监听文件激活和光标变化事件:

    dart 复制代码
    // 监听激活文件变化
    vscode.window.onDidChangeActiveTextEditor((editor) => {
      if (editor) {
        const state = {
          filePath: editor.document.uri.fsPath,
          line: editor.selection.active.line,
          column: editor.selection.active.character,
          source: 'vscode',
          isActive: vscode.window.state.focused
        };
        updateState(state); // 发送状态到 JetBrains
      }
    });
    ​
    // 监听光标位置变化
    vscode.window.onDidChangeTextEditorSelection((event) => {
      // 类似上述逻辑,生成并发送状态
    });
  • 状态接收与处理:收到 JetBrains 发送的状态后,打开对应文件并定位光标:

    ini 复制代码
    private async handleIncomingState(state: SyncState) {
      const uri = vscode.Uri.file(state.filePath);
      const document = await vscode.workspace.openTextDocument(uri);
      const editor = await vscode.window.showTextDocument(document);
      const position = new vscode.Position(state.line, state.column);
      editor.selection = new vscode.Selection(position, position);
    }

4. JetBrains 插件实现(Kotlin:编写插件的语言)

  • WebSocket 客户端 :使用 java-websocket 库连接 VSCode 的 WebSocket 服务端:

    kotlin 复制代码
    // 连接 VSCode 服务端
    webSocket = object : WebSocketClient(URI("ws://localhost:3000/jetbrains")) {
      override fun onOpen(handshakedata: ServerHandshake?) {
        // 连接成功后发送初始状态
      }
      override fun onMessage(message: String?) {
        val state = gson.fromJson(message, EditorState::class.java)
        handleIncomingState(state); // 处理 VSCode 发送的状态
      }
    }
    webSocket.connectBlocking()
  • 状态监听:通过 JetBrains 平台 API 监听文件切换和光标移动:

    kotlin 复制代码
    // 监听文件激活变化
    project.messageBus.connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER,
      object : FileEditorManagerListener {
        override fun selectionChanged(event: FileEditorManagerEvent) {
          val editor = FileEditorManager.getInstance(project).selectedTextEditor
          val file = event.newFile
          if (editor != null && file != null) {
            updateStateFromEditor(editor, file) // 生成并发送状态
          }
        }
      }
    )
    ​
    // 监听光标位置变化
    editor.caretModel.addCaretListener { event ->
      updateStateFromEditor(editor, file) // 生成并发送状态
    }
  • 状态接收与处理:收到 VSCode 发送的状态后,打开文件并定位光标:

    kotlin 复制代码
    private fun handleIncomingState(state: EditorState) {
      val file = LocalFileSystem.getInstance().findFileByPath(state.filePath)
      if (file != null) {
        // 打开文件
        FileEditorManager.getInstance(project).openFile(file, true)
        // 定位光标
        val editor = FileEditorManager.getInstance(project).selectedTextEditor
        editor?.caretModel?.moveToLogicalPosition(
          LogicalPosition(state.line, state.column)
        )
      }
    }

5. 辅助功能实现

  • 状态指示器:双方 IDE 的状态栏均显示同步状态(连接中 / 已连接 / 未连接),支持手动开启 / 关闭同步。
  • 自动重连:当连接断开时,客户端(JetBrains)会自动重试连接,确保通信稳定性。
  • 端口配置:默认使用 3000 端口,支持在双方 IDE 的设置中自定义端口(需保持一致)。

三、总结

整个同步流程基于 WebSocket 实时通信,通过监听 IDE 内部事件获取状态,再通过网络传输实现跨 IDE 状态同步

  • 利用 IDE 平台提供的 API 监听文件和光标事件;
  • 基于 WebSocket 实现长连接和双向数据传输;
  • 统一的数据格式和状态处理逻辑,确保双方兼容。
相关推荐
demo007x6 小时前
让大模型活在你的鼠标旁:我用 Tauri 2 + Rust 打造了一款“反直觉”的 AI 全局划词效率神器
macos·程序员·llm
程序员海军8 小时前
AI 越来越强,为什么打工人反而越来越累、越来越内耗了?
前端·程序员·aigc
badhope12 小时前
同样写 AI,为什么有的文章 549 人看、有的只有 16 人看?——我用 40 篇掘金文章的真实数据复盘
程序员
今朝唯我少年郎2 天前
Codex安全盲区代码漏洞生成实测
python·程序员
kyriewen2 天前
我用 AI 写完一个需求后才发现,最难的不是 prompt,而是验收
前端·程序员·ai编程
酷酷的逗逗乐2 天前
前端转 Agent 开发 · 第六节
前端·程序员
爱勇宝2 天前
没有 Fn 键关触控板?我做了一个双击即用的 Windows 小工具
前端·后端·程序员
程序员cxuan2 天前
跟 WebUI 说再见了,最强 DeepSeek 桌面端来了!
人工智能·后端·程序员
codigger3 天前
用 AI 写代码,你知道它会把我的代码传去哪?
ai·程序员·编程·数据安全
程序员cxuan3 天前
DeepSeek V4.1 Flash 正式发布!
人工智能·后端·程序员