Skip to content

Commit 8d75451

Browse files
committed
feature: Introduce CallEdge class and enhance method resolution in CallGraph
1 parent 066e503 commit 8d75451

10 files changed

Lines changed: 363 additions & 76 deletions

File tree

.idea/gradle.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/intellij-javadocs-4.0.1.xml

Lines changed: 204 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/kotlin/org/skgroup/securityinspector/analysis/ast/nodes/MethodNode.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ data class MethodNode(
2121
val parameters: List<ParameterNode>,
2222
val body: List<AstNode> = emptyList(),
2323
val refMode: RefMode,
24+
var signature: String = "",
2425
override val sourceSpan: SourceSpan? = null
2526
) : BaseAstNode(
2627
nodeType = "MethodDeclaration",
2728
children = body,
2829
sourceSpan = sourceSpan
2930
){
31+
init {
32+
signature = "$className.$name(${parameters.joinToString { it.type }})"
33+
}
3034
override fun toString(): String {
3135
return "MethodNode(className='$className', name='$name', returnType='$returnType', parameters=$parameters, body=$body, sourceSpan=$sourceSpan)"
3236
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.skgroup.securityinspector.analysis.graphs.callgraph
2+
3+
import org.skgroup.securityinspector.analysis.ast.nodes.MethodNode
4+
import org.skgroup.securityinspector.enums.EdgeType
5+
6+
/**
7+
* 类描述:CallPair 类用于。
8+
*
9+
* @author springkill
10+
* @version 1.0
11+
* @since 2025/3/29
12+
*/
13+
data class CallEdge(
14+
val caller: MethodNode,
15+
val callee: MethodNode,
16+
val edgeType: EdgeType
17+
)

src/main/kotlin/org/skgroup/securityinspector/analysis/graphs/callgraph/CallGraphBuilder.kt

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
3434

3535
// 用于记录当前访问的方法调用栈
3636
private val currentMethodStack = ArrayDeque<MethodNode>()
37+
private val methodStack = ArrayDeque<PsiMethod>()
38+
private val implMethodSet = mutableSetOf<PsiMethod>()
3739

3840
// 用于表示是否构建方法完整信息的标志
3941
private var buildWithInfo = System.getProperty("BUILD_WITH_METHOD_INFO")?.toBoolean() ?: false
@@ -56,38 +58,40 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
5658

5759
if (buildWithPath) {
5860
// 查找对该方法的所有引用,建立反向调用关系
59-
val projectScope = GlobalSearchScope.projectScope(method.project)
60-
ReferencesSearch.search(method, projectScope).forEach { reference ->
61-
val callerMethod = PsiTreeUtil.getParentOfType(reference.element, PsiMethod::class.java)
62-
?: return@forEach
63-
64-
val calleeMethodNode = GraphUtils.getMethodNode(method, reference)
65-
calleeStackNode = calleeMethodNode
66-
callGraph.nodes.add(calleeMethodNode)
67-
68-
val callerMethodNode = GraphUtils.getMethodNode(callerMethod, reference)
69-
70-
if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.containingClass?.isInterface == true) {
71-
findConcreteImplementations(method).forEach { implMethod ->
72-
val implNode = GraphUtils.getMethodNode(implMethod)
73-
callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf() }.add(implNode)
74-
}
75-
}
76-
77-
// 建立反向调用关系
78-
callGraph.nodes.add(callerMethodNode)
79-
callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf() }.add(calleeMethodNode)
80-
81-
handleDependencyInjectionAnnotations(method, calleeMethodNode)
82-
}
61+
// val projectScope = GlobalSearchScope.projectScope(method.project)
62+
// ReferencesSearch.search(method, projectScope).forEach { reference ->
63+
// val callerMethod = PsiTreeUtil.getParentOfType(reference.element, PsiMethod::class.java)
64+
// ?: return@forEach
65+
//
66+
// val calleeMethodNode = GraphUtils.getMethodNode(method, reference)
67+
// calleeStackNode = calleeMethodNode
68+
// callGraph.nodes.add(calleeMethodNode)
69+
//
70+
// val callerMethodNode = GraphUtils.getMethodNode(callerMethod, reference)
71+
//
72+
// if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.containingClass?.isInterface == true) {
73+
// findConcreteImplementations(method).forEach { implMethod ->
74+
// val implNode = GraphUtils.getMethodNode(implMethod)
75+
// callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf() }.add(implNode)
76+
// }
77+
// }
78+
//
79+
// // 建立反向调用关系
80+
// callGraph.nodes.add(callerMethodNode)
81+
// callGraph.edges.getOrPut(callerMethodNode) { mutableSetOf() }.add(calleeMethodNode)
82+
//
83+
// handleDependencyInjectionAnnotations(method, calleeMethodNode)
84+
// }
8385
}
8486

8587
// 将此方法节点加入 callGraph
8688
currentMethodStack.push(calleeStackNode)
89+
methodStack.push(method)
8790

8891
super.visitMethod(method)
8992

9093
currentMethodStack.pop()
94+
methodStack.pop()
9195
}
9296

9397
/**
@@ -107,30 +111,28 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
107111
println("method call expression $expression can not be resolve.")
108112
return
109113
}
114+
115+
val calleeMethodNode = GraphUtils.getMethodNode(resolvedMethod, expression)
116+
117+
110118
if (resolvedMethod.hasModifierProperty(PsiModifier.ABSTRACT) || resolvedMethod.containingClass?.isInterface == true) {
111119
findConcreteImplementations(resolvedMethod).forEach { implMethod ->
112-
val implNode = GraphUtils.getMethodNode(implMethod, expression)
113-
callGraph.edges.getOrPut(caller) { mutableSetOf() }.add(implNode)
120+
val implNode = GraphUtils.getImplNode(implMethod, expression)
121+
callGraph.edges.getOrPut(calleeMethodNode) { mutableSetOf() }.add(implNode)
122+
callGraph.nodes.add(implNode)
123+
if(implMethodSet.add(implMethod)) implMethod.accept(this)
114124
}
115125
}
116-
// val clazz: PsiClass? = resolvedMethod.containingClass
117-
expression.reference?.let {
118-
val calleeMethodNode = GraphUtils.getMethodNode(resolvedMethod, it)
126+
if (methodStack.peek().findSuperMethods().toSet()
127+
.containsAll(resolvedMethod.findSuperMethods().toSet())) {
119128
// 将 callee 加入节点集合
120129
callGraph.nodes.add(calleeMethodNode)
121-
// 在 callGraph 中记录调用关系 (caller -> callee)
122-
callGraph.edges
123-
.getOrPut(caller) { mutableSetOf() }
124-
.add(calleeMethodNode)
125-
handleIoCContainerCall(expression, caller, calleeMethodNode)
126-
} ?: run {
127-
if (PsiTreeUtil.getParentOfType(expression, PsiLambdaExpression::class.java) != null) {
128-
println("in lambda method call expression $expression can not resolve reference.")
129-
} else {
130-
println("unknown method call expression $expression can not resolve reference.")
131-
}
132-
val calleeMethodNode = GraphUtils.getMethodNode(resolvedMethod, expression)
133-
callGraph.nodes.add(calleeMethodNode)
130+
callGraph.nodes.add(caller)
131+
// if (methodStack.peek().findSuperMethods().toSet()
132+
// .containsAll(resolvedMethod.findSuperMethods().toSet())
133+
// ) {
134+
//
135+
// }
134136
// 在 callGraph 中记录调用关系 (caller -> callee)
135137
callGraph.edges
136138
.getOrPut(caller) { mutableSetOf() }
@@ -160,7 +162,7 @@ class CallGraphBuilder : JavaRecursiveElementVisitor() {
160162
}
161163
// val clazz: PsiClass? = constructor.containingClass
162164
expression.reference?.let {
163-
val calleeMethodNode = GraphUtils.getMethodNode(constructor, it)
165+
val calleeMethodNode = GraphUtils.getNewMethodNode(constructor, it)
164166
// 将 callee 加入节点集合
165167
callGraph.nodes.add(calleeMethodNode)
166168
// 在 callGraph 中记录 (caller -> callee构造方法)

src/main/kotlin/org/skgroup/securityinspector/enums/EdgeType.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ package org.skgroup.securityinspector.enums
88
* @since 2025/2/16
99
*/
1010
enum class EdgeType {
11+
CALL,
12+
IMPLEMENTS,
1113
DIRECT_CALL,
1214
LAMBDA_CONTAINMENT,
1315
IOC_INJECTION,

src/main/kotlin/org/skgroup/securityinspector/ui/renderer/ResultTreeRenderer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ResultTreeRenderer : DefaultTreeCellRenderer() {
3434
RefMode.CALL -> icon = IconUtil.callIcon
3535
RefMode.DECLARATION -> icon = IconUtil.declarationIcon
3636
RefMode.NEW -> icon = IconUtil.newIcon
37+
RefMode.IMPLEMENTATION -> {}
3738
else -> {}
3839
}
3940
"$refMode : ${

0 commit comments

Comments
 (0)