技术文章

架构师Web
2026-06-30 11:32
阅读 349

杭州二娃奶爸下班后的IDE插件开发折腾记

晚上11点半,终于把两个神兽哄睡了。我长舒一口气,轻手轻脚关上儿童房的门,溜进书房打开电脑。坐标杭州,作为一个在厂里卷了一天的二娃奶爸,只有这凌晨的时光才真正属于自己。熟悉我的老读者知道,我是个重度Vim党,平时写代码恨不得键盘都不看,IDE这种东西在我眼里就是“花里胡哨的累赘”。但最近为了准备跳槽,毕竟杭州这边阿里和网易的坑位多,竞争也卷,没点拿得出手的亮点简历根本过不了筛选。于是,我硬着头皮开始折腾IDE插件开发。

说起搞这个插件的契机,其实是被领导逼的。上个月团队开会,Leader说要全面拥抱AI辅助编程,让每个人调研并落地一个AI提效工具。我平时用Vim,搞个Neovim的Lua插件不就行了?但Leader一句话把我噎了:“咱们前端和客户端同学都用VS Code和JetBrains,你得搞个通用的。”得,为了合群,也为了简历上能多写一条“主导研发IDE AI辅助插件”,我只能捏着鼻子学TS和VS Code Extension API。

调研阶段我算是把市面上的AI工具摸了个底朝天。代码补全我试了CodeGeeX,响应速度确实可以,上下文感知做得不错;对话和代码解释我对比了豆包和讯飞星火,发现讯飞星火在理解中文业务注释上稍微细腻点,而豆包在生成单元测试时逻辑更严密。至于插件的Logo,我实在不想去素材网扒图,直接打开Midjourney,敲了几句Prompt,生成了一个赛博朋克风格的代码括号图标,看着还挺像那么回事。

真正动手写的时候,才发现从Vim的模态编辑思维切换到VS Code的异步事件驱动思维,简直像换了个脑子。

第一个坑就是环境。我电脑上的Node版本还是老早之前的14,跑官方脚手架 yo code 的时候直接报了一堆依赖冲突。当时真的想砸电脑,大半夜的还得去搞 nvm 切版本,顺便把ESLint的配置理顺。

第二个坑是API文档。VS Code的API多如牛毛,找个 TextEditor 的选中事件能翻半天。我这个人有个毛病,就是极度注重代码可读性和可维护性。刚开始写的时候,为了把大模型返回的流式数据渲染到侧边栏,我写了一个巨长的回调函数。后来实在看不下去,半夜两点硬是把它重构了,拆成了 StreamParserUIRendererAPIAdapter 三个类。虽然同事后来吐槽我“写个破插件还搞什么领域驱动设计”,但看着清清爽爽的代码,我这强迫症算是舒服了。

下面贴点核心代码,给想入门的兄弟避避坑。

先看下 package.json 里的核心配置,这决定了你的插件怎么被宿主识别,以及怎么注册命令和侧边栏。

{
  "name": "ai-coding-buddy",
  "displayName": "AI Coding Buddy",
  "version": "0.0.1",
  "engines": {
    "vscode": "^1.75.0"
  },
  "categories": ["Other"],
  "activationEvents": [
    "onCommand:aiBuddy.explainCode"
  ],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "aiBuddy.explainCode",
        "title": "AI: 解释选中代码"
      }
    ],
    "viewsContainers": {
      "activitybar": [
        {
          "id": "ai-buddy-sidebar",
          "title": "AI Buddy",
          "icon": "media/icon.svg"
        }
      ]
    },
    "views": {
      "ai-buddy-sidebar": [
        {
          "type": "webview",
          "id": "aiBuddy.chatView",
          "name": "对话面板"
        }
      ]
    }
  }
}

然后是侧边栏 Webview 的通信机制。这是最容易踩坑的地方,Webview 里的 JS 和插件主进程的 JS 是隔离的,必须通过 postMessage 来通信。我一开始直接想在 Webview 里 fetch 讯飞星火的接口,结果被 CORS 策略教做人。后来乖乖把网络请求放到插件主进程,Webview 只负责展示。

import * as vscode from 'vscode';

export class ChatViewProvider implements vscode.WebviewViewProvider {
    constructor(private readonly _extensionUri: vscode.Uri) {}

    public resolveWebviewView(
        webviewView: vscode.WebviewView,
        context: vscode.WebviewViewResolveContext,
        _token: vscode.CancellationToken,
    ) {
        webviewView.webview.options = {
            enableScripts: true,
            localResourceRoots: [this._extensionUri]
        };

        webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);

        // 监听来自 Webview 的消息
        webviewView.webview.onDidReceiveMessage(async (data) => {
            switch (data.type) {
                case 'requestExplain':
                    // 获取编辑器选中的代码
                    const editor = vscode.window.activeTextEditor;
                    if (editor) {
                        const selection = editor.selection;
                        const selectedText = editor.document.getText(selection);
                        // 调用大模型接口,这里以豆包为例
                        const result = await this.callLLM(selectedText);
                        // 将结果发回 Webview
                        webviewView.webview.postMessage({ type: 'explainResult', data: result });
                    }
                    break;
            }
        });
    }

    private async callLLM(code: string): Promise<string> {
        // 模拟调用大模型API,实际项目中这里要写请求逻辑
        // 注意:一定要在插件主进程发请求,避开跨域问题
        return `解释:这段代码主要用于... (由豆包生成)`; 
    }

    private _getHtmlForWebview(webview: vscode.Webview) {
        // 返回 HTML 字符串,引入 CSS 和 JS
        return `<!DOCTYPE html>...`;
    }
}

折腾了大概两个周末,这个插件总算上线了内部市场。没想到还挺受欢迎,陆陆续续有几十个同事安装使用,甚至有个测试小哥跑来问我能不能加个“自动生成甩锅话术”的功能,被我无情拒绝了。

回过头来看,IDE插件开发其实没有想象中那么难,核心就是理解编辑器的扩展API和消息通信机制。虽然我是个Vim党,平时依然坚持用键盘敲命令,但懂点IDE插件开发对理解现代编辑器的架构、甚至以后去大厂面试聊提效工具建设,都大有裨益。技术选型上没有绝对的好坏,Vim有Vim的极客浪漫,VS Code有VS Code的生态繁荣,能解决业务痛点、提高团队效率的工具就是好工具。

哎,不说了,主卧传来老二哭的声音,估计是饿了,我得赶紧去冲奶粉了。希望这篇踩坑记录能帮到同样在深夜折腾代码的兄弟们,咱们下期再见。

评论 0

最热最新
暂无评论
架构师WebLv.1
0
影响力
0
文章
0
粉丝