同时用 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 实现长连接和双向数据传输;
  • 统一的数据格式和状态处理逻辑,确保双方兼容。
相关推荐
字节逆旅9 小时前
从一次爬坑看前端的出路
前端·后端·程序员
你的人类朋友10 小时前
❤️‍🔥对过度设计的反思
程序员·架构·设计
网络安全大学堂13 小时前
【网络安全入门基础教程】TCP/IP协议深入解析(非常详细)零基础入门到精通,收藏这一篇就够了
网络协议·tcp/ip·web安全·计算机·黑客·程序员·编程
ATM给我吐钱17 小时前
Trae,Trae,Trae,怎么还用上Trae Solo了?
程序员
老周聊大模型18 小时前
AI工程化必学:Spring AI与Redis的黄金组合实践
javascript·人工智能·程序员
AI大模型19 小时前
《大模型技术30讲》——从原理到实战的终极指南
程序员·llm·deepseek
SimonKing19 小时前
PostMan不香了,IDEA因为Apipost插件这一功能轻松取代
java·后端·程序员
客白村1 天前
常识:批处理程序
程序员
用户037729334231 天前
Claude Code 和 VSCODE合体
程序员