136 lines
5.3 KiB
Java
136 lines
5.3 KiB
Java
package com.aicheck.parser;
|
||
|
||
import com.aicheck.model.FieldInfo;
|
||
import com.github.javaparser.StaticJavaParser;
|
||
import com.github.javaparser.ast.CompilationUnit;
|
||
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
||
import com.github.javaparser.ast.body.FieldDeclaration;
|
||
import com.github.javaparser.ast.body.TypeDeclaration;
|
||
import com.github.javaparser.ast.body.VariableDeclarator;
|
||
import com.github.javaparser.ast.comments.JavadocComment;
|
||
import com.github.javaparser.ast.expr.AnnotationExpr;
|
||
import com.github.javaparser.ast.expr.Expression;
|
||
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
|
||
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.LinkedHashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Optional;
|
||
|
||
/**
|
||
* 解析模型类字段:名称、类型、业务说明(注解或 Javadoc)。
|
||
*/
|
||
public class ClassFieldParser {
|
||
|
||
/** 解析指定类的实例字段列表 */
|
||
public List<FieldInfo> parseFields(String source, String expectedClassName) {
|
||
if (source == null || source.isBlank()) {
|
||
return List.of();
|
||
}
|
||
CompilationUnit cu = StaticJavaParser.parse(source);
|
||
ClassOrInterfaceDeclaration classDecl = findClass(cu, expectedClassName);
|
||
if (classDecl == null) {
|
||
return List.of();
|
||
}
|
||
return parseClassFields(classDecl);
|
||
}
|
||
|
||
/** 按类名查找类声明,找不到则取第一个类 */
|
||
private ClassOrInterfaceDeclaration findClass(CompilationUnit cu, String expectedClassName) {
|
||
if (expectedClassName != null && !expectedClassName.isBlank()) {
|
||
for (TypeDeclaration<?> type : cu.getTypes()) {
|
||
if (type instanceof ClassOrInterfaceDeclaration) {
|
||
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) type;
|
||
if (classDecl.getNameAsString().equals(expectedClassName)) {
|
||
return classDecl;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
for (TypeDeclaration<?> type : cu.getTypes()) {
|
||
if (type instanceof ClassOrInterfaceDeclaration) {
|
||
return (ClassOrInterfaceDeclaration) type;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/** 提取非 static final 字段,跳过常量 */
|
||
private List<FieldInfo> parseClassFields(ClassOrInterfaceDeclaration classDecl) {
|
||
Map<String, FieldInfo> fields = new LinkedHashMap<>();
|
||
for (FieldDeclaration fieldDecl : classDecl.getFields()) {
|
||
if (fieldDecl.isStatic() && fieldDecl.isFinal()) {
|
||
continue;
|
||
}
|
||
String type = TypeNameUtils.typeToString(fieldDecl.getElementType());
|
||
String description = extractFieldLabel(fieldDecl);
|
||
for (VariableDeclarator variable : fieldDecl.getVariables()) {
|
||
fields.put(variable.getNameAsString(), new FieldInfo(variable.getNameAsString(), type, description));
|
||
}
|
||
}
|
||
return new ArrayList<>(fields.values());
|
||
}
|
||
|
||
/**
|
||
* 字段说明:@Schema(description) > @ApiModelProperty > Javadoc,均无则空串。
|
||
*/
|
||
String extractFieldLabel(FieldDeclaration fieldDecl) {
|
||
for (AnnotationExpr annotation : fieldDecl.getAnnotations()) {
|
||
String annName = annotation.getNameAsString();
|
||
if ("Schema".equals(annName)) {
|
||
String description = readAnnotationStringValue(annotation, "description");
|
||
if (!description.isEmpty()) {
|
||
return description;
|
||
}
|
||
}
|
||
if ("ApiModelProperty".equals(annName)) {
|
||
String value = readAnnotationStringValue(annotation, "value");
|
||
if (!value.isEmpty()) {
|
||
return value;
|
||
}
|
||
}
|
||
}
|
||
return extractJavadoc(fieldDecl);
|
||
}
|
||
|
||
/** 读取注解中的字符串属性值 */
|
||
private String readAnnotationStringValue(AnnotationExpr annotation, String attributeName) {
|
||
if (annotation.isNormalAnnotationExpr()) {
|
||
NormalAnnotationExpr normal = annotation.asNormalAnnotationExpr();
|
||
for (var pair : normal.getPairs()) {
|
||
if (pair.getNameAsString().equals(attributeName)) {
|
||
return literalString(pair.getValue());
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
if (annotation.isSingleMemberAnnotationExpr()) {
|
||
SingleMemberAnnotationExpr single = annotation.asSingleMemberAnnotationExpr();
|
||
if ("value".equals(attributeName) || "description".equals(attributeName)) {
|
||
return literalString(single.getMemberValue());
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
/** 提取字符串字面量值 */
|
||
private String literalString(Expression expression) {
|
||
if (expression.isStringLiteralExpr()) {
|
||
return expression.asStringLiteralExpr().getValue().trim();
|
||
}
|
||
return "";
|
||
}
|
||
|
||
/** 从字段 Javadoc 提取首段描述 */
|
||
private String extractJavadoc(FieldDeclaration fieldDecl) {
|
||
Optional<JavadocComment> javadoc = fieldDecl.getJavadocComment();
|
||
if (javadoc.isEmpty()) {
|
||
return "";
|
||
}
|
||
String text = javadoc.get().parse().getDescription().toText();
|
||
return text == null ? "" : text.trim().replaceAll("\\s+", " ");
|
||
}
|
||
}
|