查找缺少catch的位置

42 阅读1分钟

查找缺少catch的位置

const parser = require("@babel/parser");
const t = require("@babel/types");
const traverse = require("@babel/traverse").default;
const fs = require("fs");
const path = require("path");

// 从命令行参数中获取文件路径,默认为../src
const rootPath = process.argv[2] || "../src";
// 存储babel编译错误的信息
const babelErrorInfo = [];

/**
 * 校验expression
 */
function testExpression(expression) {
  if (expression && expression.type === "CallExpression" && expression.callee.type === "MemberExpression") {
    if (
      t.isIdentifier(expression.callee.property, { name: "then" })
      || (t.isLiteral(expression.callee.property) && expression.callee.property.value === "then")
    ) {
      return true;
    }

    if (
      (
        t.isIdentifier(expression.callee.property, { name: "finally" })
        || (t.isLiteral(expression.callee.property) && expression.callee.property.value === "finally")
      )
      && testExpression(expression.callee.object)
    ) {
      return true;
    }
  }
  return false;
}

/**
 * 发现指定文件中的promise.then没有catch
 * @param {文件路径} sourcePath
 */
function findMissingCatch(sourcePath) {
  sourcePath = path.resolve(__dirname, sourcePath);
  const code = fs.readFileSync(sourcePath).toString();
  const ast = parser.parse(code, { sourceType: "module", plugins: ["jsx", "typescript", "decorators"] });

  traverse(ast, {
    ExpressionStatement(nodePath) {
      const { node } = nodePath;
      const { expression } = node;
      if (testExpression(expression)) {
        const { line, column } = expression.loc.end;
        console.log(`${sourcePath}:${line}:${column}`);
      }
    }
  });
}

/**
 * 扫描指定目录下的文件,找到所有js和ts文件
 */
function scanDir(dirPath) {
  dirPath = path.resolve(__dirname, dirPath);
  const files = [];
  if (fs.statSync(dirPath).isDirectory()) {
    files.push(...fs.readdirSync(dirPath).map((file) => path.join(dirPath, file)));
  } else {
    files.push(dirPath);
  }
  files.forEach((file) => {
    const filePath = file;
    const stat = fs.statSync(filePath);
    if (stat.isDirectory()) {
      // 跳过node_modules
      if (/node_modules/.test(filePath)) {
        return;
      }
      scanDir(filePath);
    } else if (stat.isFile()) {
      if (/\.[tj]sx?$/.test(filePath)) {
        try {
          findMissingCatch(filePath);
        } catch (error) {
          babelErrorInfo.push(`${filePath}:${error.loc.line}:${error.loc.column}`);
        }
      }
    }
  });
}

function scan(sourcePath) {
  console.log("-----------------promise missing catch-----------------");
  scanDir(sourcePath);
  if (babelErrorInfo.length) {
    console.log("-----------------文件语法错误 error-----------------");
    babelErrorInfo.forEach((item) => {
      console.log(item);
    });
  }
  console.log("-----------------复制错误链接到剪切板,打开vscode,command+p,粘贴,回车,定位到错误行-----------------");
}

scan(rootPath);