Files
bigwo/dev-assistant-mcp/dist/tools/codeReview.js
2026-03-12 12:47:56 +08:00

159 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export const codeReviewTool = {
name: "code_review",
description: "审查代码质量。根据审查重点返回结构化的检查清单和分析结果,涵盖 bug、安全、性能、风格等维度。",
inputSchema: {
type: "object",
properties: {
code: {
type: "string",
description: "要审查的代码",
},
language: {
type: "string",
description: "编程语言(如 typescript, python, java 等)",
},
focus: {
type: "string",
description: "审查重点可选security=安全性, performance=性能, style=代码风格, all=全面审查",
enum: ["security", "performance", "style", "all"],
},
},
required: ["code", "language"],
},
};
const reviewChecklists = {
security: [
"检查是否存在 SQL 注入、XSS、CSRF 等注入攻击风险",
"检查是否硬编码了密钥、密码、Token 等敏感信息",
"检查用户输入是否经过验证和清洗",
"检查权限控制是否完善,是否有越权风险",
"检查是否使用了不安全的加密算法或随机数生成",
"检查第三方依赖是否有已知安全漏洞",
],
performance: [
"检查是否存在不必要的循环嵌套或 O(n²) 以上复杂度",
"检查是否有内存泄漏(未清理的定时器、事件监听、闭包)",
"检查是否有不必要的重复计算,是否需要缓存/记忆化",
"检查异步操作是否可以并行化Promise.all",
"检查是否有阻塞主线程的同步操作",
"检查数据库查询是否有 N+1 问题",
],
style: [
"检查命名是否清晰表达意图(变量、函数、类)",
"检查函数长度是否超过 50 行,是否需要拆分",
"检查嵌套层级是否过深(>3 层),是否可用 guard clause",
"检查是否有重复代码DRY 原则)",
"检查注释是否准确且必要,而非冗余",
"检查是否遵循语言社区的标准代码风格",
],
};
export async function executeCodeReview(args) {
const { code, language, focus = "all" } = args;
const lines = code.split("\n");
const lineCount = lines.length;
// 基础代码统计
const stats = {
totalLines: lineCount,
blankLines: lines.filter((l) => l.trim() === "").length,
commentLines: lines.filter((l) => {
const t = l.trim();
return t.startsWith("//") || t.startsWith("#") || t.startsWith("/*") || t.startsWith("*");
}).length,
codeLines: 0,
maxLineLength: Math.max(...lines.map((l) => l.length)),
maxNestingDepth: 0,
};
stats.codeLines = stats.totalLines - stats.blankLines - stats.commentLines;
// 计算最大嵌套深度
let depth = 0;
for (const line of lines) {
const opens = (line.match(/{/g) || []).length;
const closes = (line.match(/}/g) || []).length;
depth += opens - closes;
if (depth > stats.maxNestingDepth)
stats.maxNestingDepth = depth;
}
// 检测潜在问题
const issues = [];
// 通用检查
if (stats.maxLineLength > 120)
issues.push(`⚠️ 存在超长行(最长 ${stats.maxLineLength} 字符),建议不超过 120`);
if (stats.maxNestingDepth > 4)
issues.push(`⚠️ 嵌套层级过深(${stats.maxNestingDepth} 层),建议重构`);
if (stats.codeLines > 300)
issues.push(`⚠️ 文件过长(${stats.codeLines} 行代码),建议拆分`);
if (stats.commentLines === 0 && stats.codeLines > 30)
issues.push("🔵 缺少注释,建议为关键逻辑添加说明");
// 安全检查
if (focus === "security" || focus === "all") {
if (/eval\s*\(/.test(code))
issues.push("🔴 使用了 eval(),存在代码注入风险");
if (/innerHTML\s*=/.test(code))
issues.push("🔴 使用了 innerHTML存在 XSS 风险");
if (/(password|secret|api_?key|token)\s*=\s*["'][^"']+["']/i.test(code))
issues.push("🔴 可能硬编码了敏感信息");
if (/\bhttp:\/\//.test(code))
issues.push("🟡 使用了 HTTP 而非 HTTPS");
if (/exec\s*\(|spawn\s*\(/.test(code) && !/sanitize|escape|validate/.test(code))
issues.push("🟡 执行了外部命令,确认输入已清洗");
}
// 性能检查
if (focus === "performance" || focus === "all") {
if (/for\s*\(.*for\s*\(/s.test(code))
issues.push("🟡 存在嵌套循环,注意时间复杂度");
if (/setTimeout|setInterval/.test(code) && !/clearTimeout|clearInterval/.test(code))
issues.push("<22> 设置了定时器但未见清理,可能内存泄漏");
if (/\.forEach\(.*await/.test(code))
issues.push("🟡 在 forEach 中使用 await不会等待完成建议用 for...of");
if (/new RegExp\(/.test(code) && /for|while|map|forEach/.test(code))
issues.push("🔵 循环中创建正则表达式,建议提取到循环外");
}
// 风格检查
if (focus === "style" || focus === "all") {
if (/var\s+/.test(code) && (language === "typescript" || language === "javascript"))
issues.push("🔵 使用了 var建议改用 const/let");
if (/console\.log/.test(code))
issues.push("🔵 包含 console.log确认是否需要在生产环境移除");
if (/any/.test(code) && language === "typescript")
issues.push("🔵 使用了 any 类型,建议使用具体类型");
if (/TODO|FIXME|HACK|XXX/.test(code))
issues.push("🔵 存在 TODO/FIXME 标记,建议处理");
}
// 获取对应的检查清单
let checklist;
if (focus === "all") {
checklist = [
...reviewChecklists.security,
...reviewChecklists.performance,
...reviewChecklists.style,
];
}
else {
checklist = reviewChecklists[focus] || reviewChecklists.style;
}
// 组装结果
const output = [
`# 代码审查报告`,
``,
`**语言**: ${language} | **审查重点**: ${focus}`,
``,
`## 代码统计`,
`- 总行数: ${stats.totalLines}(代码 ${stats.codeLines} / 注释 ${stats.commentLines} / 空行 ${stats.blankLines}`,
`- 最长行: ${stats.maxLineLength} 字符`,
`- 最大嵌套深度: ${stats.maxNestingDepth}`,
``,
`## 自动检测到的问题(${issues.length} 项)`,
issues.length > 0 ? issues.map((i) => `- ${i}`).join("\n") : "- ✅ 未检测到明显问题",
``,
`## 人工审查清单`,
`请逐项检查以下内容:`,
...checklist.map((item, idx) => `${idx + 1}. ${item}`),
``,
`## 待审查代码`,
"```" + language,
code,
"```",
];
return output.join("\n");
}
//# sourceMappingURL=codeReview.js.map