visuddhinanda há 1 mês atrás
pai
commit
40d2b0a2a0
1 ficheiros alterados com 270 adições e 0 exclusões
  1. 270 0
      dashboard-v6/migration-tools/analyze-tsc-errors.cjs

+ 270 - 0
dashboard-v6/migration-tools/analyze-tsc-errors.cjs

@@ -0,0 +1,270 @@
+#!/usr/bin/env node
+
+const { execSync } = require("child_process");
+const fs = require("fs");
+const path = require("path");
+
+console.log("🔍 TypeScript 错误分析工具 v2\n");
+console.log("=".repeat(80) + "\n");
+
+/**
+ * 运行 TypeScript 编译检查
+ */
+function getTscErrors() {
+  console.log("📊 正在运行 TypeScript 检查...\n");
+
+  try {
+    const result = execSync("npx tsc --noEmit -p tsconfig.app.json 2>&1", {
+      cwd: path.resolve(__dirname, ".."),
+      encoding: "utf-8",
+      env: { ...process.env, NODE_NO_WARNINGS: "1" },
+    });
+
+    if (!result || result.trim().length === 0) {
+      console.log("✅ 没有类型错误!");
+      return "";
+    }
+
+    return result;
+  } catch (error) {
+    return error.stdout || error.stderr || error.message || "";
+  }
+}
+
+/**
+ * 保存原始输出
+ */
+function saveRawOutput(output) {
+  const rawPath = path.join(__dirname, "..", "tsc-raw-output.txt");
+  fs.writeFileSync(rawPath, output, "utf-8");
+  console.log(`📝 原始输出已保存: ${path.basename(rawPath)}\n`);
+}
+
+/**
+ * 解析错误信息
+ * 支持格式: src/file.tsx(1,22): error TS2307: Error message
+ */
+function parseErrors(errorOutput) {
+  const lines = errorOutput.split("\n");
+  const errorsByType = new Map();
+  let parsedCount = 0;
+
+  console.log(`📄 总行数: ${lines.length}\n`);
+  console.log("🔍 开始解析错误...\n");
+
+  for (let i = 0; i < lines.length; i++) {
+    const line = lines[i].trim();
+
+    // 匹配格式: src/file.tsx(1,22): error TS2307: Error message
+    const errorMatch = line.match(
+      /^(.+?)\((\d+),(\d+)\):\s*error\s+(TS\d+):\s*(.+)$/
+    );
+
+    if (errorMatch) {
+      parsedCount++;
+      const [, filePath, lineNum, colNum, errorCode, errorMessage] = errorMatch;
+
+      const errorObj = {
+        filePath: filePath.trim(),
+        lineNum: parseInt(lineNum),
+        colNum: parseInt(colNum),
+        errorCode,
+        errorMessage: errorMessage.trim(),
+        fullError: line,
+      };
+
+      // 按错误代码分组
+      if (!errorsByType.has(errorCode)) {
+        errorsByType.set(errorCode, {
+          code: errorCode,
+          count: 0,
+          samples: [],
+          description: errorMessage.trim(),
+        });
+      }
+
+      const errorType = errorsByType.get(errorCode);
+      errorType.count++;
+
+      // 只保存前 2 个样本
+      if (errorType.samples.length < 2) {
+        errorType.samples.push(errorObj);
+      }
+
+      // 每 100 个输出进度
+      if (parsedCount % 100 === 0) {
+        process.stdout.write(`\r   已解析 ${parsedCount} 个错误...`);
+      }
+    }
+  }
+
+  if (parsedCount > 0) {
+    process.stdout.write(`\r   已解析 ${parsedCount} 个错误...完成\n\n`);
+  }
+
+  return errorsByType;
+}
+
+/**
+ * 生成 Markdown 报告
+ */
+function generateMarkdownReport(errorsByType) {
+  let report = "";
+
+  report += "# TypeScript 错误分析报告\n\n";
+  report += `生成时间: ${new Date().toLocaleString("zh-CN")}\n\n`;
+  report += "=".repeat(80) + "\n\n";
+
+  // 统计
+  const totalErrors = Array.from(errorsByType.values()).reduce(
+    (sum, e) => sum + e.count,
+    0
+  );
+  report += "## 📊 错误统计\n\n";
+  report += `- **总错误数**: ${totalErrors}\n`;
+  report += `- **错误类型**: ${errorsByType.size} 种\n\n`;
+
+  // 排序
+  const sortedErrors = Array.from(errorsByType.values()).sort(
+    (a, b) => b.count - a.count
+  );
+
+  report += "### 错误分布\n\n";
+  report += "| 排名 | 错误代码 | 数量 | 占比 | 描述 |\n";
+  report += "|------|---------|------|------|------|\n";
+
+  sortedErrors.forEach((error, index) => {
+    const percentage = ((error.count / totalErrors) * 100).toFixed(1);
+    const desc =
+      error.description.substring(0, 60) +
+      (error.description.length > 60 ? "..." : "");
+    report += `| ${index + 1} | ${error.code} | ${error.count} | ${percentage}% | ${desc} |\n`;
+  });
+
+  report += "\n" + "=".repeat(80) + "\n\n";
+
+  // 详细样本
+  report += "## 📋 错误详细样本 (每种类型 2 个)\n\n";
+
+  sortedErrors.forEach((error, index) => {
+    report += `### ${index + 1}. ${error.code} - ${error.count} 个错误\n\n`;
+    report += `**完整描述**: ${error.description}\n\n`;
+
+    if (error.samples.length > 0) {
+      report += "**样本:**\n\n";
+      error.samples.forEach((sample, sampleIndex) => {
+        report += `#### 样本 ${sampleIndex + 1}\n\n`;
+        report += "```\n";
+        report += `${sample.fullError}\n`;
+        report += "```\n\n";
+      });
+    }
+
+    report += "---\n\n";
+  });
+
+  return report;
+}
+
+/**
+ * 生成 JSON 报告
+ */
+function generateJsonReport(errorsByType) {
+  const sortedErrors = Array.from(errorsByType.values()).sort(
+    (a, b) => b.count - a.count
+  );
+
+  return JSON.stringify(
+    {
+      generatedAt: new Date().toISOString(),
+      summary: {
+        totalErrors: sortedErrors.reduce((sum, e) => sum + e.count, 0),
+        errorTypes: errorsByType.size,
+      },
+      errors: sortedErrors.map((error) => ({
+        code: error.code,
+        count: error.count,
+        description: error.description,
+        percentage: (
+          (error.count / sortedErrors.reduce((sum, e) => sum + e.count, 0)) *
+          100
+        ).toFixed(2),
+        samples: error.samples,
+      })),
+    },
+    null,
+    2
+  );
+}
+
+/**
+ * 主函数
+ */
+function main() {
+  // 获取错误
+  const errorOutput = getTscErrors();
+
+  if (!errorOutput || errorOutput.trim().length === 0) {
+    console.log("✅ 没有 TypeScript 错误!\n");
+    return;
+  }
+
+  // 保存原始输出
+  saveRawOutput(errorOutput);
+
+  // 解析错误
+  const errorsByType = parseErrors(errorOutput);
+
+  if (errorsByType.size === 0) {
+    console.log("⚠️  无法解析错误信息\n");
+    console.log("💡 请检查 tsc-raw-output.txt 查看原始输出\n");
+    return;
+  }
+
+  // 生成报告
+  console.log("📝 正在生成报告...\n");
+  const mdReport = generateMarkdownReport(errorsByType);
+  const jsonReport = generateJsonReport(errorsByType);
+
+  // 保存文件
+  const mdPath = path.join(__dirname, "..", "tsc-errors-report.md");
+  const jsonPath = path.join(__dirname, "..", "tsc-errors-report.json");
+
+  fs.writeFileSync(mdPath, mdReport, "utf-8");
+  fs.writeFileSync(jsonPath, jsonReport, "utf-8");
+
+  // 输出摘要
+  const sortedErrors = Array.from(errorsByType.values()).sort(
+    (a, b) => b.count - a.count
+  );
+
+  const totalErrors = sortedErrors.reduce((sum, e) => sum + e.count, 0);
+
+  console.log("=".repeat(80));
+  console.log("✅ 分析完成");
+  console.log("=".repeat(80));
+  console.log(`\n📊 总错误数: ${totalErrors}`);
+  console.log(`📊 错误类型: ${errorsByType.size} 种\n`);
+
+  console.log("Top 10 错误类型:\n");
+  sortedErrors.slice(0, 10).forEach((error, index) => {
+    const percentage = ((error.count / totalErrors) * 100).toFixed(1);
+    const countStr = String(error.count).padStart(4);
+    const pctStr = String(percentage).padStart(5);
+    console.log(
+      `  ${(index + 1).toString().padStart(2)}. ${error.code.padEnd(8)} ${countStr} 个 (${pctStr}%)`
+    );
+  });
+
+  console.log("\n" + "=".repeat(80));
+  console.log("📄 报告已生成:\n");
+  console.log(`  - tsc-errors-report.md`);
+  console.log(`  - tsc-errors-report.json`);
+  console.log("=".repeat(80) + "\n");
+
+  console.log("💡 下一步:\n");
+  console.log("  cat ../tsc-errors-report.md\n");
+  console.log("  把报告内容发给 AI,获取修复方案\n");
+}
+
+main();