原创 [Node.js]读取项目代码总行数

2019-8-24 09:37 2107 30 30 分类: 软件与OS
软件项目工程量的规模较难被评估, 一般来说总代码量是一个相对客观的评价参数(虽然受限诸多条件约束).
如果 IDE 是 VS 或是 Eclipse, 我们一般使用正则表达式 ^b*[^:b#/]+.*$ 进行项目搜索(极简条件下也可使用 /n).

但一般 node 项目中, 使用 VSCode 我们似没有这个便利.


Node.js 条件下, 检查项目代码总量, 一般来说应有两种方式, 使用专用软件工具, 或者是自己写作一个小工具.
-- 自行写作并不困难, 我们完成的代码行数不过 313 行(包括了相当的代码注释).
代码参考来源是: 使用 node.js 统计代码行数
这里不得不自行完全重写, 主要基于三个理由:

1. Node.js 的基本特性是异步, 参考代码的函数将同步函数用异步方式写作 -- 这几乎混淆了 Node.js 生存的理由.
2. 我们都必须用写作"高质量"的代码来要求自己, 什么是高质量的代码? -- 我个人的观点是: "不仅仅以功能实现为目的,
同时也必须处理异常", 而不是把 throw 异常交付给 runtime, 结果是异常抛出后程序多半就此中止.
3. 命令行软件工具的命令格式有哪些规范? -- 似乎没有特定规范, 或者至少是不强制. 但对于新用户来说, 没有任何帮助
的特殊命令格式的体验简直是够了. 所以我们加了
-help -path= -filestype=
复制代码
在命令行中进行参数约定,
这种感觉是不是好多了?


代码如下:
// app.js
  • const fs = require('fs');
  • const path = require('path');
  • // usage:
  • //
  • // command:
  • // <node app> or <node app -path='yourpath' -filetypes= '.ext1' '.ext2'>
  • //
  • // eg: node app
  • // output: current project dirctory code_sum with "".js", ".html", ".css" files, except for [node_modules]
  • //
  • // e.g: node app -path=e:\yourproject -filestype= .js .html
  • // output: your project directory with ".js" and ".html" files, except for [node_modules]
  • // Author: Allen Zhan; allen_zhan#163.com
  • let sum = 0;
  • let rootpath; // path
  • let filter = ["node_modules"];
  • let filestype; // files' type
  • const argv = process.argv;
  • let initLayer = 0; // init root diretory tree depth
  • // -path=
  • function readParamPath(readpath) {
  • rootpath = readpath;
  • const constPath = "-path=";
  • // console.log(rootpath.length);
  • // console.log(constPath.length);
  • if (rootpath.length <= constPath.length) {
  • return -1;
  • } else {
  • let comparePath = rootpath.substring(0, constPath.length);
  • // console.log(comparePath);
  • if (comparePath == constPath) {
  • rootpath = rootpath.substring(constPath.length);
  • // console.log(rootpath);
  • return 0;
  • } else {
  • return -2;
  • }
  • }
  • }
  • // -filestype=
  • function readParamFilesType(readtype) {
  • if (readtype == "-filestype=") {
  • return 0;
  • }
  • return -1;
  • }
  • // full command: node app -path='yourpath' -filetypes='yourfiles'
  • // e.g: node app -path=e:\\myproject -filestype= .js .html .css
  • function readParam() {
  • // for each parameters
  • // console.log(argv.length);
  • // for(let i=0; i<argv.length; i++) {
  • // console.log(argv[i]);
  • // }
  • if (argv.length < 2) {
  • return -1;
  • }
  • // default format
  • if (argv.length == 2) {
  • rootpath = argv[1];
  • rootpath = rootpath == '' ? '' : rootpath.substring(0, rootpath.lastIndexOf('\\'));
  • // console.log(rootpath);
  • filestype = [".js", ".html", ".css"];
  • return 0;
  • }
  • // defined with "-path="
  • if (argv.length == 3) {
  • let inputPath = readParamPath(argv[2]);
  • // console.log(inputPath);
  • if (inputPath < 0) {
  • // if err input "-filestype="
  • let inputFilesType = readParamFilesType(argv[2]);
  • console.log(inputFilesType);
  • if (inputFilesType >= 0) {
  • return -3;
  • }
  • return -2;
  • } else {
  • filestype = [".js", ".html", ".css"];
  • return 0;
  • }
  • }
  • // read "-filestype=" with "-path=" or without "-path="
  • if (argv.length > 3) {
  • // defined "-path=" or not?
  • let inputPath = readParamPath(argv[2]);
  • // console.log(inputPath);
  • if (inputPath >= 0) {
  • if (argv.length == 4) {
  • return -3;
  • }
  • let inputFilesType = readParamFilesType(argv[3]);
  • if (inputFilesType < 0) {
  • return -3;
  • } else {
  • filestype = argv.splice(4);
  • return 0;
  • }
  • } else {
  • rootpath = argv[1];
  • rootpath = rootpath == '' ? '' : rootpath.substring(0, rootpath.lastIndexOf('\\'));
  • let inputFilesType = readParamFilesType(argv[2]);
  • if (inputFilesType < 0) {
  • return -3;
  • } else {
  • filestype = argv.splice(3);
  • return 0;
  • }
  • }
  • }
  • }
  • function init() {
  • // node app -help
  • if ((argv.length == 3) && (argv[2] == "-help")) {
  • console.log("\ncommand: <node app> or <node app -path='yourpath' -filetypes='yourfiles'>\
  • \ne.g:\
  • \nnode app\
  • \nnode app -path=e:\\myproject\
  • \nnode app -filestype=.js\
  • \nnode app -path=e:\\myproject -filestype=.js\
  • \nnode app -path=e:\\myproject -filestype=.js .html .css\n");
  • return -1;
  • }
  • let readResult = readParam();
  • if (readResult < 0) {
  • console.log(`\nErr: Bad command format with Errcode: ${readResult}, please try <node app -help>.`);
  • const errcode = "Errcode: -1, command parameters length is err\
  • \nErrcode: -2, err parameter with '-path='\
  • \nErrcode: -3, err parameter with '-filestype='\n";
  • console.log(errcode);
  • return -2;
  • }
  • }
  • // get diretory depth
  • function getCharNum(str, ch) {
  • let ret = 0;
  • for (var i = 0; i < str.length; i++) {
  • if (str.charAt(i) == ch) ret++;
  • }
  • return ret;
  • }
  • function getDirDepth(strPath) {
  • let layer1 = getCharNum(strPath, '\\');
  • let layer2 = getCharNum(strPath, '/');
  • let maxDepth;
  • if (layer1 >= layer2) {
  • maxDepth = layer1;
  • } else {
  • maxDepth = layer2;
  • }
  • return maxDepth;
  • }
  • function getCurDepth(strPath) {
  • let depth = getDirDepth(strPath);
  • if (depth < initLayer) {
  • return 0;
  • } else {
  • return (depth - initLayer);
  • }
  • }
  • // getLine
  • function getLine(path) {
  • let data = fs.readFileSync(path);
  • data = data.toString();
  • let lines = data.split('\n');
  • // console.log(path + ' ' + lines.length);
  • return lines.length;
  • }
  • // expend the diretory tree
  • function expend(pathTree) {
  • let files = fs.readdirSync(pathTree);
  • files.forEach((file) => {
  • let stat = fs.statSync(pathTree + "\" + file);
  • // format diretory tree output
  • let layer = getCurDepth(pathTree + "\" + file);
  • layer--;
  • let tabStr = "";
  • while (layer--) {
  • tabStr = tabStr + "|----";
  • }
  • // diretory tree output
  • if (stat.isDirectory()) {
  • // neglect "node_modules" diretory
  • if (filter.indexOf(file) == -1) {
  • console.log(tabStr + "[+]" + file);
  • expend(pathTree + "\" + file);
  • }
  • } else {
  • // fit for filestype
  • let ext = path.extname(file);
  • if (filestype.indexOf(ext) >= 0) {
  • let lines = getLine(pathTree + "\" + file);
  • sum += lines; // calc total rows
  • console.log(tabStr + file + ` :${lines}`);
  • }
  • }
  • });
  • }
  • function start() {
  • let files;
  • try {
  • console.log("-- Program Start --\n");
  • console.log("Target: " + rootpath);
  • console.log("filter:");
  • console.log(filter);
  • console.log("filesType:");
  • console.log(filestype);
  • console.log("");
  • // null diretories?
  • files = fs.readdirSync(rootpath);
  • let filesLen = files.length;
  • // console.log(filesLen);
  • if (filesLen == 0) {
  • console.log("Null Diretory");
  • return;
  • }
  • // init diretory depth
  • initLayer = getDirDepth(rootpath);
  • // console.log(initLayer);
  • // expend all diretories and show theTree
  • expend(rootpath);
  • // show result:
  • console.log(`\nTotal: ${sum}`);
  • } catch (err) {
  • // console.log(err);
  • if (err.code === "ENOENT") {
  • console.log("Diretory not found");
  • } else if (err.code === "ENOTDIR") {
  • console.log("not a Diretory");
  • } else {
  • throw err;
  • }
  • }
  • console.log("\n-- Program End --");
  • }
  • // main()
  • (() => {
  • if (init() < 0) {
  • return;
  • }
  • start();
  • })();
  • 复制代码

    使用方式见: "app node -help"
    一般默认条件下, "app node" 将在本目录下计算全部 .js .html .css 的代码总行数,
    并排除了 npm 安装的 modules 的目录.

    这是输出的例子:


    P.S:  因为 fs 与 path 是 Node.js 自带 module, 因此两者无需进行 npm install,
    用户可直接打字 "node app"

    作者: allen_zhan, 来源:面包板社区

    链接: https://mbb.eet-china.com/blog/uid-me-1238440.html

    版权声明:本文为博主原创,未经本人允许,禁止转载!

    PARTNER CONTENT

    文章评论0条评论)

    登录后参与讨论
    我要评论
    0
    30
    关闭 站长推荐上一条 /3 下一条