package com.aicheck.parser; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.TypeDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Stream; /** * 扫描 Dto→Entity 转换关系:convert 方法返回值、BeanUtils.copyProperties 调用。 */ public class ConversionParser { /** 在类内查找 convert 方法,收集返回 Entity 的类型名 */ public Set findConvertTargetsInClass(String source, String className) { Set entities = new LinkedHashSet<>(); if (source == null || source.isBlank()) { return entities; } CompilationUnit cu = StaticJavaParser.parse(source); for (TypeDeclaration type : cu.getTypes()) { if (type instanceof ClassOrInterfaceDeclaration) { ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) type; if (!classDecl.getNameAsString().equals(className)) { continue; } for (MethodDeclaration method : classDecl.getMethods()) { if (!"convert".equals(method.getNameAsString())) { continue; } String returnType = TypeNameUtils.simpleName(TypeNameUtils.typeToString(method.getType())); if (returnType.endsWith("Entity")) { entities.add(returnType); } } } } return entities; } /** 递归扫描目录,查找 BeanUtils.copyProperties(sourceClass, *Entity) */ public Set findBeanUtilsTargets(Path rootDir, String sourceClassName) throws IOException { Set entities = new LinkedHashSet<>(); if (!Files.exists(rootDir)) { return entities; } try (Stream paths = Files.walk(rootDir)) { paths.filter(path -> path.toString().endsWith(".java")).forEach(path -> { try { String source = Files.readString(path, StandardCharsets.UTF_8); entities.addAll(scanBeanUtilsInSource(source, sourceClassName)); } catch (IOException ignored) { // 跳过 } }); } return entities; } /** 在单文件源码中扫描 BeanUtils.copyProperties 调用 */ private Set scanBeanUtilsInSource(String source, String sourceClassName) { Set entities = new LinkedHashSet<>(); CompilationUnit cu = StaticJavaParser.parse(source); cu.accept(new VoidVisitorAdapter() { @Override public void visit(MethodCallExpr call, Void arg) { super.visit(call, arg); if (!call.getNameAsString().equals("copyProperties")) { return; } if (call.getScope().isEmpty()) { return; } String scope = call.getScope().get().toString(); if (!scope.endsWith("BeanUtils")) { return; } if (call.getArguments().size() < 2) { return; } String firstArg = TypeNameUtils.simpleName(call.getArguments().get(0).toString()); String secondArg = TypeNameUtils.simpleName(call.getArguments().get(1).toString()); if (sourceClassName.equals(firstArg) && secondArg.endsWith("Entity")) { entities.add(secondArg); } } }, null); return entities; } }