@@ -3,10 +3,13 @@ package org.skgroup.securityinspector.analysis.graphs.callgraph
33import com.intellij.openapi.application.ApplicationManager
44import com.intellij.openapi.project.Project
55import com.intellij.psi.*
6+ import com.intellij.psi.search.GlobalSearchScope
7+ import com.intellij.psi.search.searches.ClassInheritorsSearch
68import com.intellij.psi.search.searches.ReferencesSearch
79import com.intellij.psi.util.PsiTreeUtil
810import org.skgroup.securityinspector.analysis.ast.nodes.MethodNode
911import org.skgroup.securityinspector.analysis.di.DIProcessor
12+ import org.skgroup.securityinspector.enums.RefMode
1013import org.skgroup.securityinspector.utils.GraphUtils
1114import java.util.ArrayDeque
1215
@@ -44,7 +47,8 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
4447
4548 // 查找对该方法的所有引用,建立反向调用关系
4649 // TODO 这里的逻辑我自己也混乱了,可能会有问题,后面再看
47- ReferencesSearch .search(method, method.useScope).forEach { reference ->
50+ val projectScope = GlobalSearchScope .projectScope(method.project)
51+ ReferencesSearch .search(method, projectScope).forEach { reference ->
4852 val callerMethod = PsiTreeUtil .getParentOfType(reference.element, PsiMethod ::class .java)
4953 ? : return @forEach
5054
@@ -74,26 +78,58 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
7478 * @param expression 方法调用表达式
7579 */
7680 override fun visitMethodCallExpression (expression : PsiMethodCallExpression ) {
77- super .visitMethodCallExpression(expression)
78- if (currentMethodStack.isEmpty()) {
79- return
80- }
81+ if (currentMethodStack.isEmpty()) return
82+ expression.methodExpression.qualifierExpression?.accept(this )
8183
8284 val caller = currentMethodStack.peek()
83-
8485 // 解析被调用的方法
85- val resolvedMethod = expression.resolveMethod() ? : return
86- val calleeMethodNode = GraphUtils .getMethodNode(resolvedMethod, expression)
87-
88- // 将 callee 加入节点集合
89- callGraph.nodes.add(calleeMethodNode)
90-
91- // 在 callGraph 中记录调用关系 (caller -> callee)
92- callGraph.edges
93- .getOrPut(caller) { mutableSetOf () }
94- .add(calleeMethodNode)
95-
96- handleIoCContainerCall(expression, caller, calleeMethodNode)
86+ val resolvedMethod = expression.resolveMethod()
87+ // 调试日志
88+ if (resolvedMethod == null ) {
89+ println (" method call expression $expression can not be resolve." )
90+ return
91+ }
92+ if (resolvedMethod.hasModifierProperty(PsiModifier .ABSTRACT ) || resolvedMethod.containingClass?.isInterface == true ) {
93+ findConcreteImplementations(resolvedMethod).forEach { implMethod ->
94+ val implNode = GraphUtils .getMethodNode(implMethod, expression)
95+ callGraph.edges.getOrPut(caller) { mutableSetOf () }.add(implNode)
96+ }
97+ }
98+ // val clazz: PsiClass? = resolvedMethod.containingClass
99+ expression.reference?.let {
100+ val calleeMethodNode = GraphUtils .getMethodNode(resolvedMethod, it)
101+ // 将 callee 加入节点集合
102+ callGraph.nodes.add(calleeMethodNode)
103+ // 在 callGraph 中记录调用关系 (caller -> callee)
104+ callGraph.edges
105+ .getOrPut(caller) { mutableSetOf () }
106+ .add(calleeMethodNode)
107+ handleIoCContainerCall(expression, caller, calleeMethodNode)
108+ } ? : 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+ // }
119+ if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
120+ println (" in lambda method call expression $expression can not resolve reference." )
121+ } else {
122+ println (" unknown method call expression $expression can not resolve reference." )
123+ }
124+ val calleeMethodNode = GraphUtils .getMethodNode(resolvedMethod, expression)
125+ callGraph.nodes.add(calleeMethodNode)
126+ // 在 callGraph 中记录调用关系 (caller -> callee)
127+ callGraph.edges
128+ .getOrPut(caller) { mutableSetOf () }
129+ .add(calleeMethodNode)
130+ handleIoCContainerCall(expression, caller, calleeMethodNode)
131+ }
132+ super .visitMethodCallExpression(expression)
97133 }
98134
99135 /* *
@@ -102,24 +138,51 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
102138 * @param expression
103139 */
104140 override fun visitNewExpression (expression : PsiNewExpression ) {
105- super .visitNewExpression(expression)
106- if (currentMethodStack.isEmpty()) {
107- return
108- }
109- val callerMethodNode = currentMethodStack.peek()
141+ if (currentMethodStack.isEmpty()) return
142+ // expression.methodNewExpression.qualifierExpression?.accept(this)
110143
144+ val callerMethodNode = currentMethodStack.peek()
111145 // 解析构造方法
112- val constructor = expression.resolveConstructor() ? : return
113- val calleeMethodNode = GraphUtils .getMethodNode(constructor , expression)
114-
115- // 将 callee 加入节点集合
116- callGraph.nodes.add(calleeMethodNode)
117-
118- // 在 callGraph 中记录 (caller -> callee构造方法)
119- callGraph
120- .edges
121- .getOrPut(callerMethodNode) { mutableSetOf () }
122- .add(calleeMethodNode)
146+ val constructor = expression.resolveConstructor()
147+ // 调试日志
148+ if (constructor == null ) {
149+ println (" new expression $constructor can not be resolve." )
150+ return
151+ }
152+ // val clazz: PsiClass? = constructor.containingClass
153+ expression.reference?.let {
154+ val calleeMethodNode = GraphUtils .getMethodNode(constructor , it)
155+ // 将 callee 加入节点集合
156+ callGraph.nodes.add(calleeMethodNode)
157+ // 在 callGraph 中记录 (caller -> callee构造方法)
158+ callGraph.edges
159+ .getOrPut(callerMethodNode) { mutableSetOf () }
160+ .add(calleeMethodNode)
161+ println (" expression $expression resolve reference success." )
162+ } ? : 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+ // }
173+ if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
174+ println (" in lambda method call expression $expression can not resolve reference." )
175+ } else {
176+ println (" unknown new expression $constructor can not resolve reference." )
177+ }
178+ val calleeMethodNode = GraphUtils .getMethodNode(constructor , expression)
179+ callGraph.nodes.add(calleeMethodNode)
180+ // 在 callGraph 中记录调用关系 (caller -> callee)
181+ callGraph.edges
182+ .getOrPut(callerMethodNode) { mutableSetOf () }
183+ .add(calleeMethodNode)
184+ }
185+ super .visitNewExpression(expression)
123186 }
124187
125188 /* *
@@ -141,15 +204,20 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
141204 super .visitMethodCallExpression(lambdaCall)
142205 val caller = currentMethodStack.peek()
143206 val resolvedMethod = lambdaCall.resolveMethod() ? : return
144- val calleeMethodNode = GraphUtils .getLambdaMethodNode(resolvedMethod)
145-
146- // 将 callee 加入图
147- callGraph.nodes.add(calleeMethodNode)
148-
149- // 在 callGraph 中记录调用关系 (caller -> callee)
150- callGraph.edges
151- .getOrPut(caller) { mutableSetOf () }
152- .add(calleeMethodNode)
207+ lambdaCall.children.forEach { child ->
208+ val calleeMethodNode = child.reference?.let {
209+ GraphUtils .getMethodNode(resolvedMethod, it)
210+ } ? : run {
211+ GraphUtils .getLambdaMethodNode(resolvedMethod)
212+ }
213+ callGraph.nodes.add(caller)
214+ calleeMethodNode?.let {
215+ callGraph.nodes.add(it)
216+ callGraph.edges
217+ .getOrPut(caller) { mutableSetOf () }
218+ .add(it)
219+ }
220+ }
153221 }
154222
155223 override fun visitMethodReferenceExpression (expression : PsiMethodReferenceExpression ) {
@@ -205,7 +273,8 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
205273 // 其他的慢慢加吧
206274 ) {
207275 // 如果是构造方法或者带有此注解的方法,可能被框架在运行时调用
208- val containerMethodNode = MethodNode (" Container" , " Container" , " Framework" , emptyList(), emptyList())
276+ val containerMethodNode =
277+ MethodNode (" Container" , " Container" , " Framework" , emptyList(), emptyList(), RefMode .CALL )
209278 callGraph.nodes.add(containerMethodNode)
210279
211280 callGraph.edges
@@ -232,7 +301,7 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
232301 if (qualifierExpression != null && methodName == " getBean" ) {
233302 // 将容器节点与被调用方法或类做额外的链接
234303 val containerMethodNode =
235- MethodNode (" ApplicationContext" , " ApplicationContext" , " Spring" , emptyList(), emptyList())
304+ MethodNode (" ApplicationContext" , " ApplicationContext" , " Spring" , emptyList(), emptyList(), RefMode . CALL )
236305 callGraph.nodes.add(containerMethodNode)
237306 // caller -> container
238307 callGraph.edges
@@ -260,4 +329,26 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
260329 return callGraph
261330 }
262331
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+
263354}
0 commit comments