Skip to content

Commit 131bf02

Browse files
authored
Add refresh action, show busy icon on refresh (#361)
1 parent 0dfe869 commit 131bf02

File tree

13 files changed

+135
-40
lines changed

13 files changed

+135
-40
lines changed

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/FocusAction.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ class FocusAction(val path: Path) : AnAction("Show") {
1414
?: error("Focus action should be disabled for path $path")
1515

1616
val project = e.activeProject()
17-
val projectInstance = PsiManager.getInstance(project)
17+
val psiManager = PsiManager.getInstance(project)
1818

1919

2020
if (virtualFile.isDirectory) {
21-
projectInstance.findDirectory(virtualFile)?.navigate(true)
21+
psiManager.findDirectory(virtualFile)?.navigate(true)
2222
} else {
23-
projectInstance.findFile(virtualFile)?.navigate(true)
23+
psiManager.findFile(virtualFile)?.navigate(true)
2424
}
2525
}
2626

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.utbot.cpp.clion.plugin.actions
2+
3+
import com.intellij.icons.AllIcons
4+
import com.intellij.openapi.actionSystem.AnAction
5+
import com.intellij.openapi.actionSystem.AnActionEvent
6+
import com.intellij.openapi.components.service
7+
import org.utbot.cpp.clion.plugin.ui.targetsToolWindow.UTBotTargetsController
8+
import org.utbot.cpp.clion.plugin.utils.activeProject
9+
10+
class RefreshTargetsAction: AnAction() {
11+
override fun actionPerformed(e: AnActionEvent) {
12+
e.activeProject().service<UTBotTargetsController>().requestTargetsFromServer()
13+
}
14+
15+
override fun update(e: AnActionEvent) {
16+
e.presentation.isEnabledAndVisible = e.project != null
17+
e.presentation.icon = AllIcons.Actions.Refresh
18+
}
19+
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/ClientManager.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.utbot.cpp.clion.plugin.client
22

33
import com.intellij.openapi.Disposable
4+
import com.intellij.openapi.application.ApplicationManager
45
import com.intellij.openapi.components.Service
56
import com.intellij.openapi.project.Project
67
import org.utbot.cpp.clion.plugin.client.channels.GTestLogChannelImpl
@@ -22,11 +23,11 @@ class ClientManager(val project: Project): Disposable {
2223
}
2324

2425
private fun subscribeToEvents() {
25-
with(project.messageBus.connect()) {
26+
with(ApplicationManager.getApplication().messageBus.connect()) {
2627
subscribe(ConnectionSettingsListener.TOPIC, object : ConnectionSettingsListener {
2728
override fun connectionSettingsChanged(newPort: Int, newServerName: String) {
2829
if (newPort != client.port || newServerName != client.serverName) {
29-
project.logger.trace{ "Connection settings changed. Setting up new client." }
30+
project.logger.trace { "Connection settings changed. Setting up new client." }
3031
client.dispose()
3132
client = Client(project, clientId, loggingChannels)
3233
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/ProjectTargetsRequest.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,20 @@ import testsgen.TestsGenServiceGrpcKt
88
class ProjectTargetsRequest(
99
project: Project,
1010
request: Testgen.ProjectTargetsRequest,
11-
val processTargets: suspend (Testgen.ProjectTargetsResponse)->Unit
11+
val processTargets: suspend (Testgen.ProjectTargetsResponse)->Unit,
12+
val onError: suspend (Throwable) -> Unit
1213
): BaseRequest<Testgen.ProjectTargetsRequest, Testgen.ProjectTargetsResponse>(request, project) {
1314

1415
override val logMessage: String = "Sending request to get project targets"
1516

17+
override suspend fun execute(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub, cancellationJob: Job?) {
18+
try {
19+
super.execute(stub, cancellationJob)
20+
} catch (e: Throwable) {
21+
onError(e)
22+
}
23+
}
24+
1625
override suspend fun Testgen.ProjectTargetsResponse.handle(cancellationJob: Job?) = processTargets(this)
1726

1827
override suspend fun TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub.send(cancellationJob: Job?): Testgen.ProjectTargetsResponse =

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/BaseTestsRequest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.utbot.cpp.clion.plugin.client.handlers.TestsStreamHandler
88
import org.utbot.cpp.clion.plugin.client.requests.BaseRequest
99
import org.utbot.cpp.clion.plugin.utils.getLongestCommonPathFromRoot
1010
import org.utbot.cpp.clion.plugin.utils.isHeaderFile
11+
import org.utbot.cpp.clion.plugin.utils.isSarifReport
1112
import org.utbot.cpp.clion.plugin.utils.logger
1213
import org.utbot.cpp.clion.plugin.utils.notifyInfo
1314
import testsgen.Testgen
@@ -35,7 +36,7 @@ abstract class BaseTestsRequest<R>(request: R, project: Project, private val pro
3536
}
3637

3738
open fun getFocusTarget(generatedTestFiles: List<Path>): Path? {
38-
return generatedTestFiles.filter { !isHeaderFile(it.fileName.toString()) }.getLongestCommonPathFromRoot()
39+
return generatedTestFiles.filter { !isHeaderFile(it) && !isSarifReport(it) }.getLongestCommonPathFromRoot()
3940
}
4041

4142
override fun logRequest() {

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ class UTBotAllProjectSettings(val project: Project) {
2020
get() = project.service<UTBotProjectStoredSettings>().state
2121

2222
var projectPath: String
23-
get() = storedSettings.projectPath ?: project.guessProjectDir()?.path
24-
?: error("Could not guess project path! Should be specified in settings by user")
23+
get() {
24+
// if true then there is nothing persisted in xml files and plugin was launched for the first time
25+
if (storedSettings.projectPath == null)
26+
// so we should guess the project path
27+
storedSettings.projectPath = project.guessProjectDir()?.path
28+
return storedSettings.projectPath
29+
?: error("Could not guess project path! Should be specified in settings by user")
30+
}
2531
set(value) {
2632
storedSettings.projectPath = value
2733
}
@@ -49,7 +55,8 @@ class UTBotAllProjectSettings(val project: Project) {
4955
*/
5056
val isRemoteScenario: Boolean
5157
get() {
52-
val isLocalHost = projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
58+
val isLocalHost =
59+
projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
5360
return !(storedSettings.remotePath == projectPath && isLocalHost) || isWindows
5461
}
5562

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotProjectIndependentSettings.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.utbot.cpp.clion.plugin.settings
22

3+
import com.intellij.openapi.application.ApplicationManager
34
import com.intellij.openapi.components.PersistentStateComponent
45
import com.intellij.openapi.components.Service
56
import com.intellij.openapi.components.State
67
import com.intellij.openapi.components.Storage
8+
import org.utbot.cpp.clion.plugin.listeners.ConnectionSettingsListener
79

810
/**
911
* Settings that are the same for all projects
@@ -22,11 +24,17 @@ class UTBotProjectIndependentSettings : PersistentStateComponent<UTBotProjectInd
2224
port = model.globalSettings.port
2325
serverName = model.globalSettings.serverName
2426
}
27+
28+
fun fireConnectionSettingsChanged() {
29+
ApplicationManager.getApplication().messageBus.syncPublisher(ConnectionSettingsListener.TOPIC)
30+
.connectionSettingsChanged(port, serverName)
31+
}
2532
}
2633

2734
private var myState: State = State()
2835
override fun getState(): State = myState
2936
override fun loadState(state: State) {
3037
myState = state
3138
}
39+
3240
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/targetsToolWindow/UTBotTargetsController.kt

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow
22

3+
import com.intellij.openapi.components.Service
34
import com.intellij.openapi.project.Project
45
import com.intellij.ui.CollectionListModel
56
import org.utbot.cpp.clion.plugin.client.requests.ProjectTargetsRequest
@@ -13,13 +14,16 @@ import org.utbot.cpp.clion.plugin.utils.getCurrentClient
1314
import org.utbot.cpp.clion.plugin.utils.invokeOnEdt
1415
import org.utbot.cpp.clion.plugin.utils.logger
1516
import org.utbot.cpp.clion.plugin.utils.relativize
17+
import testsgen.Testgen
1618

19+
@Service
1720
class UTBotTargetsController(val project: Project) {
1821
private val settings: UTBotAllProjectSettings
1922
get() = project.settings
2023

21-
private val listModel = CollectionListModel(mutableListOf(UTBotTarget.autoTarget))
22-
private val logger = project.logger
24+
private val listModel = CollectionListModel(mutableListOf<UTBotTarget>())
25+
private val logger get() = project.logger
26+
val targetsToolWindow: UTBotTargetsToolWindow by lazy { UTBotTargetsToolWindow(listModel, this) }
2327

2428
val targets: List<UTBotTarget>
2529
get() = listModel.toList()
@@ -32,23 +36,35 @@ class UTBotTargetsController(val project: Project) {
3236
fun requestTargetsFromServer() {
3337
val currentClient = project.getCurrentClient()
3438

39+
invokeOnEdt {
40+
listModel.removeAll()
41+
targetsToolWindow.setBusy(true)
42+
}
3543
ProjectTargetsRequest(
3644
project,
3745
getProjectTargetsGrpcRequest(project),
38-
) { targetsResponse ->
39-
invokeOnEdt {
40-
listModel.apply {
41-
val oldTargetList = toList()
42-
oldTargetList.addAll(
43-
targetsResponse.targetsList.map { projectTarget ->
44-
UTBotTarget(projectTarget, project)
45-
})
46-
listModel.replaceAll(oldTargetList.distinct())
46+
processTargets = { targetsResponse: Testgen.ProjectTargetsResponse ->
47+
invokeOnEdt {
48+
targetsToolWindow.setBusy(false)
49+
50+
listModel.apply {
51+
listModel.replaceAll(
52+
targetsResponse.targetsList.map { projectTarget ->
53+
UTBotTarget(projectTarget, project)
54+
})
55+
}
4756
}
48-
}
49-
}.let { targetsRequest ->
57+
},
58+
onError = {
59+
invokeOnEdt {
60+
targetsToolWindow.setBusy(false)
61+
}
62+
}).let { targetsRequest ->
5063
if (!currentClient.isServerAvailable()) {
5164
logger.error { "Could not request targets from server: server is unavailable!" }
65+
invokeOnEdt {
66+
targetsToolWindow.setBusy(false)
67+
}
5268
return
5369
}
5470
logger.trace { "Requesting project targets from server!" }
@@ -68,8 +84,6 @@ class UTBotTargetsController(val project: Project) {
6884
}
6985
}
7086

71-
fun createTargetsToolWindow(): UTBotTargetsToolWindow = UTBotTargetsToolWindow(listModel, this)
72-
7387
fun selectionChanged(selectedTarget: UTBotTarget) {
7488
// when user selects target update model
7589
settings.storedSettings.targetPath = selectedTarget.path
@@ -94,7 +108,7 @@ class UTBotTargetsController(val project: Project) {
94108
UTBotEventsListener.CONNECTION_CHANGED_TOPIC,
95109
object : UTBotEventsListener {
96110
override fun onConnectionChange(oldStatus: ConnectionStatus, newStatus: ConnectionStatus) {
97-
if (newStatus != oldStatus && newStatus == ConnectionStatus.CONNECTED) {
111+
if (newStatus != oldStatus) {
98112
requestTargetsFromServer()
99113
}
100114
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/targetsToolWindow/UTBotTargetsToolWindow.kt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow
22

3+
import com.intellij.openapi.actionSystem.ActionGroup
4+
import com.intellij.openapi.actionSystem.ActionManager
5+
import com.intellij.openapi.actionSystem.ActionPlaces
6+
import com.intellij.openapi.actionSystem.ActionToolbar
7+
import com.intellij.openapi.actionSystem.DefaultActionGroup
8+
import com.intellij.openapi.project.DumbAware
39
import com.intellij.openapi.ui.SimpleToolWindowPanel
410
import com.intellij.ui.CollectionListModel
511
import com.intellij.ui.ColoredListCellRenderer
@@ -8,24 +14,47 @@ import com.intellij.ui.components.JBList
814
import com.intellij.ui.components.JBScrollPane
915
import javax.swing.JList
1016
import javax.swing.ListSelectionModel
17+
import org.utbot.cpp.clion.plugin.UTBot
18+
import org.utbot.cpp.clion.plugin.actions.RefreshTargetsAction
19+
import org.utbot.cpp.clion.plugin.utils.logger
1120

1221
class UTBotTargetsToolWindow(
1322
listModel: CollectionListModel<UTBotTarget>,
14-
private val controller: UTBotTargetsController,
15-
): SimpleToolWindowPanel(true, true) {
23+
private val controller: UTBotTargetsController
24+
): SimpleToolWindowPanel(true, true), DumbAware {
1625
private val uiList = JBList(listModel)
1726

1827
init {
19-
val panel = JBScrollPane()
28+
toolbar = createActionToolBar().let {
29+
it.targetComponent = this.component
30+
it.component
31+
}
32+
2033
uiList.cellRenderer = Renderer()
2134
uiList.selectionMode = ListSelectionModel.SINGLE_SELECTION
2235
uiList.addListSelectionListener {
23-
controller.selectionChanged(uiList.selectedValue)
36+
if (!uiList.isSelectionEmpty)
37+
controller.selectionChanged(uiList.selectedValue)
2438
}
39+
uiList.setEmptyText(UTBot.message("targets.notargets.description"))
40+
41+
val panel = JBScrollPane()
2542
panel.setViewportView(uiList)
2643
setContent(panel)
2744
}
2845

46+
fun setBusy(busy: Boolean) {
47+
uiList.setPaintBusy(busy)
48+
}
49+
50+
private fun createActionToolBar(isHorizontal: Boolean = false): ActionToolbar {
51+
return ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLBAR, createActionGroup(), isHorizontal)
52+
}
53+
54+
private fun createActionGroup(): ActionGroup {
55+
return DefaultActionGroup(RefreshTargetsAction())
56+
}
57+
2958
private inner class Renderer : ColoredListCellRenderer<UTBotTarget>() {
3059
override fun customizeCellRenderer(
3160
list: JList<out UTBotTarget>,
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow
22

3+
import com.intellij.openapi.components.service
34
import com.intellij.openapi.diagnostic.Logger
45
import com.intellij.openapi.project.Project
56
import com.intellij.openapi.wm.ToolWindow
@@ -11,9 +12,9 @@ class UTBotTargetsToolWindowFactory : ToolWindowFactory {
1112
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
1213
logger.info("createToolWindowContent was called")
1314
val contentManager = toolWindow.contentManager
14-
val utbotToolWindow = UTBotTargetsController(project).createTargetsToolWindow()
15-
16-
val content = contentManager.factory.createContent(utbotToolWindow, null, false,)
17-
contentManager.addContent(content)
15+
val content = contentManager.factory.createContent(
16+
project.service<UTBotTargetsController>().targetsToolWindow, null, false
17+
)
18+
toolWindow.contentManager.addContent(content)
1819
}
1920
}

0 commit comments

Comments
 (0)