PSI笔记本

import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class MethodDependencyAnalyzer {

    /**
     * 获取方法的所有依赖类及源代码
     *
     * @param method 目标方法
     * @return 映射: 类全限定名 -> 源代码
     */
    public static Map<String, String> getMethodDependenciesWithSource(@NotNull PsiMethod method) {
        Set<PsiClass> dependencies = new LinkedHashSet<>();
        Project project = method.getProject();
        
        // 1. 添加方法自身的所属类
        PsiClass containingClass = method.getContainingClass();
        if (containingClass != null) {
            collectDependencies(containingClass, dependencies);
        }
        
        // 2. 分析方法签名依赖
        analyzeMethodSignatureDependencies(method, dependencies);
        
        // 3. 分析方法体依赖
        analyzeMethodBodyDependencies(method, dependencies);
        
        // 4. 收集所有依赖类的源代码
        Map<String, String> result = new LinkedHashMap<>();
        for (PsiClass psiClass : dependencies) {
            // 跳过没有源码的类(如 JDK 类)
            if (psiClass.getContainingFile() != null && psiClass.getContainingFile().isValid()) {
                String source = psiClass.getContainingFile().getText();
                result.put(psiClass.getQualifiedName(), source);
            }
        }
        
        return result;
    }

    /**
     * 分析方法签名依赖(返回类型、参数类型、异常类型)
     */
    private static void analyzeMethodSignatureDependencies(PsiMethod method, Set<PsiClass> dependencies) {
        // 返回类型
        PsiType returnType = method.getReturnType();
        if (returnType != null) {
            extractClassFromType(returnType, dependencies);
        }
        
        // 参数类型
        for (PsiParameter parameter : method.getParameterList().getParameters()) {
            extractClassFromType(parameter.getType(), dependencies);
        }
        
        // 异常类型
        for (PsiClassType exceptionType : method.getThrowsList().getReferencedTypes()) {
            extractClassFromType(exceptionType, dependencies);
        }
    }

    /**
     * 分析方法体依赖(变量声明、方法调用、字段访问等)
     */
    private static void analyzeMethodBodyDependencies(PsiMethod method, Set<PsiClass> dependencies) {
        // 只分析方法体,跳过抽象方法
        PsiCodeBlock body = method.getBody();
        if (body == null) return;
        
        // 使用 PsiRecursiveElementWalkingVisitor 遍历所有元素
        body.accept(new JavaRecursiveElementWalkingVisitor() {
            @Override
            public void visitElement(@NotNull PsiElement element) {
                super.visitElement(element);
                
                // 变量声明
                if (element instanceof PsiLocalVariable) {
                    PsiType variableType = ((PsiLocalVariable) element).getType();
                    extractClassFromType(variableType, dependencies);
                }
                
                // 方法调用
                else if (element instanceof PsiMethodCallExpression) {
                    PsiMethodCallExpression methodCall = (PsiMethodCallExpression) element;
                    extractMethodCallDependencies(methodCall, dependencies);
                }
                
                // 字段访问
                else if (element instanceof PsiReferenceExpression) {
                    PsiReferenceExpression ref = (PsiReferenceExpression) element;
                    PsiElement resolved = ref.resolve();
                    if (resolved instanceof PsiField) {
                        extractClassFromType(((PsiField) resolved).getType(), dependencies);
                    }
                }
                
                // 类引用
                else if (element instanceof PsiJavaCodeReferenceElement) {
                    PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) element;
                    PsiElement resolved = ref.resolve();
                    if (resolved instanceof PsiClass) {
                        dependencies.add((PsiClass) resolved);
                    }
                }
                
                // 类型转换
                else if (element instanceof PsiTypeCastExpression) {
                    PsiTypeCastExpression castExpr = (PsiTypeCastExpression) element;
                    extractClassFromType(castExpr.getCastType(), dependencies);
                }
                
                // 实例化对象
                else if (element instanceof PsiNewExpression) {
                    PsiNewExpression newExpr = (PsiNewExpression) element;
                    PsiType classType = newExpr.getType();
                    extractClassFromType(classType, dependencies);
                    
                    // 处理匿名内部类
                    PsiAnonymousClass anonymousClass = newExpr.getAnonymousClass();
                    if (anonymousClass != null) {
                        dependencies.add(anonymousClass);
                    }
                }
            }
        });
    }

    /**
     * 提取方法调用依赖关系
     */
    private static void extractMethodCallDependencies(PsiMethodCallExpression methodCall, Set<PsiClass> dependencies) {
        PsiMethod method = methodCall.resolveMethod();
        if (method != null) {
            // 1. 添加方法所属类
            PsiClass containingClass = method.getContainingClass();
            if (containingClass != null) {
                collectDependencies(containingClass, dependencies);
            }
            
            // 2. 添加返回类型
            PsiType returnType = method.getReturnType();
            if (returnType != null) {
                extractClassFromType(returnType, dependencies);
            }
            
            // 3. 处理泛型参数
            PsiType[] typeArguments = PsiUtil.getMethodReturnType(methodCall).getTypeArguments();
            for (PsiType typeArg : typeArguments) {
                extractClassFromType(typeArg, dependencies);
            }
        }
    }

    /**
     * 从类型中提取类依赖(处理泛型、数组等)
     */
    private static void extractClassFromType(PsiType type, Set<PsiClass> dependencies) {
        if (type == null) return;
        
        // 处理原始类型
        if (type instanceof PsiPrimitiveType) return;
        
        // 处理类引用类型
        if (type instanceof PsiClassReferenceType) {
            PsiClassReferenceType classRefType = (PsiClassReferenceType) type;
            PsiClass psiClass = classRefType.resolve();
            if (psiClass != null) {
                collectDependencies(psiClass, dependencies);
            }
        }
        
        // 处理泛型类型参数
        PsiType[] typeParameters = type.getTypeArguments();
        for (PsiType paramType : typeParameters) {
            extractClassFromType(paramType, dependencies);
        }
        
        // 处理数组元素类型
        PsiType componentType = PsiUtil.extractIterableTypeParameter(type, false);
        if (componentType != null) {
            extractClassFromType(componentType, dependencies);
        }
    }

    /**
     * 收集类及其所有依赖(嵌套类、父类、接口等)
     */
    private static void collectDependencies(@NotNull PsiClass psiClass, Set<PsiClass> dependencies) {
        if (!dependencies.add(psiClass)) return; // 避免重复处理
        
        // 1. 添加父类
        PsiClass superClass = psiClass.getSuperClass();
        if (superClass != null) {
            collectDependencies(superClass, dependencies);
        }
        
        // 2. 添加实现的接口
        for (PsiClassType interfaceType : psiClass.getImplementsListTypes()) {
            PsiClass interfaceClass = interfaceType.resolve();
            if (interfaceClass != null) {
                collectDependencies(interfaceClass, dependencies);
            }
        }
        
        // 3. 添加包含的外部类(对内部类)
        PsiClass containingClass = psiClass.getContainingClass();
        if (containingClass != null) {
            collectDependencies(containingClass, dependencies);
        }
        
        // 4. 添加类使用的注解
        for (PsiAnnotation annotation : psiClass.getAnnotations()) {
            PsiClass annotationClass = annotation.resolveAnnotationType();
            if (annotationClass != null) {
                collectDependencies(annotationClass, dependencies);
            }
        }
        
        // 5. 添加字段类型
        for (PsiField field : psiClass.getFields()) {
            extractClassFromType(field.getType(), dependencies);
        }
        
        // 6. 添加方法签名类型(只处理重要方法)
        for (PsiMethod method : psiClass.getMethods()) {
            if (method.isConstructor() || "equals".equals(method.getName()) || "hashCode".equals(method.getName())) {
                analyzeMethodSignatureDependencies(method, dependencies);
            }
        }
    }
}
posted @ 2025-06-12 14:55  frontlook  阅读(26)  评论(0)    收藏  举报