@@ -4,14 +4,14 @@ import com.intellij.openapi.application.ApplicationManager
44import com.intellij.openapi.project.Project
55import com.intellij.psi.*
66import com.intellij.psi.search.GlobalSearchScope
7- import com.intellij.psi.search.searches.ClassInheritorsSearch
87import com.intellij.psi.search.searches.ReferencesSearch
98import com.intellij.psi.util.PsiTreeUtil
109import org.skgroup.securityinspector.analysis.ast.nodes.MethodNode
1110import org.skgroup.securityinspector.analysis.di.DIProcessor
1211import org.skgroup.securityinspector.enums.RefMode
1312import org.skgroup.securityinspector.utils.GraphUtils
14- import java.util.ArrayDeque
13+ import org.skgroup.securityinspector.utils.PsiUtil.findConcreteImplementations
14+ import java.util.*
1515
1616/* *
1717 * Call graph builder 是一个用于构建调用图的类
@@ -32,8 +32,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
3232 // 用于记录当前访问的方法调用栈
3333 private val currentMethodStack = ArrayDeque <MethodNode >()
3434
35- // private val diProcessor = DIProcessor(callGraph)
36-
3735 /* *
3836 * Visit method 方法用于访问一个Java方法并将其加入调用图
3937 * 用栈处理递归方法调用
@@ -46,7 +44,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
4644 var calleeStackNode = GraphUtils .getMethodNode(method)
4745
4846 // 查找对该方法的所有引用,建立反向调用关系
49- // TODO 这里的逻辑我自己也混乱了,可能会有问题,后面再看
5047 val projectScope = GlobalSearchScope .projectScope(method.project)
5148 ReferencesSearch .search(method, projectScope).forEach { reference ->
5249 val callerMethod = PsiTreeUtil .getParentOfType(reference.element, PsiMethod ::class .java)
@@ -57,6 +54,14 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
5754 callGraph.nodes.add(calleeMethodNode)
5855
5956 val callerMethodNode = GraphUtils .getMethodNode(callerMethod, reference)
57+
58+ if (method.hasModifierProperty(PsiModifier .ABSTRACT ) || method.containingClass?.isInterface == true ) {
59+ findConcreteImplementations(method).forEach { implMethod ->
60+ val implNode = GraphUtils .getMethodNode(implMethod)
61+ callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf () }.add(implNode)
62+ }
63+ }
64+
6065 // 建立反向调用关系
6166 callGraph.nodes.add(callerMethodNode)
6267 callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf () }.add(calleeMethodNode)
@@ -79,7 +84,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
7984 */
8085 override fun visitMethodCallExpression (expression : PsiMethodCallExpression ) {
8186 if (currentMethodStack.isEmpty()) return
82- expression.methodExpression.qualifierExpression?.accept(this )
8387
8488 val caller = currentMethodStack.peek()
8589 // 解析被调用的方法
@@ -106,16 +110,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
106110 .add(calleeMethodNode)
107111 handleIoCContainerCall(expression, caller, calleeMethodNode)
108112 } ? : run {
109- // if (clazz != null) {
110- // if (clazz.isInterface) {
111- // println("$clazz is an interface")
112- // println("and the method call expression $expression can not resolve reference.")
113- // }
114- // if (clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
115- // println("$clazz is an abstract class")
116- // println("and the method call expression $expression can not resolve reference.")
117- // }
118- // }
119113 if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
120114 println (" in lambda method call expression $expression can not resolve reference." )
121115 } else {
@@ -139,7 +133,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
139133 */
140134 override fun visitNewExpression (expression : PsiNewExpression ) {
141135 if (currentMethodStack.isEmpty()) return
142- // expression.methodNewExpression.qualifierExpression?.accept(this)
143136
144137 val callerMethodNode = currentMethodStack.peek()
145138 // 解析构造方法
@@ -160,16 +153,6 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
160153 .add(calleeMethodNode)
161154 println (" expression $expression resolve reference success." )
162155 } ? : run {
163- // if (clazz != null) {
164- // if (clazz.isInterface) {
165- // println("$clazz is an interface")
166- // println("and the method call expression $expression can not resolve reference.")
167- // }
168- // if (clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
169- // println("$clazz is an abstract class")
170- // println("and the method call expression $expression can not resolve referencee.")
171- // }
172- // }
173156 if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
174157 println (" in lambda method call expression $expression can not resolve reference." )
175158 } else {
@@ -329,26 +312,4 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
329312 return callGraph
330313 }
331314
332- private fun findConcreteImplementations (abstractMethod : PsiMethod ): List <PsiMethod > {
333- val implementations = mutableListOf<PsiMethod >()
334- val containingClass = abstractMethod.containingClass ? : return emptyList()
335-
336- // 查找所有子类或实现类
337- val inheritors = if (containingClass.isInterface) {
338- ClassInheritorsSearch .search(containingClass, abstractMethod.useScope, true ).toList()
339- } else {
340- ClassInheritorsSearch .search(containingClass).toList()
341- }
342-
343- inheritors.forEach { implClass ->
344- implClass.findMethodBySignature(abstractMethod, true )?.let {
345- if (! it.hasModifierProperty(PsiModifier .ABSTRACT )) {
346- implementations.add(it)
347- }
348- }
349- }
350-
351- return implementations
352- }
353-
354315}
0 commit comments