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);
}
}
}
}