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 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 parseClassFields(ClassOrInterfaceDeclaration classDecl) { Map 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 javadoc = fieldDecl.getJavadocComment(); if (javadoc.isEmpty()) { return ""; } String text = javadoc.get().parse().getDescription().toText(); return text == null ? "" : text.trim().replaceAll("\\s+", " "); } }