项目结构变更
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user