Files
bigwo/dev-assistant-mcp/dist/tools/lintCheck.js

133 lines
5.6 KiB
JavaScript
Raw Normal View History

2026-03-12 12:47:56 +08:00
import { exec } from "child_process";
import { promisify } from "util";
import { existsSync } from "fs";
import { join } from "path";
const execAsync = promisify(exec);
export const lintCheckTool = {
name: "lint_check",
description: "对项目执行代码检查。自动检测项目类型并运行对应的 lint 工具ESLint、TypeScript 编译检查、Pylint 等),返回结构化的错误列表。",
inputSchema: {
type: "object",
properties: {
project_path: {
type: "string",
description: "项目根目录(绝对路径)",
},
fix: {
type: "boolean",
description: "是否自动修复可修复的问题(默认 false",
},
files: {
type: "string",
description: "指定检查的文件或 glob可选默认检查整个项目",
},
},
required: ["project_path"],
},
};
async function runCommand(cmd, cwd, timeout = 30000) {
try {
const { stdout, stderr } = await execAsync(cmd, {
cwd,
timeout,
maxBuffer: 1024 * 1024 * 5,
shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash",
});
return { stdout, stderr, code: 0 };
}
catch (error) {
return {
stdout: error.stdout || "",
stderr: error.stderr || "",
code: error.code ?? 1,
};
}
}
export async function executeLintCheck(args) {
const { project_path, fix = false, files } = args;
const results = [];
const hasFile = (name) => existsSync(join(project_path, name));
const hasNodeModules = hasFile("node_modules");
// TypeScript 编译检查
if (hasFile("tsconfig.json")) {
const result = await runCommand("npx tsc --noEmit --pretty", project_path);
const errorCount = (result.stdout.match(/error TS/g) || []).length;
results.push({
tool: "TypeScript (tsc --noEmit)",
success: result.code === 0,
errorCount,
warningCount: 0,
output: result.stdout || result.stderr || "(无输出)",
});
}
// ESLint
if (hasFile(".eslintrc.js") || hasFile(".eslintrc.json") || hasFile(".eslintrc.yml") || hasFile("eslint.config.js") || hasFile("eslint.config.mjs")) {
const target = files || "src/";
const fixFlag = fix ? " --fix" : "";
const result = await runCommand(`npx eslint ${target}${fixFlag} --format stylish`, project_path);
const errorMatch = result.stdout.match(/(\d+) errors?/);
const warnMatch = result.stdout.match(/(\d+) warnings?/);
results.push({
tool: `ESLint${fix ? " (--fix)" : ""}`,
success: result.code === 0,
errorCount: errorMatch ? parseInt(errorMatch[1]) : 0,
warningCount: warnMatch ? parseInt(warnMatch[1]) : 0,
output: result.stdout || result.stderr || "✅ 无问题",
});
}
// Python: pylint / flake8
if (hasFile("requirements.txt") || hasFile("setup.py") || hasFile("pyproject.toml")) {
const target = files || ".";
// 优先 flake8
const result = await runCommand(`python -m flake8 ${target} --max-line-length=120 --count`, project_path);
if (result.code !== 127) { // 127 = command not found
const lines = result.stdout.trim().split("\n").filter(Boolean);
results.push({
tool: "Flake8",
success: result.code === 0,
errorCount: lines.length,
warningCount: 0,
output: result.stdout || result.stderr || "✅ 无问题",
});
}
}
// 如果什么检查工具都没找到
if (results.length === 0) {
// 尝试通用的 package.json lint 脚本
if (hasFile("package.json")) {
const result = await runCommand("npm run lint 2>&1 || echo LINT_SCRIPT_NOT_FOUND", project_path);
if (!result.stdout.includes("LINT_SCRIPT_NOT_FOUND") && !result.stdout.includes("Missing script")) {
results.push({
tool: "npm run lint",
success: result.code === 0,
errorCount: result.code === 0 ? 0 : 1,
warningCount: 0,
output: result.stdout || result.stderr,
});
}
}
}
if (results.length === 0) {
return `# Lint 检查结果\n\n⚠️ 未检测到 lint 工具配置ESLint、tsconfig、pylint 等)\n项目路径: ${project_path}\n\n建议:\n- TypeScript 项目:添加 tsconfig.json\n- JS 项目npm init @eslint/config\n- Python 项目pip install flake8`;
}
// 组装报告
const totalErrors = results.reduce((sum, r) => sum + r.errorCount, 0);
const totalWarnings = results.reduce((sum, r) => sum + r.warningCount, 0);
const allPassed = results.every((r) => r.success);
const output = [
`# Lint 检查报告`,
``,
`📂 项目: ${project_path}`,
`${allPassed ? "✅ 全部通过" : "❌ 发现问题"} | 错误: ${totalErrors} | 警告: ${totalWarnings}`,
``,
];
for (const r of results) {
output.push(`## ${r.success ? "✅" : "❌"} ${r.tool}`, `错误: ${r.errorCount} | 警告: ${r.warningCount}`, "```", r.output.slice(0, 3000), // 限制输出长度
"```", ``);
}
if (!allPassed && !fix) {
output.push(`💡 提示: 可以设置 fix=true 自动修复可修复的问题`);
}
return output.join("\n");
}
//# sourceMappingURL=lintCheck.js.map