package com.codechecker.cache.analyze; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Stream; /** * 扫描工作树中受包含/排除模块限制的 {@code src/main/java} 下的所有 Java 源文件。 *

返回路径 → 源码内容映射,供 {@link SchemaCheckAnalyzer} 构建新旧 {@code SourceIndex}。

*/ public class FileScanner { private final Path repoRoot; private final List includeModules; private final List excludeModules; public FileScanner(Path repoRoot, List includeModules, List excludeModules) { this.repoRoot = repoRoot; this.includeModules = includeModules; this.excludeModules = excludeModules; } /** * @return 相对仓库根(/ 分隔)-> 文件内容 */ public Map scan() { Map result = new LinkedHashMap<>(); try (Stream stream = Files.walk(repoRoot)) { List javaFiles = stream .filter(Files::isRegularFile) .filter(p -> p.toString().endsWith(".java")) .filter(p -> { String rel = repoRoot.relativize(p).toString().replace('\\', '/'); return rel.contains("/src/main/java/") && moduleAllowed(rel); }) .collect(java.util.stream.Collectors.toList()); javaFiles.parallelStream().forEach(p -> { String rel = repoRoot.relativize(p).toString().replace('\\', '/'); try { synchronized (result) { result.put(rel, new String(Files.readAllBytes(p), StandardCharsets.UTF_8)); } } catch (IOException e) { throw new UncheckedIOException(e); } }); } catch (IOException e) { throw new UncheckedIOException(e); } return result; } boolean moduleAllowed(String relPath) { String topModule = relPath.contains("/") ? relPath.substring(0, relPath.indexOf('/')) : relPath; if (excludeModules != null && excludeModules.contains(topModule)) { return false; } if (includeModules == null || includeModules.isEmpty()) { return true; } return includeModules.contains(topModule); } }