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

vscode里安装这个插件

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

然后就可以愉快的跨ide编码啦
知其然,更要知其所以然,很好奇他们之间是怎么进行同步的,于是我去看了一部分他们的实现整理了下面的内容
一、核心原理
- 双向状态监听:在 VSCode 和 JetBrains IDE 中分别部署插件,实时监听当前激活文件、光标位置及窗口焦点变化。
- WebSocket 通信:以 WebSocket 作为通信协议,建立 VSCode(服务端)与 JetBrains IDE(客户端)的长连接,实现状态数据的实时传输。
- 状态同步逻辑:当一方 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 发送的状态后,打开对应文件并定位光标:
iniprivate 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 发送的状态后,打开文件并定位光标:
kotlinprivate 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 实现长连接和双向数据传输;
- 统一的数据格式和状态处理逻辑,确保双方兼容。