diff --git a/src/main/kotlin/callgraph/CallGraphToolWindow.form b/src/main/kotlin/callgraph/CallGraphToolWindow.form index 9f281a5..89fc9c5 100644 --- a/src/main/kotlin/callgraph/CallGraphToolWindow.form +++ b/src/main/kotlin/callgraph/CallGraphToolWindow.form @@ -3,7 +3,7 @@ - + @@ -183,7 +183,7 @@ - + @@ -433,19 +433,70 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + @@ -459,7 +510,7 @@ - + @@ -470,7 +521,7 @@ - + @@ -479,93 +530,61 @@ - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + - - + + - + - + + + diff --git a/src/main/kotlin/callgraph/CallGraphToolWindow.kt b/src/main/kotlin/callgraph/CallGraphToolWindow.kt index d1e9b1e..e9e450c 100644 --- a/src/main/kotlin/callgraph/CallGraphToolWindow.kt +++ b/src/main/kotlin/callgraph/CallGraphToolWindow.kt @@ -38,6 +38,7 @@ class CallGraphToolWindow { private lateinit var nodeSelectionComboBox: JComboBox private lateinit var searchTextField: JTextField private lateinit var nodeColorComboBox: JComboBox + private lateinit var filterExternalCheckbox: JCheckBox private lateinit var filterAccessPublicCheckbox: JCheckBox private lateinit var filterAccessProtectedCheckbox: JCheckBox private lateinit var filterAccessPackageLocalCheckbox: JCheckBox @@ -46,7 +47,8 @@ class CallGraphToolWindow { private val canvasBuilder = CanvasBuilder() private val canvas: Canvas = Canvas(this) private val focusedMethods = mutableSetOf() - private val filterAccessCheckboxes = listOf( + private val filterCheckboxes = listOf( + this.filterExternalCheckbox, this.filterAccessPublicCheckbox, this.filterAccessProtectedCheckbox, this.filterAccessPackageLocalCheckbox, @@ -90,7 +92,7 @@ class CallGraphToolWindow { this@CallGraphToolWindow.canvas.repaint() } }) - this.filterAccessCheckboxes.forEach { it.addActionListener { this.canvas.filterAccessChangeHandler() } } + this.filterCheckboxes.forEach { it.addActionListener { this.canvas.filterChangeHandler() } } // click handlers for buttons this.projectScopeButton.addActionListener { projectScopeButtonHandler() } @@ -123,13 +125,9 @@ class CallGraphToolWindow { this.canvasPanel.add(this.canvas) } - fun getContent(): JPanel { - return this.callGraphToolWindowContent - } + fun getContent() = this.callGraphToolWindowContent - fun isFocusedMethod(method: PsiMethod): Boolean { - return this.focusedMethods.contains(method) - } + fun isFocusedMethod(method: PsiMethod) = this.focusedMethods.contains(method) fun toggleFocusedMethod(method: PsiMethod): CallGraphToolWindow { if (this.focusedMethods.contains(method)) { @@ -182,29 +180,19 @@ class CallGraphToolWindow { return searchQuery.isNotEmpty() && text.toLowerCase().contains(searchQuery) } - fun isNodeColorByAccess(): Boolean { - return getSelectedComboBoxOption(this.nodeColorComboBox) == ComboBoxOptions.NODE_COLOR_ACCESS - } + fun isNodeColorByAccess() = getSelectedComboBoxOption(this.nodeColorComboBox) == ComboBoxOptions.NODE_COLOR_ACCESS - fun isNodeColorByClassName(): Boolean { - return getSelectedComboBoxOption(this.nodeColorComboBox) == ComboBoxOptions.NODE_COLOR_CLASS - } + fun isNodeColorByClassName() = getSelectedComboBoxOption(this.nodeColorComboBox) == ComboBoxOptions.NODE_COLOR_CLASS - fun isFilterAccessPublicChecked(): Boolean { - return this.filterAccessPublicCheckbox.isSelected - } + fun isFilterExternalChecked() = this.filterExternalCheckbox.isSelected - fun isFilterAccessProtectedChecked(): Boolean { - return this.filterAccessProtectedCheckbox.isSelected - } + fun isFilterAccessPublicChecked() = this.filterAccessPublicCheckbox.isSelected - fun isFilterAccessPackageLocalChecked(): Boolean { - return this.filterAccessPackageLocalCheckbox.isSelected - } + fun isFilterAccessProtectedChecked() = this.filterAccessProtectedCheckbox.isSelected - fun isFilterAccessPrivateChecked(): Boolean { - return this.filterAccessPrivateCheckbox.isSelected - } + fun isFilterAccessPackageLocalChecked() = this.filterAccessPackageLocalCheckbox.isSelected + + fun isFilterAccessPrivateChecked() = this.filterAccessPrivateCheckbox.isSelected fun getCanvasSize(): Dimension = this.canvasPanel.size @@ -331,7 +319,7 @@ class CallGraphToolWindow { this.searchTextField ).forEach { (it as JComponent).isEnabled = false } // filter-related checkboxes - this.filterAccessCheckboxes.forEach { + this.filterCheckboxes.forEach { it.isEnabled = false it.isSelected = true } @@ -365,7 +353,7 @@ class CallGraphToolWindow { this.searchTextField ).forEach { (it as JComponent).isEnabled = true } // filter-related checkboxes - this.filterAccessCheckboxes.forEach { it.isEnabled = true } + this.filterCheckboxes.forEach { it.isEnabled = true } } private fun getSelectedBuildType(): CanvasConfig.BuildType { diff --git a/src/main/kotlin/callgraph/Canvas.kt b/src/main/kotlin/callgraph/Canvas.kt index 676b887..3094488 100644 --- a/src/main/kotlin/callgraph/Canvas.kt +++ b/src/main/kotlin/callgraph/Canvas.kt @@ -165,21 +165,23 @@ class Canvas(private val callGraphToolWindow: CallGraphToolWindow): JPanel() { repaint() } - fun getNodesCount(): Int { - return this.graph.getNodes().size - } + fun getNodesCount() = this.graph.getNodes().size - fun filterAccessChangeHandler() { + fun filterChangeHandler() { this.visibleNodes = this.graph.getNodes() .filter { node -> val method = node.method - when { + val isVisibleAccessLevel = when { Utils.isPublic(method) -> this.callGraphToolWindow.isFilterAccessPublicChecked() Utils.isProtected(method) -> this.callGraphToolWindow.isFilterAccessProtectedChecked() Utils.isPackageLocal(method) -> this.callGraphToolWindow.isFilterAccessPackageLocalChecked() Utils.isPrivate(method) -> this.callGraphToolWindow.isFilterAccessPrivateChecked() else -> true } + val isExternalMethod = Utils.getSourceRoot(method.containingFile.virtualFile) == null + val isVisibleExternal = !isExternalMethod || this.callGraphToolWindow.isFilterExternalChecked() + + isVisibleAccessLevel && isVisibleExternal } .toSet() this.visibleEdges = this.graph.getEdges() @@ -248,7 +250,7 @@ class Canvas(private val callGraphToolWindow: CallGraphToolWindow): JPanel() { } // file path if (this.callGraphToolWindow.isRenderFunctionFilePath(isNodeHovered)) { - val filePath = Utils.getMethodFilePath(node.method) + val filePath = Utils.getMethodFilePath(node.method) ?: "(no file)" labels.add(filePath to Colors.UN_HIGHLIGHTED_COLOR.color) } return labels diff --git a/src/main/kotlin/callgraph/Utils.kt b/src/main/kotlin/callgraph/Utils.kt index b52a6ab..0f942de 100644 --- a/src/main/kotlin/callgraph/Utils.kt +++ b/src/main/kotlin/callgraph/Utils.kt @@ -126,31 +126,25 @@ object Utils { }) } - fun getMethodPackageName(psiMethod: PsiMethod): String { + fun getMethodPackageName(method: PsiMethod): String { // get package name - val psiJavaFile = psiMethod.containingFile as PsiJavaFile + val psiJavaFile = method.containingFile as PsiJavaFile val packageName = psiJavaFile.packageStatement?.packageName ?: "" // get class name - val className = psiMethod.containingClass?.qualifiedName ?: "" + val className = method.containingClass?.qualifiedName ?: "" return if (packageName.isBlank() || className.startsWith(packageName)) className else "$packageName.$className" } - fun getMethodFilePath(method: PsiMethod): String { - val psiFile = PsiTreeUtil.getParentOfType(method, PsiFile::class.java) - if (psiFile != null) { - val currentFile = psiFile.virtualFile - val project = getActiveProject() - if (project != null) { - val rootFile = ProjectFileIndex.SERVICE.getInstance(project).getContentRootForFile(currentFile) - if (rootFile != null) { - val relativePath = VfsUtilCore.getRelativePath(currentFile, rootFile) - if (relativePath != null) { - return relativePath - } - } - } - } - return "(empty)" + fun getMethodFilePath(method: PsiMethod): String? { + val file = method.containingFile.virtualFile + val sourceRoot = getSourceRoot(file) + return if (sourceRoot == null) null else VfsUtilCore.getRelativePath(file, sourceRoot) + } + + fun getSourceRoot(file: VirtualFile): VirtualFile? { + val project = getActiveProject() + + return if (project == null) null else ProjectFileIndex.SERVICE.getInstance(project).getContentRootForFile(file) } fun getMethodSignature(method: PsiMethod): String {