@@ -4,6 +4,7 @@ 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
78import com.intellij.psi.search.searches.ReferencesSearch
89import com.intellij.psi.util.PsiTreeUtil
910import org.skgroup.securityinspector.analysis.ast.nodes.MethodNode
@@ -46,8 +47,8 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
4647
4748 // 查找对该方法的所有引用,建立反向调用关系
4849 // TODO 这里的逻辑我自己也混乱了,可能会有问题,后面再看
49- val scope = GlobalSearchScope .projectScope(method.project)
50- ReferencesSearch .search(method, scope ).forEach { reference ->
50+ val projectScope = GlobalSearchScope .projectScope(method.project)
51+ ReferencesSearch .search(method, projectScope ).forEach { reference ->
5152 val callerMethod = PsiTreeUtil .getParentOfType(reference.element, PsiMethod ::class .java)
5253 ? : return @forEach
5354
@@ -88,10 +89,15 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
8889 println (" method call expression $expression can not be resolve." )
8990 return
9091 }
91- val clazz: PsiClass ? = resolvedMethod.containingClass
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
9299 expression.reference?.let {
93100 val calleeMethodNode = GraphUtils .getMethodNode(resolvedMethod, it)
94- println (" expression $expression resolve reference success." )
95101 // 将 callee 加入节点集合
96102 callGraph.nodes.add(calleeMethodNode)
97103 // 在 callGraph 中记录调用关系 (caller -> callee)
@@ -100,21 +106,28 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
100106 .add(calleeMethodNode)
101107 handleIoCContainerCall(expression, caller, calleeMethodNode)
102108 } ? : run {
103- if (clazz != null ) {
104- if (clazz.isInterface) {
105- println (" $clazz is an interface" )
106- println (" and the method call expression $expression can not resolve reference." )
107- }
108- if (clazz.hasModifierProperty(PsiModifier .ABSTRACT )) {
109- println (" $clazz is an abstract class" )
110- println (" and the method call expression $expression can not resolve reference." )
111- }
112- }
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+ // }
113119 if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
114120 println (" in lambda method call expression $expression can not resolve reference." )
115121 } else {
116122 println (" unknown method call expression $expression can not resolve reference." )
117123 }
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)
118131 }
119132 super .visitMethodCallExpression(expression)
120133 }
@@ -136,7 +149,7 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
136149 println (" new expression $constructor can not be resolve." )
137150 return
138151 }
139- val clazz: PsiClass ? = constructor .containingClass
152+ // val clazz: PsiClass? = constructor.containingClass
140153 expression.reference?.let {
141154 val calleeMethodNode = GraphUtils .getMethodNode(constructor , it)
142155 // 将 callee 加入节点集合
@@ -147,21 +160,27 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
147160 .add(calleeMethodNode)
148161 println (" expression $expression resolve reference success." )
149162 } ? : run {
150- if (clazz != null ) {
151- if (clazz.isInterface) {
152- println (" $clazz is an interface" )
153- println (" and the method call expression $expression can not resolve reference." )
154- }
155- if (clazz.hasModifierProperty(PsiModifier .ABSTRACT )) {
156- println (" $clazz is an abstract class" )
157- println (" and the method call expression $expression can not resolve referencee." )
158- }
159- }
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+ // }
160173 if (PsiTreeUtil .getParentOfType(expression, PsiLambdaExpression ::class .java) != null ) {
161174 println (" in lambda method call expression $expression can not resolve reference." )
162175 } else {
163176 println (" unknown new expression $constructor can not resolve reference." )
164177 }
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)
165184 }
166185 super .visitNewExpression(expression)
167186 }
@@ -310,4 +329,26 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
310329 return callGraph
311330 }
312331
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+
313354}
0 commit comments