AI 工具开发实战(4):开发一个 VS Code AI 插件——选中代码一键解释/优化/写测试
前几篇做了 CLI 工具,这篇做点不一样的——VS Code 插件。
选中一段代码,右键选"AI 解释这段代码",插件调用 LLM 在旁边显示注释。还有"优化代码"和"生成测试"功能。
插件做什么
选中代码 → 右键菜单:
├─ 🤖 AI 解释这段代码
├─ ⚡ AI 优化这段代码
└─ 🧪 AI 生成单元测试
点击后 → 调用 DeepSeek API → 结果显示在新面板
项目结构
vscode-ai/
├── package.json # 插件配置
├── extension.js # 主入口
├── ai.js # AI 调用
└── .env
插件配置
// package.json
{
"name": "vscode-ai",
"displayName": "AI Code Assistant",
"version": "1.0.0",
"engines": { "vscode": "^1.85.0" },
"activationEvents": [],
"main": "./extension.js",
"contributes": {
"commands": [
{ "command": "vscode-ai.explain", "title": "🤖 AI 解释这段代码" },
{ "command": "vscode-ai.optimize", "title": "⚡ AI 优化这段代码" },
{ "command": "vscode-ai.test", "title": "🧪 AI 生成单元测试" }
],
"menus": {
"editor/context": [
{ "command": "vscode-ai.explain", "group": "ai" },
{ "command": "vscode-ai.optimize", "group": "ai" },
{ "command": "vscode-ai.test", "group": "ai" }
]
}
}
}
AI 调用模块
// ai.js
const https = require('https');
const API_KEY = process.env.DEEPSEEK_API_KEY || '';
const API_URL = 'api.deepseek.com';
function callLLM(systemPrompt, userPrompt) {
return new Promise((resolve, reject) => {
const data = JSON.stringify({
model: 'deepseek-chat',
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt },
],
temperature: 0.3,
max_tokens: 2048,
});
const req = https.request({
hostname: API_URL,
path: '/v1/chat/completions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`,
},
}, (res) => {
let body = '';
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
try {
const json = JSON.parse(body);
resolve(json.choices[0].message.content);
} catch (e) {
reject(e);
}
});
});
req.on('error', reject);
req.write(data);
req.end();
});
}
// 解释代码
function explainCode(code, language) {
return callLLM(
'你是一个代码解释专家。用中文解释代码的功能和逻辑,重点标注关键部分。',
`解释以下 ${language} 代码:\n\`\`\`${language}\n${code}\n\`\`\``
);
}
// 优化代码
function optimizeCode(code, language) {
return callLLM(
'你是一个代码优化专家。分析代码并给出优化建议,包括性能、可读性、安全性。',
`审查并优化以下 ${language} 代码,给出具体建议:\n\`\`\`${language}\n${code}\n\`\`\``
);
}
// 生成测试
function generateTest(code, language) {
const framework = language === 'python' ? 'pytest' :
language === 'javascript' ? 'jest' :
language === 'typescript' ? 'jest' : '测试框架';
return callLLM(
`你是一个测试工程师。为给定代码生成 ${framework} 单元测试,覆盖正常情况、边界情况和异常情况。`,
`为以下 ${language} 代码生成测试:\n\`\`\`${language}\n${code}\n\`\`\``
);
}
module.exports = { explainCode, optimizeCode, generateTest };
插件主入口
// extension.js
const vscode = require('vscode');
const { explainCode, optimizeCode, generateTest } = require('./ai');
function getSelectedCode() {
const editor = vscode.window.activeTextEditor;
if (!editor) return null;
const selection = editor.selection;
const text = editor.document.getText(selection);
const language = editor.document.languageId;
// 如果没有选中文本,取整个文件
if (!text) {
return {
code: editor.document.getText(),
language: language,
range: new vscode.Range(0, 0, editor.document.lineCount, 0),
};
}
return { code: text, language, range: selection };
}
function showResult(title, content, language) {
// 创建或显示输出面板
const panel = vscode.window.createWebviewPanel(
'aiResult',
title,
vscode.ViewColumn.Beside,
{ enableScripts: true }
);
const html = `
body { font-family: sans-serif; padding: 16px; line-height: 1.6; }
pre { background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; overflow-x: auto; }
code { font-size: 13px; }
${content.replace(/\`\`\`(\w*)\n([\s\S]*?)\`\`\`/g,
'$2')}
`;
panel.webview.html = html;
}
async function handleCommand(action) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage('请先打开一个文件');
return;
}
const { code, language } = getSelectedCode();
if (!code.trim()) {
vscode.window.showWarningMessage('没有可分析的代码');
return;
}
vscode.window.showInformationMessage(`🤖 AI 正在${action}...`);
try {
let result;
if (action === '解释') result = await explainCode(code, language);
else if (action === '优化') result = await optimizeCode(code, language);
else if (action === '测试') result = await generateTest(code, language);
showResult(`AI ${action}结果`, result, language);
} catch (e) {
vscode.window.showErrorMessage(`AI 调用失败: ${e.message}`);
}
}
function activate(context) {
context.subscriptions.push(
vscode.commands.registerCommand('vscode-ai.explain',
() => handleCommand('解释')),
vscode.commands.registerCommand('vscode-ai.optimize',
() => handleCommand('优化')),
vscode.commands.registerCommand('vscode-ai.test',
() => handleCommand('测试')),
);
}
function deactivate() {}
module.exports = { activate, deactivate };
安装使用
# 1. 安装依赖
npm init -y
npm install
# 2. 配置 Key
echo "DEEPSEEK_API_KEY=sk-your-key" > .env
# 3. 打包插件
npm install -g @vscode/vsce
vsce package
# 4. 在 VS Code 中安装
# Command Palette (Cmd+Shift+P) → Extensions: Install from VSIX → 选择 .vsix 文件
效果
1. 打开任意代码文件
2. 选中一段代码
3. 右键 → 🤖 AI 解释这段代码
4. 右侧面板显示:
这段代码是一个用户认证中间件,它:
- 从请求头中提取 JWT Token
- 验证 Token 的有效性
- 将用户信息注入到 request.state
...
总结
VS Code AI 插件的核心:
1. 获取选中的代码(editor.selection)
2. 调用 LLM API
3. 在新的 WebView 面板中展示结果
三个命令覆盖了开发者最常用的场景:看不懂的代码 → 解释、想改进的代码 → 优化、新写的函数 → 生成测试。
本文是 《AI 开发者工具链实战》 系列的第 4 篇。
上一篇:AI 代码审查 CLI
下一篇:AI 浏览器划词翻译插件
本文由 Zyentor(智元界)原创发布