java代码重构 接口和接口实现类合并

maven

<dependency>
            <groupId>com.github.javaparser</groupId>
            <artifactId>javaparser-core</artifactId>
            <version>3.24.0</version>
        </dependency>

代码

package com.xx;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.type.Type;
import com.shocksoft.component.util.JacksonUtil;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 接口-接口实现 合并
 */
public class ScanMain {


    private static MethodDeclaration findMatchingMethod(ClassOrInterfaceDeclaration implementationClass, String methodName, List<Type> paramTypes) {
        for (MethodDeclaration method : implementationClass.getMethods()) {
            if (method.getNameAsString().equals(methodName) && haveSameParameters(method, paramTypes)) {
                return method;
            }
        }
        return null;
    }

    private static boolean haveSameParameters(MethodDeclaration method, List<Type> paramTypes) {
        List<Type> methodParamTypes = method.getParameters().stream()
                .map(Parameter::getType)
                .collect(Collectors.toList());
        return methodParamTypes.containsAll(paramTypes) && paramTypes.containsAll(methodParamTypes);
    }

    private static void dd(MData mData) throws Exception {
        // 读取源代码文件
        JavaParser javaParser = new JavaParser();
        String api = mData.getApiFile();
        String apiImpl = mData.getApiImplFile();
        CompilationUnit apiUnit = javaParser.parse(new File(api)).getResult().get();
        CompilationUnit apiImplUnit = javaParser.parse(new File(apiImpl)).getResult().get();
        String apiClassName = mData.getApiClassName();
        String apiImplClassName = mData.getApiImplClassName();
        ClassOrInterfaceDeclaration apiClass = apiUnit.getInterfaceByName(apiClassName).orElse(null);
        ClassOrInterfaceDeclaration apiImplClass = apiImplUnit.getClassByName(apiImplClassName).orElse(null);

        assert apiClass != null;
        assert apiImplClass != null;

        StringBuilder src = new StringBuilder();

        src.append(apiUnit.getPackageDeclaration().get()).append("\n");

        Set<String> importPackage = new LinkedHashSet<>();
        NodeList<ImportDeclaration> apiPack = apiUnit.getImports();
        NodeList<ImportDeclaration> apiImplPack = apiImplUnit.getImports();
        for (ImportDeclaration declaration : apiPack) {
            importPackage.add(declaration.toString());
        }
        for (ImportDeclaration declaration : apiImplPack) {
            importPackage.add(declaration.toString());
        }
        for (String s : importPackage) {
            src.append(s.replace("\n", "")).append("\n");
        }
        Set<String> importAn = new LinkedHashSet<>();
        NodeList<AnnotationExpr> apiAn = apiClass.getAnnotations();
        for (AnnotationExpr annotation : apiAn) {
            importAn.add(annotation.toString());
        }
        NodeList<AnnotationExpr> apiImplAn = apiImplClass.getAnnotations();
        for (AnnotationExpr annotation : apiImplAn) {
            importAn.add(annotation.toString());
        }

        for (String s : importAn) {
            src.append(s).append("\n");
        }

        src.append("public class " + apiClassName + " {").append("\n");

        List<FieldDeclaration> fields = apiImplClass.getFields();
        for (FieldDeclaration field : fields) {
            src.append(field.toString()).append("\n");
        }

        Map<String, String> methodImplementationMap = new LinkedHashMap<>();
        List<MethodDeclaration> interfaceMethods = apiClass.getMethods();
        for (MethodDeclaration interfaceMethod : interfaceMethods) {
            String interfaceMethodName = interfaceMethod.getNameAsString();
            List<Type> interfaceMethodParamTypes = interfaceMethod.getParameters().stream()
                    .map(Parameter::getType)
                    .collect(Collectors.toList());

            MethodDeclaration implementedMethod = findMatchingMethod(apiImplClass, interfaceMethodName, interfaceMethodParamTypes);
            if (implementedMethod != null) {
                methodImplementationMap.put(interfaceMethod.toString(), implementedMethod.getBody().get().toString());
            }
        }

        for (Map.Entry<String, String> entry : methodImplementationMap.entrySet()) {
            src.append(entry.getKey().replace(";", "")).append("\n");
            src.append(entry.getValue()).append("\n");
        }
        src.append("}");

//        System.out.println(src);

        FileUtil.writeUtf8String(src.toString(), api);
        FileUtil.del(apiImpl);

    }

    @Data
    public static class MData {
        private String apiImplFile;
        private String apiFile;
        private String apiClassName;
        private String apiImplClassName;
    }

    public static List<MData> scan() {
        List<String> list = scanClassesWithAnnotation("com.xx", RestController.class);
        List<MData> mm = new ArrayList<>();
        for (String s : list) {
            if (StrUtil.contains(s, "ApiImpl")) {
                String impl = StrUtil.replace(s, "\\target\\classes", "\\src\\main\\java");
                impl = StrUtil.replace(impl, ".class", ".java");
                String api = StrUtil.replace(impl, "\\impl", "");
                api = StrUtil.replace(api, "Impl", "");
                if (new File(api).exists()) {
                    MData e = new MData();
                    e.setApiImplFile(impl);
                    e.setApiFile(api);
                    e.setApiClassName(FileUtil.getName(api).replace(".java", ""));
                    e.setApiImplClassName(FileUtil.getName(impl).replace(".java", ""));
                    mm.add(e);
                } else {
                    System.out.println(api);
                }
            }
        }
        return mm;
    }


    public static void main(String[] args) throws Exception {
        // dd();
        List<MData> data = scan();
        System.out.println("检测到需要优化的项目 " + data.size());
        int i = 1;
        for (MData mData : data) {
            System.out.println("正在处理 " + i++);
            dd(mData);
        }
        cleanEmptyDir();
        System.out.println("ok");
    }

    public static List<String> scanClassesWithAnnotation(String packageName, Class<?> annotationClass) {
        List<String> classes = new ArrayList<>();
        String packagePath = packageName.replace('.', '/');
        URL resource = Thread.currentThread().getContextClassLoader().getResource(packagePath);
        if (resource != null) {
            File directory = new File(resource.getFile());
            if (directory.exists() && directory.isDirectory()) {
                scanDirectory(directory, packageName, annotationClass, classes);
            }
        }
        return classes;
    }

    private static void scanDirectory(File directory, String packageName, Class<?> annotationClass, List<String> classes) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    String subPackageName = packageName + "." + file.getName();
                    scanDirectory(file, subPackageName, annotationClass, classes);
                } else if (file.getName().endsWith(".class")) {
                    String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                    try {
                        Class<?> clazz = Class.forName(className);
                        if (clazz.isAnnotationPresent((Class<? extends Annotation>) annotationClass)) {
                            classes.add(file.getAbsolutePath());
                        }
                        if (clazz.isAnnotationPresent(RestController.class)
                                && !clazz.isAnnotationPresent(Tag.class)
                        ) {
                            System.out.println(className);
                        }

                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

     public static void cleanEmptyDir() {
        // 替换为你想要清理的目录路径
        File directory = new File("D:\\workspace\\xxx\\src\\main\\java\\com\\xx");
        deleteEmptyDirectories(directory);
    }

    /**
     * 删除所有空目录
     *
     * @param directory 要清理的目录
     */
    public static void deleteEmptyDirectories(File directory) {
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteEmptyDirectories(file);
                    }
                }
            }
            // 再次检查目录是否为空,如果是,则删除
            if (directory.listFiles().length == 0) {
                directory.delete();
                System.out.println("Deleted empty directory: " + directory.getAbsolutePath());
            }
        }
    }
}

posted @ 2024-11-04 15:57  Ranger-dev  阅读(7)  评论(0编辑  收藏  举报