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

2019-8-24 09:37 2085 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. 命令行软件工具的命令格式有哪些规范? -- 似乎没有特定规范, 或者至少是不强制. 但对于新用户来说, 没有任何帮助
的特殊命令格式的体验简直是够了. 所以我们加了
  1. -help -path= -filestype=
在命令行中进行参数约定,
这种感觉是不是好多了?


代码如下:
  1. // app.js
  2. const fs = require('fs');
  3. const path = require('path');
  4. // usage:
  5. //
  6. // command:
  7. // <node app> or <node app -path='yourpath' -filetypes= '.ext1' '.ext2'>
  8. //
  9. // eg: node app
  10. // output: current project dirctory code_sum with "".js", ".html", ".css" files, except for [node_modules]
  11. //
  12. // e.g: node app -path=e:\yourproject -filestype= .js .html
  13. // output: your project directory with ".js" and ".html" files, except for [node_modules]
  14. // Author: Allen Zhan; allen_zhan#163.com
  15. let sum = 0;
  16. let rootpath; // path
  17. let filter = ["node_modules"];
  18. let filestype; // files' type
  19. const argv = process.argv;
  20. let initLayer = 0; // init root diretory tree depth
  21. // -path=
  22. function readParamPath(readpath) {
  23. rootpath = readpath;
  24. const constPath = "-path=";
  25. // console.log(rootpath.length);
  26. // console.log(constPath.length);
  27. if (rootpath.length <= constPath.length) {
  28. return -1;
  29. } else {
  30. let comparePath = rootpath.substring(0, constPath.length);
  31. // console.log(comparePath);
  32. if (comparePath == constPath) {
  33. rootpath = rootpath.substring(constPath.length);
  34. // console.log(rootpath);
  35. return 0;
  36. } else {
  37. return -2;
  38. }
  39. }
  40. }
  41. // -filestype=
  42. function readParamFilesType(readtype) {
  43. if (readtype == "-filestype=") {
  44. return 0;
  45. }
  46. return -1;
  47. }
  48. // full command: node app -path='yourpath' -filetypes='yourfiles'
  49. // e.g: node app -path=e:\\myproject -filestype= .js .html .css
  50. function readParam() {
  51. // for each parameters
  52. // console.log(argv.length);
  53. // for(let i=0; i<argv.length; i++) {
  54. // console.log(argv[i]);
  55. // }
  56. if (argv.length < 2) {
  57. return -1;
  58. }
  59. // default format
  60. if (argv.length == 2) {
  61. rootpath = argv[1];
  62. rootpath = rootpath == '' ? '' : rootpath.substring(0, rootpath.lastIndexOf('\\'));
  63. // console.log(rootpath);
  64. filestype = [".js", ".html", ".css"];
  65. return 0;
  66. }
  67. // defined with "-path="
  68. if (argv.length == 3) {
  69. let inputPath = readParamPath(argv[2]);
  70. // console.log(inputPath);
  71. if (inputPath < 0) {
  72. // if err input "-filestype="
  73. let inputFilesType = readParamFilesType(argv[2]);
  74. console.log(inputFilesType);
  75. if (inputFilesType >= 0) {
  76. return -3;
  77. }
  78. return -2;
  79. } else {
  80. filestype = [".js", ".html", ".css"];
  81. return 0;
  82. }
  83. }
  84. // read "-filestype=" with "-path=" or without "-path="
  85. if (argv.length > 3) {
  86. // defined "-path=" or not?
  87. let inputPath = readParamPath(argv[2]);
  88. // console.log(inputPath);
  89. if (inputPath >= 0) {
  90. if (argv.length == 4) {
  91. return -3;
  92. }
  93. let inputFilesType = readParamFilesType(argv[3]);
  94. if (inputFilesType < 0) {
  95. return -3;
  96. } else {
  97. filestype = argv.splice(4);
  98. return 0;
  99. }
  100. } else {
  101. rootpath = argv[1];
  102. rootpath = rootpath == '' ? '' : rootpath.substring(0, rootpath.lastIndexOf('\\'));
  103. let inputFilesType = readParamFilesType(argv[2]);
  104. if (inputFilesType < 0) {
  105. return -3;
  106. } else {
  107. filestype = argv.splice(3);
  108. return 0;
  109. }
  110. }
  111. }
  112. }
  113. function init() {
  114. // node app -help
  115. if ((argv.length == 3) && (argv[2] == "-help")) {
  116. console.log("\ncommand: <node app> or <node app -path='yourpath' -filetypes='yourfiles'>\
  117. \ne.g:\
  118. \nnode app\
  119. \nnode app -path=e:\\myproject\
  120. \nnode app -filestype=.js\
  121. \nnode app -path=e:\\myproject -filestype=.js\
  122. \nnode app -path=e:\\myproject -filestype=.js .html .css\n");
  123. return -1;
  124. }
  125. let readResult = readParam();
  126. if (readResult < 0) {
  127. console.log(`\nErr: Bad command format with Errcode: ${readResult}, please try <node app -help>.`);
  128. const errcode = "Errcode: -1, command parameters length is err\
  129. \nErrcode: -2, err parameter with '-path='\
  130. \nErrcode: -3, err parameter with '-filestype='\n";
  131. console.log(errcode);
  132. return -2;
  133. }
  134. }
  135. // get diretory depth
  136. function getCharNum(str, ch) {
  137. let ret = 0;
  138. for (var i = 0; i < str.length; i++) {
  139. if (str.charAt(i) == ch) ret++;
  140. }
  141. return ret;
  142. }
  143. function getDirDepth(strPath) {
  144. let layer1 = getCharNum(strPath, '\\');
  145. let layer2 = getCharNum(strPath, '/');
  146. let maxDepth;
  147. if (layer1 >= layer2) {
  148. maxDepth = layer1;
  149. } else {
  150. maxDepth = layer2;
  151. }
  152. return maxDepth;
  153. }
  154. function getCurDepth(strPath) {
  155. let depth = getDirDepth(strPath);
  156. if (depth < initLayer) {
  157. return 0;
  158. } else {
  159. return (depth - initLayer);
  160. }
  161. }
  162. // getLine
  163. function getLine(path) {
  164. let data = fs.readFileSync(path);
  165. data = data.toString();
  166. let lines = data.split('\n');
  167. // console.log(path + ' ' + lines.length);
  168. return lines.length;
  169. }
  170. // expend the diretory tree
  171. function expend(pathTree) {
  172. let files = fs.readdirSync(pathTree);
  173. files.forEach((file) => {
  174. let stat = fs.statSync(pathTree + "\" + file);
  175. // format diretory tree output
  176. let layer = getCurDepth(pathTree + "\" + file);
  177. layer--;
  178. let tabStr = "";
  179. while (layer--) {
  180. tabStr = tabStr + "|----";
  181. }
  182. // diretory tree output
  183. if (stat.isDirectory()) {
  184. // neglect "node_modules" diretory
  185. if (filter.indexOf(file) == -1) {
  186. console.log(tabStr + "[+]" + file);
  187. expend(pathTree + "\" + file);
  188. }
  189. } else {
  190. // fit for filestype
  191. let ext = path.extname(file);
  192. if (filestype.indexOf(ext) >= 0) {
  193. let lines = getLine(pathTree + "\" + file);
  194. sum += lines; // calc total rows
  195. console.log(tabStr + file + ` :${lines}`);
  196. }
  197. }
  198. });
  199. }
  200. function start() {
  201. let files;
  202. try {
  203. console.log("-- Program Start --\n");
  204. console.log("Target: " + rootpath);
  205. console.log("filter:");
  206. console.log(filter);
  207. console.log("filesType:");
  208. console.log(filestype);
  209. console.log("");
  210. // null diretories?
  211. files = fs.readdirSync(rootpath);
  212. let filesLen = files.length;
  213. // console.log(filesLen);
  214. if (filesLen == 0) {
  215. console.log("Null Diretory");
  216. return;
  217. }
  218. // init diretory depth
  219. initLayer = getDirDepth(rootpath);
  220. // console.log(initLayer);
  221. // expend all diretories and show theTree
  222. expend(rootpath);
  223. // show result:
  224. console.log(`\nTotal: ${sum}`);
  225. } catch (err) {
  226. // console.log(err);
  227. if (err.code === "ENOENT") {
  228. console.log("Diretory not found");
  229. } else if (err.code === "ENOTDIR") {
  230. console.log("not a Diretory");
  231. } else {
  232. throw err;
  233. }
  234. }
  235. console.log("\n-- Program End --");
  236. }
  237. // main()
  238. (() => {
  239. if (init() < 0) {
  240. return;
  241. }
  242. start();
  243. })();

使用方式见: "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

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

文章评论0条评论)

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