年度代码统计
年度汇报中需要统计代码的注释率、检视率、重复率....
很多统计可以从git从通过命令统计
比如
#统计具体某员工的代码提交量
git log --author=xiao.changwei--since=2020-01-01 --until=2020-12-31 --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | grep "\(.html\|.java\|.xml\|.properties\)$" | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done
#统计提交次数
$ git log |grep commit|wc -l
5335
注释率就真的不好统计了,就用最原始的方法写一个:
package com.xiao.utils; import org.springframework.util.Assert; import java.io.*; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import static java.util.stream.Collectors.*; /** * @author xiao.changwei */ public class CodeStatistics { private static final String rootPath = "D:\\code\\cx"; //因包含过多第三方js库,js库不做统计 private static final List<String> staticsFileSuffixes = Arrays.asList("java", "xml", "sql", "conf", "properties", "yaml", "yml", "html"); private static final List<String> excludePath = Arrays.asList("deprecated", "node_modules"); private static List<File> files = new LinkedList<>(); private static int whiteLines = 0; private static int commentLines = 0; private static int normalLines = 0; public static void main(String[] args) { File rootDir = new File(rootPath); if (rootDir.exists()) { getFileRecursively(rootDir); if (files.size() > 0) { files.forEach(file -> Statistics(file)); System.out.println("空行数:" + whiteLines); System.out.println("注释行数:" + commentLines); System.out.println("代码行数:" + normalLines); System.out.println("文件总数:" + files.size()); System.out.println("========================"); BigDecimal bigDecimal = new BigDecimal(commentLines).divide(new BigDecimal(commentLines + normalLines), 4, BigDecimal.ROUND_HALF_UP); NumberFormat percent = NumberFormat.getPercentInstance(); percent.setMaximumFractionDigits(4); System.out.println("代码注释率:" + percent.format(bigDecimal.doubleValue())); //按类型分类 Map<String, List<String>> collect = files.stream().collect(groupingBy(file -> getFileSuffix(file.getName()), mapping(File::getAbsolutePath, toList()))); } } } private static void getFileRecursively(File file) { Assert.notNull(file, "file can not be null"); if (!shouldSkip(file) && file.isDirectory()) { for (File listFile : file.listFiles()) { if (listFile.isDirectory()) { getFileRecursively(listFile); } else { if (!shouldSkip(file) && filterBySuffix(listFile)) { files.add(listFile); } } } } else { if (!shouldSkip(file) && filterBySuffix(file)) { files.add(file); } } } private static boolean shouldSkip(File file) { String absolutePath = file.getAbsolutePath(); for (String exclude : excludePath) { if (absolutePath.contains(exclude)) { return true; } } return false; } private static boolean filterBySuffix(File file) { String[] split = file.getName().split("\\."); if (split.length >= 2) { String suffix = split[split.length - 1]; if (staticsFileSuffixes.contains(suffix)) { return true; } } return false; } private static String getFileSuffix(String fileName) { String[] split = fileName.split("\\."); if (split.length >= 2) { return split[split.length - 1]; } return ""; } private static void Statistics(File file) { BufferedReader br = null; boolean comment = false; try { br = new BufferedReader(new FileReader(file)); String line = ""; try { while ((line = br.readLine()) != null) { line = line.trim(); if (line.matches("^[\\s&&[^\\n]]*$")) { whiteLines++; } else if (line.startsWith("/*") && !line.endsWith("*/")) { commentLines++; comment = true; } else if (true == comment) { commentLines++; if (line.endsWith("*/")) { comment = false; } } else if (line.startsWith("//")) { commentLines++; } else { normalLines++; } } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } }