Skip to content

Commit 9314a3f

Browse files
authored
add ability to enable/disable plugin per project (#404)
* fix merge conflicts * add more docs * don't hide toolwindows on disabling * hide/show settings ui when enabling/disabling plugin * required fixes * rebase * delete empty files * set plugin disabled on default, show wizard on first enabled * don't request targets in tests until ci is fixed * fix console accessed not from edt using lazy delegate * fix logging for tests using tinylog * fix tests: enable plugin & wait for connection
1 parent 10d73de commit 9314a3f

File tree

63 files changed

+585
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+585
-307
lines changed

clion-plugin/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ dependencies {
7070
implementation("com.google.protobuf:protobuf-kotlin:$protobufVersion")
7171

7272
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.3.2")
73+
implementation("org.tinylog:tinylog-api-kotlin:2.5.0")
74+
implementation("org.tinylog:tinylog-impl:2.5.0")
7375

7476
// testing with JUnit 5
7577
testImplementation(platform("org.junit:junit-bom:5.8.2"))
Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,31 @@
11
package org.utbot.cpp.clion.plugin
22

33
import com.intellij.ide.util.RunOnceUtil
4-
import com.intellij.openapi.application.ApplicationManager
54
import com.intellij.openapi.components.service
65
import com.intellij.openapi.project.Project
76
import com.intellij.openapi.startup.StartupActivity
8-
import org.utbot.cpp.clion.plugin.client.ClientManager
7+
import org.utbot.cpp.clion.plugin.client.ManagedClient
98
import org.utbot.cpp.clion.plugin.settings.settings
10-
import org.utbot.cpp.clion.plugin.ui.wizard.UTBotWizard
11-
import org.utbot.cpp.clion.plugin.utils.invokeOnEdt
129

1310
class UTBotStartupActivity : StartupActivity {
1411
override fun runActivity(project: Project) {
1512
// We initialize Client here, so that initialization will not happen
1613
// when user issues first generation request which would cause a UI freeze.
17-
initializeClient(project)
18-
guessPathsOnFirstOpen(project)
19-
showWizardOnFirstOpen(project)
14+
if (project.settings.storedSettings.isPluginEnabled) {
15+
initializeClient(project)
16+
guessPathsOnFirstOpen(project)
17+
}
2018
}
2119

2220
// Here we address the service ClientManager for the first time so that it
2321
// will be initialized by the ide and Client will be created.
2422
// Client in turn will create a grpc channel and start heart-beating the server.
25-
private fun initializeClient(project: Project) = project.service<ClientManager>()
26-
23+
private fun initializeClient(project: Project) = project.service<ManagedClient>()
2724

28-
private fun showWizardOnFirstOpen(project: Project) {
29-
if (!ApplicationManager.getApplication().isUnitTestMode) {
30-
invokeOnEdt {
31-
RunOnceUtil.runOnceForProject(project, "Show UTBot quick-start wizard to configure project") {
32-
UTBotWizard(project).showAndGet()
33-
}
34-
}
35-
}
36-
}
3725

3826
private fun guessPathsOnFirstOpen(project: Project) {
3927
RunOnceUtil.runOnceForProject(project, "Guess UTBot paths in settings") {
4028
project.settings.predictPaths()
4129
}
4230
}
43-
}
31+
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package org.utbot.cpp.clion.plugin.actions
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import org.utbot.cpp.clion.plugin.UTBot
65
import org.utbot.cpp.clion.plugin.client.requests.CreateBuildDirRequest
76

8-
class AskServerToGenerateBuildDir : AnAction(UTBot.message("projectConfigure.generate.buildDir")) {
7+
class AskServerToGenerateBuildDir : UTBotBaseAction(UTBot.message("projectConfigure.generate.buildDir")) {
98

10-
override fun actionPerformed(e: AnActionEvent) = CreateBuildDirRequest(e).executeUsingCurrentClient()
9+
override fun actionPerformed(e: AnActionEvent) = CreateBuildDirRequest(e).execute()
1110

12-
override fun update(e: AnActionEvent) {
11+
override fun updateIfEnabled(e: AnActionEvent) {
1312
e.presentation.isEnabledAndVisible = e.project != null
1413
}
1514
}
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package org.utbot.cpp.clion.plugin.actions
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import org.utbot.cpp.clion.plugin.UTBot
65
import org.utbot.cpp.clion.plugin.client.requests.GenerateJsonFilesRequest
76

8-
class AskServerToGenerateJsonForProjectConfiguration : AnAction(UTBot.message("projectConfigure.generate.json")) {
7+
class AskServerToGenerateJsonForProjectConfiguration : UTBotBaseAction(UTBot.message("projectConfigure.generate.json")) {
98

10-
override fun actionPerformed(e: AnActionEvent) = GenerateJsonFilesRequest(e).executeUsingCurrentClient()
9+
override fun actionPerformed(e: AnActionEvent) = GenerateJsonFilesRequest(e).execute()
1110

12-
override fun update(e: AnActionEvent) {
11+
override fun updateIfEnabled(e: AnActionEvent) {
1312
e.presentation.isEnabledAndVisible = e.project != null
1413
}
1514
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,19 @@ package org.utbot.cpp.clion.plugin.actions
33
import com.intellij.openapi.actionSystem.ActionPlaces
44
import com.intellij.openapi.actionSystem.AnActionEvent
55
import com.intellij.openapi.actionSystem.CommonDataKeys
6-
import com.intellij.openapi.actionSystem.ToggleAction
76
import com.intellij.openapi.project.Project
87
import org.utbot.cpp.clion.plugin.UTBot
98
import org.utbot.cpp.clion.plugin.settings.settings
109

11-
class ChangeVerboseModeAction : ToggleAction() {
10+
class ChangeVerboseModeAction : UTBotBaseToggleAction() {
1211
override fun isSelected(e: AnActionEvent): Boolean {
1312
updateActionText(e)
1413
return e.getRequiredData(CommonDataKeys.PROJECT).settings.storedSettings.verbose
1514
}
1615

1716
override fun isDumbAware(): Boolean = true
1817

19-
override fun update(e: AnActionEvent) {
20-
super.update(e)
18+
override fun updateIfEnabled(e: AnActionEvent) {
2119
e.presentation.isEnabledAndVisible = (e.project != null)
2220
}
2321

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

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

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import com.intellij.openapi.vfs.LocalFileSystem
65
import com.intellij.psi.PsiManager
76
import org.utbot.cpp.clion.plugin.utils.activeProject
87
import java.nio.file.Path
98

10-
class FocusAction(val path: Path) : AnAction("Show") {
9+
class FocusAction(val path: Path) : UTBotBaseAction("Show") {
1110

1211
override fun actionPerformed(e: AnActionEvent) {
1312
val virtualFile = LocalFileSystem.getInstance().findFileByNioFile(path)
@@ -24,7 +23,7 @@ class FocusAction(val path: Path) : AnAction("Show") {
2423
}
2524
}
2625

27-
override fun update(e: AnActionEvent) {
26+
override fun updateIfEnabled(e: AnActionEvent) {
2827
e.presentation.isEnabledAndVisible = LocalFileSystem.getInstance().findFileByNioFile(path) != null
2928
}
3029
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
package org.utbot.cpp.clion.plugin.actions
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import com.intellij.openapi.components.service
65
import org.utbot.cpp.clion.plugin.UTBot
7-
import org.utbot.cpp.clion.plugin.client.ClientManager
6+
import org.utbot.cpp.clion.plugin.client.ManagedClient
87

9-
class ReconnectAction: AnAction(UTBot.message("actions.reconnect")) {
8+
class ReconnectAction : UTBotBaseAction(UTBot.message("actions.reconnect")) {
109
override fun actionPerformed(e: AnActionEvent) {
11-
e.project!!.service<ClientManager>().restartClient()
10+
e.project!!.service<ManagedClient>().restartClient()
1211
}
1312

14-
override fun update(e: AnActionEvent) {
13+
override fun updateIfEnabled(e: AnActionEvent) {
1514
e.presentation.isEnabledAndVisible = e.project != null
1615
}
1716
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import com.intellij.openapi.components.service
77
import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTargetsController
88
import org.utbot.cpp.clion.plugin.utils.activeProject
99

10-
class RefreshTargetsAction: AnAction() {
10+
class RefreshTargetsAction: UTBotBaseAction() {
1111
override fun actionPerformed(e: AnActionEvent) {
1212
e.activeProject().service<UTBotTargetsController>().requestTargetsFromServer()
1313
}
1414

15-
override fun update(e: AnActionEvent) {
15+
override fun updateIfEnabled(e: AnActionEvent) {
1616
e.presentation.isEnabledAndVisible = e.project != null
1717
e.presentation.icon = AllIcons.Actions.Refresh
1818
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package org.utbot.cpp.clion.plugin.actions
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import org.utbot.cpp.clion.plugin.UTBot
65
import org.utbot.cpp.clion.plugin.ui.wizard.UTBotWizard
76
import org.utbot.cpp.clion.plugin.utils.activeProject
87

9-
class ShowWizardAction: AnAction(UTBot.message("wizard.show")) {
8+
class ShowWizardAction: UTBotBaseAction(UTBot.message("wizard.show")) {
109

1110
override fun actionPerformed(e: AnActionEvent) {
1211
UTBotWizard(e.activeProject()).showAndGet()
1312
}
1413

15-
override fun update(e: AnActionEvent) {
14+
override fun updateIfEnabled(e: AnActionEvent) {
1615
e.presentation.isEnabled = e.project != null
1716
}
1817
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.utbot.cpp.clion.plugin.actions
2+
3+
import com.intellij.openapi.actionSystem.ActionPlaces
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import com.intellij.openapi.actionSystem.ToggleAction
6+
import com.intellij.openapi.project.Project
7+
import org.utbot.cpp.clion.plugin.UTBot
8+
import org.utbot.cpp.clion.plugin.settings.settings
9+
10+
class TogglePluginAction : ToggleAction() {
11+
override fun isSelected(e: AnActionEvent): Boolean {
12+
val project = e.project ?: return false
13+
updateActionText(e, project)
14+
return project.settings.storedSettings.isPluginEnabled
15+
}
16+
17+
override fun setSelected(e: AnActionEvent, pluginEnabled: Boolean) {
18+
val project = e.project ?: return
19+
val previousValue = project.settings.storedSettings.isPluginEnabled
20+
project.settings.storedSettings.isPluginEnabled = pluginEnabled
21+
updateActionText(e, project)
22+
if (previousValue != pluginEnabled)
23+
project.settings.fireUTBotEnabledStateChanged()
24+
}
25+
26+
private fun updateActionText(e: AnActionEvent, project: Project) {
27+
val isPluginEnabled = project.settings.storedSettings.isPluginEnabled
28+
var newText = if (isPluginEnabled) UTBot.message("actions.enable.enabled")
29+
else UTBot.message("actions.enable.disabled")
30+
if (ActionPlaces.isPopupPlace(e.place)) {
31+
newText = if (isPluginEnabled)
32+
UTBot.message("actions.enable.menu.enabled")
33+
else UTBot.message("actions.enable.menu.disabled")
34+
}
35+
e.presentation.text = newText
36+
}
37+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.utbot.cpp.clion.plugin.actions
2+
3+
import com.intellij.openapi.actionSystem.AnAction
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import javax.swing.Icon
6+
import org.utbot.cpp.clion.plugin.utils.isPluginEnabled
7+
8+
abstract class UTBotBaseAction(
9+
text: () -> String? = { null },
10+
description: () -> String? = { null },
11+
icon: Icon? = null
12+
) : AnAction(text, description, icon) {
13+
constructor(text: String) : this({ text })
14+
15+
override fun update(e: AnActionEvent) {
16+
if (isPluginEnabled(e)) {
17+
updateIfEnabled(e)
18+
} else {
19+
e.presentation.isEnabledAndVisible = false
20+
}
21+
}
22+
23+
abstract fun updateIfEnabled(e: AnActionEvent)
24+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.utbot.cpp.clion.plugin.actions
2+
3+
import com.intellij.openapi.actionSystem.AnActionEvent
4+
import com.intellij.openapi.actionSystem.ToggleAction
5+
import javax.swing.Icon
6+
import org.utbot.cpp.clion.plugin.utils.isPluginEnabled
7+
8+
abstract class UTBotBaseToggleAction(
9+
text: () -> String? = { null },
10+
description: () -> String? = { null },
11+
icon: Icon? = null
12+
): ToggleAction(text, description, icon) {
13+
override fun update(e: AnActionEvent) {
14+
super.update(e)
15+
if (isPluginEnabled(e)) {
16+
updateIfEnabled(e)
17+
} else {
18+
e.presentation.isEnabledAndVisible = false
19+
}
20+
}
21+
22+
abstract fun updateIfEnabled(e: AnActionEvent)
23+
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package org.utbot.cpp.clion.plugin.actions.configure
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import org.utbot.cpp.clion.plugin.UTBot
5+
import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction
66
import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest
77
import org.utbot.cpp.clion.plugin.utils.activeProject
88

9-
class ConfigureProjectAction : AnAction(UTBot.message("projectConfigure.configure")) {
9+
class ConfigureProjectAction : UTBotBaseAction(UTBot.message("projectConfigure.configure")) {
1010

11-
override fun actionPerformed(e: AnActionEvent) = CheckProjectConfigurationRequest(e.activeProject()).executeUsingCurrentClient()
11+
override fun actionPerformed(e: AnActionEvent) = CheckProjectConfigurationRequest(e.activeProject()).execute()
1212

13-
override fun update(e: AnActionEvent) {
13+
override fun updateIfEnabled(e: AnActionEvent) {
1414
e.presentation.isEnabledAndVisible = e.project != null
1515
}
1616
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
package org.utbot.cpp.clion.plugin.actions.configure
22

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
54
import org.utbot.cpp.clion.plugin.UTBot
5+
import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction
66
import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest
77
import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest
88
import org.utbot.cpp.clion.plugin.utils.activeProject
99
import testsgen.Testgen
1010

11-
class ReconfigureProjectAction: AnAction(UTBot.message("projectConfigure.reconfigure")) {
11+
class ReconfigureProjectAction: UTBotBaseAction(UTBot.message("projectConfigure.reconfigure")) {
1212

1313
override fun actionPerformed(e: AnActionEvent) {
1414
val project = e.activeProject()
1515
CheckProjectConfigurationRequest(
1616
getProjectConfigGrpcRequest(project, Testgen.ConfigMode.ALL),
1717
project,
18-
).executeUsingCurrentClient()
18+
).execute()
1919
}
2020

21-
override fun update(e: AnActionEvent) {
21+
override fun updateIfEnabled(e: AnActionEvent) {
2222
e.presentation.isEnabledAndVisible = e.project != null
2323
}
24-
}
24+
}

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

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

3-
import com.intellij.openapi.actionSystem.AnAction
43
import com.intellij.openapi.actionSystem.AnActionEvent
5-
import org.utbot.cpp.clion.plugin.utils.currentClient
4+
import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction
5+
import org.utbot.cpp.clion.plugin.utils.client
66

7-
abstract class BaseGenerateTestsAction : AnAction() {
7+
abstract class BaseGenerateTestsAction : UTBotBaseAction() {
88

9-
override fun update(e: AnActionEvent) {
9+
override fun updateIfEnabled(e: AnActionEvent) {
1010
val isDefined: Boolean = isDefined(e)
1111

1212
e.presentation.isVisible = isDefined
13-
e.presentation.isEnabled = isDefined && e.currentClient.isServerAvailable()
13+
e.presentation.isEnabled = isDefined && e.client.isServerAvailable()
1414
}
1515

1616
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class GenerateForAssertionAction : BaseGenerateTestsAction() {
1111
AssertionRequest(
1212
getAssertionGrpcRequest(e),
1313
e.activeProject(),
14-
).executeUsingCurrentClient()
14+
).execute()
1515

1616
override fun isDefined(e: AnActionEvent): Boolean {
1717
val project = e.project

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class GenerateForClassAction : BaseGenerateTestsAction() {
1212
ClassRequest(
1313
getClassGrpcRequest(e),
1414
e.activeProject(),
15-
).executeUsingCurrentClient()
15+
).execute()
1616

1717
override fun isDefined(e: AnActionEvent): Boolean {
1818
val project = e.project

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class GenerateForFileAction : BaseGenerateTestsAction() {
1212
FileRequest(
1313
getFileGrpcRequest(e),
1414
e.activeProject(),
15-
).executeUsingCurrentClient()
15+
).execute()
1616

1717
// action is available only if the selected file ends in .cpp, .hpp, .c or .h
1818
override fun isDefined(e: AnActionEvent): Boolean {

0 commit comments

Comments
 (0)