|
|
@@ -0,0 +1,152 @@
|
|
|
+package cn.reghao.devops.mgr.util.codelines;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.nio.file.*;
|
|
|
+import java.nio.file.attribute.BasicFileAttributes;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 统计代码行数
|
|
|
+ *
|
|
|
+ * @author reghao
|
|
|
+ * @date 2021-08-10 下午4:54
|
|
|
+ */
|
|
|
+public class LinesOfCode {
|
|
|
+ private String projectDir;
|
|
|
+ private int totalLines;
|
|
|
+ private int totalFiles;
|
|
|
+ private Matcher matcher;
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * @param projectDir 项目路径
|
|
|
+ * @param matcher 源代码类型
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ public LinesOfCode(String projectDir, Matcher matcher) {
|
|
|
+ this.projectDir = projectDir;
|
|
|
+ this.matcher = matcher;
|
|
|
+ this.totalLines = 0;
|
|
|
+ this.totalFiles = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 代码总行数
|
|
|
+ *
|
|
|
+ * @return 代码总行数
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ public int totalLines() {
|
|
|
+ return totalLines;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 源文件数量
|
|
|
+ *
|
|
|
+ * @return 源文件数量
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ public int totalFiles() {
|
|
|
+ return totalFiles;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算代码总行数和源文件数量
|
|
|
+ *
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ public int calculate() {
|
|
|
+ Path path = Paths.get(projectDir);
|
|
|
+ try {
|
|
|
+ walkDir(path);
|
|
|
+ } catch (IOException ioe) {
|
|
|
+ ioe.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ return totalLines;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 遍历目录树并处理文件
|
|
|
+ *
|
|
|
+ * @param path 目录根路径
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ private void walkDir(Path path) throws IOException {
|
|
|
+ final String BLANK = "";
|
|
|
+ if (path.toString().equals(BLANK)) {
|
|
|
+ throw new IOException("CAN NOT specify a BLANK path");
|
|
|
+ }
|
|
|
+
|
|
|
+ Files.walkFileTree(path, new FileVisitor<Path>() {
|
|
|
+ @Override
|
|
|
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
|
|
+ String suffix = fileSuffix(file.toString());
|
|
|
+ if (matcher.matchSuffix(suffix)) {
|
|
|
+ totalLines += linesOfFile(file.toFile(), matcher);;
|
|
|
+ totalFiles++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统计源文件包含多少行代码
|
|
|
+ *
|
|
|
+ * @param file 源文件
|
|
|
+ * @param matcher 匹配器
|
|
|
+ * @return 每个源文件包含的代码行数
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ private int linesOfFile(File file, Matcher matcher) {
|
|
|
+ int count = 0;
|
|
|
+ try {
|
|
|
+ BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
|
|
+ String line;
|
|
|
+ while ((line = in.readLine()) != null) {
|
|
|
+ if (!matcher.match(line)) {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException ioe) {
|
|
|
+ ioe.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件的后缀名
|
|
|
+ *
|
|
|
+ * @param filePath 文件路径
|
|
|
+ * @return 文件后缀名
|
|
|
+ * @date 2021-08-10 下午4:55
|
|
|
+ */
|
|
|
+ private String fileSuffix(String filePath) {
|
|
|
+ String[] paths = filePath.split("/");
|
|
|
+ String file = paths[paths.length-1];
|
|
|
+
|
|
|
+ if (file.contains(".")) {
|
|
|
+ return file.split("\\.")[1];
|
|
|
+ } else {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|