统计指定目录下代码行数及注释率

868 阅读1分钟

最近项目上要求统计项目的注释率,于是写了个小脚本。

结果示例:

具体代码:

/**
 * 统计指定目录下代码行数及注释率
 *
 * 用法: node count.js <路径> [后缀名]...
 * 后缀名不填的话默认为统计 .js .ts 和 .vue 文件
 *
 * 示例 [统计 ./src 下的 js/ts/vue 文件]: node count.js ./src
 * 示例 [统计 ./src 下的 vue 文件]: node count.js ./src .vue
 */

const fs = require('fs')
let path = require('path')

// 获取命令行参数
const parm = process.argv.splice(2)
// 第一个参数是路径
const rootPath = parm[0]
// 后面的所有参数都是文件后缀
let types = parm.splice(1)
if (types.length === 0) types = ['.js', '.ts', '.vue']
// 需要过滤的文件夹
const filter = ['./node_modules', './.git', './.tscache', './dist', './public']
// 总计
let total = {
  path: 'total',
  length: 0,
  comment: 0,
  commentRatio: 1
}
// 统计结果
let result = []

/**
 * 对指定文件进行统计
 * 包括获取文件行数、注释及计算注释率
 *
 * @param {string} path 文件路径
 */
async function count (path) {
  const rep = await fs.readFileSync(path).toString()
  const lines = rep.split('\n')

  // 匹配出注释的行数
  const commentNum = lines.filter(line => new RegExp('^(//|/\\*|\\*|\\*/)', 'g').test(line.trimStart())).length

  result.push({
    path,
    length: lines.length,
    comment: commentNum,
    commentRatio: (Math.round(commentNum / lines.length * 10000) / 100) + '%'
  })

  updateTotal(lines.length, commentNum)
}

/**
 * 更新总计信息
 *
 * @param {number} length 新增行数
 * @param {number} comment 新增注释
 */
function updateTotal (length, comment) {
  total.length += length
  total.comment += comment
  total.commentRatio = (Math.round(total.comment / total.length * 10000) / 100) + '%'
}

/**
 * 递归所有文件夹统计
 *
 * @param {string} pt 根目录
 */
async function start (pt) {
  fs.readdirSync(pt).map(file => `${pt}/${file}`)
    .forEach(file => {
      const stat = fs.statSync(file)
      // 是文件夹就递归
      if (stat.isDirectory()) {
        if (filter.indexOf(pt) !== -1) return
        return start(file)
      }
      // 是文件并且后缀名符合就执行统计
      if (types.indexOf(path.extname(file)) !== -1) count(file)
    })
}

(async () => {
  await start(rootPath)
  result.push(total)
  console.table(result)
})()