diff --git a/README.md b/README.md
index 0050d2e..d12c71b 100644
--- a/README.md
+++ b/README.md
@@ -13,3 +13,7 @@ Features
- Jump from post to subscribe and vice versa
- Shows marker only for `@Subscribe` methods that have correct signatures
- Fully supported for project using both Java and Kotlin
+
+Testing
+-----
+There are no unit tests yet (I am writing them, but hit a roadblock. We will soon find a way). Any changes made to the plugin should be tested against this project. This project contains all possible use cases of EventBus in both Java and Kotlin.
diff --git a/build.gradle b/build.gradle
index c85adf0..8c24c65 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ plugins {
}
group 'com.madrapps'
-version '0.3.3.2018.3'
+version '0.4.2.2018.3'
sourceCompatibility = 1.8
@@ -34,10 +34,7 @@ compileTestKotlin {
patchPluginXml {
changeNotes """
- - Option to view usages in "Find" tool window
- - Improved the UI of the usages popup
- - Support for Enums
- - Support for `@file:JvmName()`
- - Performance improvement
+ - Add breakpoints to `post` or `subscribe` in a single click
+ - Option to clear added breakpoints as well
"""
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/madrapps/eventbus/FindUsages.kt b/src/main/kotlin/com/madrapps/eventbus/FindUsages.kt
index 2ca10c8..1967485 100644
--- a/src/main/kotlin/com/madrapps/eventbus/FindUsages.kt
+++ b/src/main/kotlin/com/madrapps/eventbus/FindUsages.kt
@@ -48,4 +48,10 @@ internal fun UElement.getParentOfTypeCallExpression(): UCallExpression? {
.filterIsInstance()
.firstOrNull()
?.selector as? UCallExpression
-}
\ No newline at end of file
+}
+
+internal fun Usage.getPostStatementSourcePsi() = toUElement()?.getParentOfTypeCallExpression()?.sourcePsi
+
+internal fun Usage.getSubscribeMethodSourcePsi() = getType()?.uastAnchor?.sourcePsi
+
+internal fun Usage.file() = toUElement()?.sourcePsi?.containingFile
\ No newline at end of file
diff --git a/src/main/kotlin/com/madrapps/eventbus/PopUpView.kt b/src/main/kotlin/com/madrapps/eventbus/PopUpView.kt
index 191a868..6443a89 100644
--- a/src/main/kotlin/com/madrapps/eventbus/PopUpView.kt
+++ b/src/main/kotlin/com/madrapps/eventbus/PopUpView.kt
@@ -1,5 +1,9 @@
package com.madrapps.eventbus
+import com.intellij.debugger.DebuggerManagerEx
+import com.intellij.debugger.ui.breakpoints.BreakpointManager
+import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter
+import com.intellij.icons.AllIcons
import com.intellij.icons.AllIcons.Toolwindows.ToolWindowFind
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces.USAGE_VIEW_TOOLBAR
@@ -7,8 +11,10 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.IdeActions.ACTION_FIND_USAGES
+import com.intellij.openapi.editor.Document
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
+import com.intellij.psi.PsiDocumentManager
import com.intellij.ui.ScrollingUtil
import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.SimpleTextAttributes.REGULAR_ATTRIBUTES
@@ -20,6 +26,9 @@ import com.intellij.util.PlatformIcons
import com.intellij.util.ui.ColumnInfo
import com.intellij.util.ui.ListTableModel
import com.intellij.util.ui.UIUtil
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties
+import org.jetbrains.kotlin.idea.refactoring.getLineNumber
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UFile
import org.jetbrains.uast.UMethod
@@ -91,7 +100,11 @@ private fun showTablePopUp(usages: List, columnInfos: Array
if (usages.isNotEmpty()) {
val actionGroup = DefaultActionGroup()
- actionGroup.add(ShowUsagesAction(usages) { popUp?.closeOk(it) })
+ val closePopUp: (InputEvent) -> Unit = { popUp?.closeOk(it) }
+ actionGroup.add(SetBreakpointAction(usages, closePopUp))
+ actionGroup.add(RemoveBreakpointAction(usages, closePopUp))
+ actionGroup.addSeparator()
+ actionGroup.add(ShowUsagesAction(usages, closePopUp))
val actionToolbar = ActionManager.getInstance().createActionToolbar(USAGE_VIEW_TOOLBAR, actionGroup, true)
actionToolbar.setReservePlaceAutoPopupIcon(false)
val toolBar = actionToolbar.component
@@ -103,7 +116,7 @@ private fun showTablePopUp(usages: List, columnInfos: Array
return popUp
}
-private fun getTitle(usages: List) = if (usages.isEmpty()) "No usages found" else "Find Usages"
+private fun getTitle(usages: List) = if (usages.isEmpty()) "No usages found" else "Usages"
private fun resizeColumnWidth(table: JTable) {
val columnModel = table.columnModel
@@ -199,4 +212,94 @@ private class ShowUsagesAction(
usageViewPresentation
)
}
+}
+
+private class SetBreakpointAction(
+ private val usages: List,
+ private val closePopUp: (InputEvent) -> Unit
+) : AnAction(
+ "Set Breakpoints",
+ "Set breakpoints at all usages",
+ AllIcons.Debugger.Db_set_breakpoint
+) {
+ override fun actionPerformed(e: AnActionEvent) {
+ closePopUp(e.inputEvent)
+ val breakpointManager = DebuggerManagerEx.getInstanceEx(e.project!!).breakpointManager
+ usages.forEach {
+ val containingFile = it.file()
+ if (containingFile != null) {
+ val document = PsiDocumentManager.getInstance(e.project!!).getDocument(containingFile)
+ if (document != null) {
+ val isBreakpointAdded = addLineBreakpoint(it, breakpointManager, document)
+ if (!isBreakpointAdded) {
+ addMethodBreakpoint(it, breakpointManager, document)
+ }
+ }
+ }
+ }
+ }
+
+ private fun addLineBreakpoint(
+ it: Usage,
+ breakpointManager: BreakpointManager,
+ document: Document
+ ): Boolean {
+ val sourcePsi = it.getPostStatementSourcePsi()
+ if (sourcePsi != null) {
+ val lineNumber = sourcePsi.getLineNumber(true)
+ breakpointManager.addLineBreakpoint(document, lineNumber)
+ }
+ return sourcePsi != null
+ }
+
+ private fun addMethodBreakpoint(
+ it: Usage,
+ breakpointManager: BreakpointManager,
+ document: Document?
+ ) {
+ val source = it.getSubscribeMethodSourcePsi()
+ if (source != null) {
+ val lineNumber = source.getLineNumber(true)
+ if (breakpointManager.findBreakpoint>>(
+ document,
+ source.startOffset,
+ null
+ ) == null
+ ) {
+ breakpointManager.addMethodBreakpoint(document, lineNumber)
+ }
+ }
+ }
+}
+
+private class RemoveBreakpointAction(
+ private val usages: List,
+ private val closePopUp: (InputEvent) -> Unit
+) : AnAction(
+ "Remove Breakpoints",
+ "Remove breakpoints at all usages",
+ AllIcons.Debugger.MuteBreakpoints
+) {
+ override fun actionPerformed(e: AnActionEvent) {
+ closePopUp(e.inputEvent)
+ val project = e.project!!
+ val breakpointManager = DebuggerManagerEx.getInstanceEx(project).breakpointManager
+ val documentManager = PsiDocumentManager.getInstance(project)
+ usages.forEach {
+ val containingFile = it.file()
+ if (containingFile != null) {
+ val document = documentManager.getDocument(containingFile)
+ val source = it.getPostStatementSourcePsi() ?: it.getSubscribeMethodSourcePsi()
+ if (source != null && document != null) {
+ val breakPoint =
+ breakpointManager.findBreakpoint>>(
+ document,
+ source.startOffset,
+ null
+ )
+ breakpointManager.removeBreakpoint(breakPoint)
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 056ea32..75fe0f0 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -10,6 +10,8 @@
Supports post, postSticky and @Subscribe
Jump from post to subscribe and vice versa
Shows marker only for @Subscribe methods that have correct signatures
+ Optionally show usages in 'Find' tool window
+ Add breakpoints to all usages in a single click
Fully supported for project using both Java and Kotlin
]]>