项目结构变更

This commit is contained in:
2026-06-09 11:20:24 +08:00
parent fb6cd124c8
commit 871823b3da
45 changed files with 222 additions and 223 deletions

View File

@@ -0,0 +1,127 @@
package com.codechecker.analyzer;
import com.codechecker.config.AppConfig;
import com.codechecker.git.GitChangeScanner;
import com.codechecker.model.ChangedClassFile;
import com.codechecker.model.ClassChangeKind;
import com.codechecker.model.ClassChangeReport;
import com.codechecker.model.FieldChange;
import com.codechecker.model.FieldInfo;
import com.codechecker.parser.ClassDeclParser;
import com.codechecker.parser.ClassFieldParser;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 编排 git 扫描、字段 diff、影响分析生成待通知的 ClassChangeReport 列表。
*/
public class ClassChangeAnalyzer {
private final GitChangeScanner gitScanner;
private final ClassFieldParser classFieldParser = new ClassFieldParser();
private final FieldDiffEngine fieldDiffEngine = new FieldDiffEngine();
private final ImpactAnalyzer impactAnalyzer = new ImpactAnalyzer();
private final ClassDeclParser classDeclParser = new ClassDeclParser();
public ClassChangeAnalyzer(GitChangeScanner gitScanner) {
this.gitScanner = gitScanner;
}
/** 扫描变更文件并逐条分析,无实质变更的 MODIFIED 会被跳过 */
public List<ClassChangeReport> analyze(Path repoRoot, AppConfig config, String oldSha, String newSha,
Map<String, com.codechecker.model.ApiEndpoint> endpointIndex) throws IOException {
List<ChangedClassFile> changedFiles = gitScanner.scanChangedClasses(oldSha, newSha);
List<ClassChangeReport> reports = new ArrayList<>();
for (ChangedClassFile changedFile : changedFiles) {
if (changedFile.getStatus() == ChangedClassFile.ChangeStatus.DELETED) {
reports.add(analyzeDeleted(changedFile, config, repoRoot, oldSha, endpointIndex));
continue;
}
ClassChangeReport report = analyzeModifiedOrRenamed(changedFile, config, repoRoot, oldSha, newSha, endpointIndex);
if (report != null) {
reports.add(report);
}
}
return reports;
}
/** 处理删除:标记 DELETED 并分析影响(基于旧源码) */
private ClassChangeReport analyzeDeleted(ChangedClassFile changedFile, AppConfig config, Path repoRoot,
String oldSha, Map<String, com.codechecker.model.ApiEndpoint> endpointIndex)
throws IOException {
String path = changedFile.getRelativePath();
String oldSource = gitScanner.readFileAtCommit(oldSha, path);
String classDescription = classDeclParser.extractClassDescription(
oldSource, changedFile.getClassName());
ClassChangeReport report = new ClassChangeReport(
changedFile.getClassName(),
null,
changedFile.getClassType(),
ClassChangeKind.DELETED,
path,
config.isDtoEntityConversionEnabled(),
classDescription
);
impactAnalyzer.analyze(report, endpointIndex, config, repoRoot, oldSource, oldSource);
return report;
}
/** 处理修改/重命名:字段 diff → 判定 changeKind → 影响分析 */
private ClassChangeReport analyzeModifiedOrRenamed(ChangedClassFile changedFile, AppConfig config,
Path repoRoot, String oldSha, String newSha,
Map<String, com.codechecker.model.ApiEndpoint> endpointIndex)
throws IOException {
String oldPath = changedFile.pathForOldCommit();
String newPath = changedFile.getRelativePath();
String oldSource = gitScanner.readFileAtCommit(oldSha, oldPath);
String newSource = gitScanner.readFileAtCommit(newSha, newPath);
if (newSource == null || newSource.isBlank()) {
newSource = gitScanner.readFileAtHead(newPath);
}
String oldFallback = ClassDeclParser.classNameFromPath(oldPath);
String newFallback = ClassDeclParser.classNameFromPath(newPath);
String oldClassName = changedFile.getOldClassName() != null
? changedFile.getOldClassName()
: classDeclParser.resolveClassName(oldSource, oldFallback);
String newClassName = classDeclParser.resolveClassName(newSource, newFallback);
List<FieldInfo> oldFields = classFieldParser.parseFields(oldSource, oldClassName);
List<FieldInfo> newFields = classFieldParser.parseFields(newSource, newClassName);
List<FieldChange> fieldChanges = fieldDiffEngine.diff(oldFields, newFields);
boolean renamed = !oldClassName.equals(newClassName);
ClassChangeKind changeKind;
if (renamed && fieldChanges.isEmpty()) {
changeKind = ClassChangeKind.RENAME_ONLY;
} else if (renamed) {
changeKind = ClassChangeKind.RENAME_AND_FIELDS;
} else if (!fieldChanges.isEmpty()) {
changeKind = ClassChangeKind.FIELDS_ONLY;
} else {
return null;
}
String classDescription = classDeclParser.extractClassDescription(newSource, newClassName);
ClassChangeReport report = new ClassChangeReport(
newClassName,
renamed ? oldClassName : null,
changedFile.getClassType(),
changeKind,
newPath,
config.isDtoEntityConversionEnabled(),
classDescription
);
fieldChanges.forEach(report::addFieldChange);
impactAnalyzer.analyze(report, endpointIndex, config, repoRoot, newSource, oldSource);
return report;
}
}