@@ -7,10 +7,11 @@ import com.intellij.openapi.progress.ProgressManager
77import com.intellij.openapi.progress.Task
88import com.intellij.openapi.project.Project
99import com.intellij.openapi.ui.ComboBox
10- import com.intellij.psi.PsiFile
11- import com.intellij.psi.PsiJavaFile
12- import com.intellij.psi.PsiMethod
10+ import com.intellij.psi.*
11+ import com.intellij.psi.search.GlobalSearchScope
1312import com.intellij.psi.search.ProjectScope
13+ import com.intellij.psi.search.searches.ReferencesSearch
14+ import com.intellij.psi.util.PsiTreeUtil
1415import com.intellij.ui.Gray
1516import com.intellij.ui.components.JBTextArea
1617import org.skgroup.securityinspector.analysis.ast.nodes.MethodNode
@@ -29,7 +30,6 @@ object CallGraphGenerator {
2930 progressBar : JProgressBar ,
3031 infoArea : JTextArea ,
3132 rootListModel : DefaultListModel <MethodNode >,
32- sinkListModel : DefaultListModel <MethodNode >,
3333 searchComboBox : ComboBox <AnalysisScope >
3434 ) {
3535 progressBar.apply {
@@ -136,15 +136,13 @@ object CallGraphGenerator {
136136 * @param progressBar
137137 * @param infoArea
138138 * @param rootListModel
139- * @param sinkListModel
140139 */
141140 fun generate (
142141 project : Project ,
143142 method : PsiMethod ,
144143 progressBar : JProgressBar ,
145144 infoArea : JBTextArea ,
146145 rootListModel : DefaultListModel <MethodNode >,
147- sinkListModel : DefaultListModel <MethodNode >
148146 ) {
149147 progressBar.apply {
150148 isVisible = true
@@ -154,10 +152,8 @@ object CallGraphGenerator {
154152 string = " Initializing..."
155153 }
156154
157- // TODO 现在的调用图只有一个方法的上下文,非常残缺,需要拓展
158- // TODO 现在每次生成会覆盖原有调用图(因为方法从完整调用图得来),对于单个方法,需要考虑增量
159155 ProgressManager .getInstance().run (object : Task .Backgroundable (project, " Generating CallGraph" , true ) {
160- private var newGraph : CallGraph ? = null
156+ private var tempGraph : CallGraph ? = null
161157
162158 override fun run (indicator : ProgressIndicator ) {
163159
@@ -170,20 +166,46 @@ object CallGraphGenerator {
170166 indicator.text = " Analyzing ${method.name} "
171167
172168 val builder = CallGraphBuilder ()
169+ ReferencesSearch .search(method, GlobalSearchScope .projectScope(project)).forEach { reference ->
170+ var callerMethod: PsiMethod = method
171+ ApplicationManager .getApplication().runReadAction {
172+ callerMethod = PsiTreeUtil .getParentOfType(reference.element, PsiMethod ::class .java)
173+ ? : return @runReadAction
174+ }
175+ if (callerMethod != method) {
176+ generate(project, callerMethod, progressBar, infoArea, rootListModel)
177+ }
178+ }
173179 ApplicationManager .getApplication().runReadAction {
174180 method.accept(builder)
175181 }
176182 progressBar.string = " Building CallGraph for method ${method.name} "
177183
178- newGraph = builder.getCallGraph(project)
184+ tempGraph = builder.getCallGraph(project)
179185 }
180186
187+ // override fun onSuccess() {
188+ // newGraph?.let { graph ->
189+ // ApplicationManager.getApplication().invokeLater {
190+ // CallGraphMemoryService.getInstance(project).setCallGraph(graph)
191+ // infoArea.append("Build CallGraph for method ${method.name} with ${graph.nodes.size} methods.\n")
192+ // updateRootAndSinkLists(graph, rootListModel)
193+ // }
194+ // }
195+ // }
196+ // 注释原有图生成,采用增量方式替换
181197 override fun onSuccess () {
182- newGraph ?.let { graph ->
198+ tempGraph ?.let { delta ->
183199 ApplicationManager .getApplication().invokeLater {
184- CallGraphMemoryService .getInstance(project).setCallGraph(graph)
185- infoArea.append(" Build CallGraph for method ${method.name} with ${graph.nodes.size} methods.\n " )
186- updateRootAndSinkLists(graph, rootListModel)
200+ val memoryService = CallGraphMemoryService .getInstance(project)
201+ val currentGraph = memoryService.getCallGraph() ? : CallGraph ()
202+
203+ // 合并
204+ currentGraph.merge(delta)
205+ memoryService.setCallGraph(currentGraph)
206+
207+ infoArea.append(" Added ${delta.nodes.size} nodes for Call graph\n " )
208+ updateRootAndSinkLists(currentGraph, rootListModel)
187209 }
188210 }
189211 }
@@ -206,21 +228,13 @@ object CallGraphGenerator {
206228 private fun updateRootAndSinkLists (
207229 callGraph : CallGraph ,
208230 rootListModel : DefaultListModel <MethodNode >,
209- // sinkListModel: DefaultListModel<MethodNode>
210231 ) {
211232 rootListModel.clear()
212- // sinkListModel.clear()
213233
214234 val allCallees = callGraph.edges.values.flatten().toSet()
215235 val roots = callGraph.nodes.filter { it !in allCallees }.sortedBy { it.name }
216236
217- val sinks = callGraph.nodes.filter { node ->
218- val callees = callGraph.edges[node]
219- callees.isNullOrEmpty()
220- }.sortedBy { it.name }
221-
222237 roots.forEach(rootListModel::addElement)
223- // sinks.forEach(sinkListModel::addElement)
224238 }
225239
226240 private fun showModuleSelectorDialog (project : Project ): Module {
0 commit comments