first commit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package com.codechecker.api.parser;
|
||||
|
||||
import com.codechecker.git.GitChangeScanner;
|
||||
import com.codechecker.model.FieldInfo;
|
||||
import com.codechecker.parser.ClassFieldParser;
|
||||
import com.codechecker.parser.TypeNameUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 递归展开 Dto/Vo 嵌套字段(dot path),与类变更字段解析解耦但复用 ClassFieldParser。
|
||||
*/
|
||||
public class NestedDtoFieldParser {
|
||||
private static final Set<String> LEAF_TYPES = Set.of(
|
||||
"String", "Integer", "int", "Long", "long", "Boolean", "boolean", "Double", "double",
|
||||
"Float", "float", "Short", "short", "Byte", "byte", "Character", "char",
|
||||
"BigDecimal", "BigInteger", "Date", "LocalDate", "LocalDateTime", "LocalTime",
|
||||
"Instant", "Timestamp", "Object", "Void", "void"
|
||||
);
|
||||
|
||||
private final ClassFieldParser classFieldParser = new ClassFieldParser();
|
||||
private final JavaSourceLocator sourceLocator;
|
||||
private final GitChangeScanner gitScanner;
|
||||
private final String oldSha;
|
||||
private final String newSha;
|
||||
private final int maxDepth;
|
||||
|
||||
public NestedDtoFieldParser(Path repoRoot, List<String> searchDirs,
|
||||
GitChangeScanner gitScanner, String oldSha, String newSha, int maxDepth) {
|
||||
this.sourceLocator = new JavaSourceLocator(repoRoot, searchDirs);
|
||||
this.gitScanner = gitScanner;
|
||||
this.oldSha = oldSha;
|
||||
this.newSha = newSha;
|
||||
this.maxDepth = maxDepth;
|
||||
}
|
||||
|
||||
public List<NestedFieldInfo> parseNestedFieldsAtOldCommit(String dtoClassName) throws IOException {
|
||||
return parseNestedFields(dtoClassName, oldSha);
|
||||
}
|
||||
|
||||
public List<NestedFieldInfo> parseNestedFieldsAtNewCommit(String dtoClassName) throws IOException {
|
||||
return parseNestedFields(dtoClassName, newSha);
|
||||
}
|
||||
|
||||
private List<NestedFieldInfo> parseNestedFields(String dtoClassName, String sha) throws IOException {
|
||||
Set<String> visiting = new HashSet<>();
|
||||
List<NestedFieldInfo> result = new ArrayList<>();
|
||||
collectFields(dtoClassName, "", visiting, result, sha, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void collectFields(String className, String prefix, Set<String> visiting,
|
||||
List<NestedFieldInfo> out, String sha, int depth) throws IOException {
|
||||
if (className == null || className.isBlank() || visiting.contains(className) || depth > maxDepth) {
|
||||
return;
|
||||
}
|
||||
visiting.add(className);
|
||||
Optional<String> source = readSource(className, sha);
|
||||
if (source.isEmpty()) {
|
||||
visiting.remove(className);
|
||||
return;
|
||||
}
|
||||
List<FieldInfo> fields = classFieldParser.parseFields(source.get(), className);
|
||||
for (FieldInfo field : fields) {
|
||||
String path = prefix.isBlank() ? field.getName() : prefix + "." + field.getName();
|
||||
Set<String> nestedTypes = TypeNameUtils.peelDirectTypeNames(field.getType());
|
||||
boolean expanded = false;
|
||||
for (String nestedType : nestedTypes) {
|
||||
if (isLeafType(nestedType) || nestedType.equals(className)) {
|
||||
continue;
|
||||
}
|
||||
expanded = true;
|
||||
// 嵌套字段路径用类型简单类名(如 UserSelfDto.nickName),不用成员名(userDtos.nickName)
|
||||
collectFields(nestedType, nestedType, visiting, out, sha, depth + 1);
|
||||
}
|
||||
if (!expanded) {
|
||||
out.add(new NestedFieldInfo(path, field.getType(), field.getDescription()));
|
||||
}
|
||||
}
|
||||
visiting.remove(className);
|
||||
}
|
||||
|
||||
private Optional<String> readSource(String className, String sha) throws IOException {
|
||||
if (sha != null && gitScanner != null) {
|
||||
return sourceLocator.readSourceAtCommit(gitScanner, sha, className);
|
||||
}
|
||||
return sourceLocator.readSourceBySimpleName(className);
|
||||
}
|
||||
|
||||
private boolean isLeafType(String simpleType) {
|
||||
return LEAF_TYPES.contains(simpleType) || simpleType.endsWith("[]");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user