Skip to content

Commit 60ae0c7

Browse files
Refactor settings in CLion plugin (#350)
1 parent dffca68 commit 60ae0c7

29 files changed

+349
-465
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ import com.intellij.openapi.project.Project
66
import com.intellij.openapi.startup.StartupActivity
77
import org.utbot.cpp.clion.plugin.client.Client
88
import org.utbot.cpp.clion.plugin.settings.UTBotPluginSpecificSettings
9+
import org.utbot.cpp.clion.plugin.settings.pluginSettings
10+
import org.utbot.cpp.clion.plugin.settings.settings
911
import org.utbot.cpp.clion.plugin.ui.wizard.UTBotWizard
1012
import org.utbot.cpp.clion.plugin.utils.getClient
1113
import org.utbot.cpp.clion.plugin.utils.invokeOnEdt
12-
import org.utbot.cpp.clion.plugin.utils.utbotSettings
1314

1415
class UTBotStartupActivity : StartupActivity {
1516
override fun runActivity(project: Project) {
16-
// start plugin and connect to server on project opening
17+
1718
project.getClient()
1819
guessPathsOnFirstProjectOpen(project)
1920
showWizardOnFirstProjectOpen(project)
2021
}
2122

2223
private fun showWizardOnFirstProjectOpen(project: Project) {
23-
val pluginSettings = service<UTBotPluginSpecificSettings>()
2424
if (pluginSettings.isFirstLaunch && !Client.IS_TEST_MODE) {
2525
pluginSettings.isFirstLaunch = false
2626
invokeOnEdt {
@@ -31,7 +31,7 @@ class UTBotStartupActivity : StartupActivity {
3131

3232
private fun guessPathsOnFirstProjectOpen(project: Project) {
3333
RunOnceUtil.runOnceForProject(project, "Guess UTBot paths in settings") {
34-
project.utbotSettings.predictPaths()
34+
project.settings.predictPaths()
3535
}
3636
}
3737
}

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

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,28 @@
11
package org.utbot.cpp.clion.plugin.client
22

33
import com.intellij.openapi.Disposable
4-
5-
import testsgen.Testgen
6-
74
import com.intellij.openapi.project.Project
8-
5+
import io.grpc.Status
6+
import kotlinx.coroutines.CoroutineExceptionHandler
7+
import kotlinx.coroutines.CoroutineName
98
import kotlinx.coroutines.CoroutineScope
109
import kotlinx.coroutines.Dispatchers
10+
import kotlinx.coroutines.Job
11+
import kotlinx.coroutines.SupervisorJob
1112
import kotlinx.coroutines.cancel
1213
import kotlinx.coroutines.delay
1314
import kotlinx.coroutines.isActive
1415
import kotlinx.coroutines.launch
15-
16-
import io.grpc.Status
17-
import kotlinx.coroutines.CoroutineExceptionHandler
18-
import kotlinx.coroutines.CoroutineName
19-
import kotlinx.coroutines.SupervisorJob
2016
import kotlinx.coroutines.runBlocking
2117
import kotlinx.coroutines.withTimeout
22-
23-
import kotlinx.coroutines.Job
24-
import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest
25-
import org.utbot.cpp.clion.plugin.grpc.getVersionGrpcRequest
2618
import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest
19+
import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest
2720
import org.utbot.cpp.clion.plugin.listeners.ConnectionStatus
2821
import org.utbot.cpp.clion.plugin.listeners.UTBotEventsListener
22+
import org.utbot.cpp.clion.plugin.settings.projectIndependentSettings
2923
import org.utbot.cpp.clion.plugin.utils.hasChildren
3024
import org.utbot.cpp.clion.plugin.utils.logger
31-
import org.utbot.cpp.clion.plugin.utils.utbotSettings
25+
import testsgen.Testgen
3226

3327
/**
3428
* Sends requests to grpc server via stub
@@ -38,13 +32,12 @@ class Client(
3832
clientId: String,
3933
private val loggingChannels: List<LoggingChannel>
4034
) : Disposable,
41-
GrpcClient(project.utbotSettings.port, project.utbotSettings.serverName, clientId) {
35+
GrpcClient(projectIndependentSettings.port, projectIndependentSettings.serverName, clientId) {
4236
var connectionStatus = ConnectionStatus.INIT
4337
private set
4438

4539
private val messageBus = project.messageBus
4640
private var newClient = true
47-
private val settings = project.utbotSettings
4841
private val logger = project.logger
4942

5043
/*
@@ -67,7 +60,7 @@ class Client(
6760
val servicesCS: CoroutineScope = CoroutineScope(dispatcher + excHandler + SupervisorJob())
6861

6962
init {
70-
logger.info { "Connecting to server on host: ${settings.serverName} , port: ${settings.port}" }
63+
logger.info { "Connecting to server on host: ${projectIndependentSettings.serverName} , port: ${projectIndependentSettings.port}" }
7164
startPeriodicHeartBeat()
7265
}
7366

@@ -92,18 +85,6 @@ class Client(
9285

9386
fun isServerAvailable() = connectionStatus == ConnectionStatus.CONNECTED
9487

95-
fun doHandShake() {
96-
requestsCS.launch {
97-
// Logger.info("sending HandShake request!")
98-
try {
99-
stub.handshake(getVersionGrpcRequest())
100-
logger.info { "Handshake successful!" }
101-
} catch (e: Exception) {
102-
logger.warn { "HandShake failed with the following error: ${e.message}" }
103-
}
104-
}
105-
}
106-
10788
private fun provideLoggingChannels() {
10889
for (channel in loggingChannels) {
10990
servicesCS.launch(CoroutineName(channel.toString())) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import kotlinx.coroutines.flow.Flow
66
import org.utbot.cpp.clion.plugin.UTBot
77
import org.utbot.cpp.clion.plugin.actions.AskServerToGenerateBuildDir
88
import org.utbot.cpp.clion.plugin.actions.AskServerToGenerateJsonForProjectConfiguration
9+
import org.utbot.cpp.clion.plugin.settings.settings
910
import org.utbot.cpp.clion.plugin.utils.getClient
1011
import org.utbot.cpp.clion.plugin.utils.logger
1112
import org.utbot.cpp.clion.plugin.utils.notifyError
1213
import org.utbot.cpp.clion.plugin.utils.notifyInfo
1314
import org.utbot.cpp.clion.plugin.utils.notifyUnknownResponse
1415
import org.utbot.cpp.clion.plugin.utils.notifyWarning
1516
import org.utbot.cpp.clion.plugin.utils.refreshAndFindIOFile
16-
import org.utbot.cpp.clion.plugin.utils.utbotSettings
1717
import testsgen.Testgen
1818

1919
abstract class ProjectConfigResponseHandler(
@@ -87,7 +87,7 @@ class CreateBuildDirHandler(
8787
}
8888
else -> notifyUnknownResponse(response, project)
8989
}
90-
refreshAndFindIOFile(project.utbotSettings.buildDirPath.toString())
90+
refreshAndFindIOFile(project.settings.buildDirPath.toString())
9191
}
9292
}
9393

@@ -106,6 +106,6 @@ class GenerateJsonHandler(
106106
)
107107
else -> notifyUnknownResponse(response, project)
108108
}
109-
refreshAndFindIOFile(project.utbotSettings.buildDirPath.toString())
109+
refreshAndFindIOFile(project.settings.buildDirPath.toString())
110110
}
111111
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ActionsGrpcRequests.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.utbot.cpp.clion.plugin.grpc
33
import com.intellij.openapi.actionSystem.AnActionEvent
44
import com.intellij.openapi.actionSystem.CommonDataKeys
55
import com.intellij.openapi.project.Project
6+
import org.utbot.cpp.clion.plugin.settings.settings
67
import org.utbot.cpp.clion.plugin.utils.activeProject
78
import org.utbot.cpp.clion.plugin.utils.convertToRemotePathIfNeeded
89
import testsgen.Testgen
@@ -88,13 +89,12 @@ private fun getPredicateGrpcRequest(predicate: String, returnValue: String, type
8889
.build()
8990

9091
private fun getProjectGrpcRequest(project: Project): Testgen.ProjectRequest {
91-
val settings = project.allSettings()
9292
return Testgen.ProjectRequest.newBuilder()
9393
.setSettingsContext(getSettingsContextMessage(project))
9494
.setProjectContext(getProjectContextMessage(project))
95-
.setTargetPath(settings.convertedTargetPath)
96-
.addAllSourcePaths(settings.convertedSourcePaths)
97-
.setSynchronizeCode(settings.isRemoteScenario)
95+
.setTargetPath(project.settings.convertedTargetPath)
96+
.addAllSourcePaths(project.settings.convertedSourcePaths)
97+
.setSynchronizeCode(project.settings.isRemoteScenario)
9898
.build()
9999
}
100100

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
package org.utbot.cpp.clion.plugin.grpc
22

3-
import com.intellij.openapi.components.service
3+
import com.intellij.openapi.actionSystem.AnActionEvent
44
import com.intellij.openapi.project.Project
5-
import org.utbot.cpp.clion.plugin.settings.UTBotAllSettings
5+
import org.utbot.cpp.clion.plugin.settings.settings
66
import testsgen.Testgen
77

88
fun getSettingsContextMessage(project: Project): Testgen.SettingsContext {
9-
val settings = project.allSettings()
9+
val storedSettings = project.settings.storedSettings
1010
return Testgen.SettingsContext.newBuilder()
11-
.setVerbose(settings.verbose)
12-
.setUseStubs(settings.useStubs)
13-
.setTimeoutPerTest(settings.timeoutPerTest)
14-
.setTimeoutPerFunction(settings.timeoutPerFunction)
15-
.setGenerateForStaticFunctions(settings.generateForStaticFunctions)
16-
.setUseDeterministicSearcher(settings.useDeterministicSearcher)
11+
.setVerbose(storedSettings.verbose)
12+
.setUseStubs(storedSettings.useStubs)
13+
.setTimeoutPerTest(storedSettings.timeoutPerTest)
14+
.setTimeoutPerFunction(storedSettings.timeoutPerFunction)
15+
.setGenerateForStaticFunctions(storedSettings.generateForStaticFunctions)
16+
.setUseDeterministicSearcher(storedSettings.useDeterministicSearcher)
1717
.build()
1818
}
1919

20-
fun getProjectContextMessage(project: Project): Testgen.ProjectContext {
21-
val settings = project.allSettings()
22-
return Testgen.ProjectContext.newBuilder()
23-
.setProjectName(project.name)
24-
.setProjectPath(settings.convertedProjectPath)
25-
.setBuildDirRelativePath(settings.buildDirRelativePath)
26-
.setResultsDirRelativePath("") // this path is used only by command line interface, server doesn't require it.
27-
.setTestDirPath(settings.convertedTestDirPath)
28-
.build()
29-
}
20+
fun getProjectContextMessage(project: Project): Testgen.ProjectContext = Testgen.ProjectContext.newBuilder()
21+
.setProjectName(project.name)
22+
.setProjectPath(project.settings.convertedProjectPath)
23+
.setBuildDirRelativePath(project.settings.storedSettings.buildDirRelativePath)
24+
.setResultsDirRelativePath("") // this path is used only by command line interface, server doesn't require it.
25+
.setTestDirPath(project.settings.convertedTestDirPath)
26+
.build()
3027

31-
fun Project.allSettings() = this.service<UTBotAllSettings>()
28+
fun AnActionEvent.activeProject() = this.project
29+
?: error("A project related to action event $this not found")
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.utbot.cpp.clion.plugin.listeners
22

33
import com.intellij.util.messages.Topic
4-
import org.utbot.cpp.clion.plugin.settings.UTBotAllSettings
4+
import org.utbot.cpp.clion.plugin.settings.UTBotAllProjectSettings
55

66
fun interface UTBotSettingsChangedListener {
77
companion object {
@@ -11,5 +11,5 @@ fun interface UTBotSettingsChangedListener {
1111
)
1212
}
1313

14-
fun settingsChanged(settings: UTBotAllSettings)
14+
fun settingsChanged(settings: UTBotAllProjectSettings)
1515
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.utbot.cpp.clion.plugin.settings
2+
3+
import com.intellij.openapi.components.service
4+
import com.intellij.openapi.project.Project
5+
6+
val Project.settings: UTBotAllProjectSettings
7+
get() = this.service()
8+
9+
val projectIndependentSettings: UTBotProjectIndependentSettings.State
10+
get() = service<UTBotProjectIndependentSettings>().state
11+
12+
val pluginSettings: UTBotPluginSpecificSettings
13+
get() = service()
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package org.utbot.cpp.clion.plugin.settings
2+
3+
import com.intellij.openapi.components.Service
4+
import com.intellij.openapi.components.service
5+
import com.intellij.openapi.project.Project
6+
import com.intellij.openapi.project.guessProjectDir
7+
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfiguration
8+
import org.utbot.cpp.clion.plugin.listeners.UTBotSettingsChangedListener
9+
import org.utbot.cpp.clion.plugin.ui.targetsToolWindow.UTBotTarget
10+
import org.utbot.cpp.clion.plugin.utils.convertToRemotePathIfNeeded
11+
import org.utbot.cpp.clion.plugin.utils.isWindows
12+
import org.utbot.cpp.clion.plugin.utils.notifyWarning
13+
import java.io.File
14+
import java.nio.file.Path
15+
import java.nio.file.Paths
16+
17+
@Service
18+
class UTBotAllProjectSettings(val project: Project) {
19+
val storedSettings: UTBotProjectStoredSettings.State
20+
get() = project.service<UTBotProjectStoredSettings>().state
21+
22+
var projectPath: String
23+
get() = storedSettings.projectPath ?: project.guessProjectDir()?.path
24+
?: error("Could not guess project path! Should be specified in settings by user")
25+
set(value) {
26+
storedSettings.projectPath = value
27+
}
28+
29+
val buildDirPath: Path
30+
get() = Paths.get(projectPath).resolve(storedSettings.buildDirRelativePath)
31+
32+
val convertedSourcePaths: List<String>
33+
get() = storedSettings.sourceDirs.map { it.convertToRemotePathIfNeeded(project) }
34+
35+
val convertedTestDirPath: String
36+
get() = storedSettings.testDirPath.convertToRemotePathIfNeeded(project)
37+
38+
val convertedTargetPath: String
39+
get() = if (storedSettings.targetPath == UTBotTarget.autoTarget.path) storedSettings.targetPath
40+
else storedSettings.targetPath.convertToRemotePathIfNeeded(project)
41+
42+
val convertedProjectPath: String get() = projectPath.convertToRemotePathIfNeeded(project)
43+
44+
/**
45+
* If this property returns true, plugin must convert path sent and returned from server.
46+
* @see [String.convertToRemotePathIfNeeded], [String.convertFromRemotePathIfNeeded]
47+
*
48+
* If we are on Windows, this is not a server, so it is always a remote scenario.
49+
*/
50+
val isRemoteScenario: Boolean
51+
get() {
52+
val isLocalHost = projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
53+
return !(storedSettings.remotePath == projectPath && isLocalHost) || isWindows
54+
}
55+
56+
fun fireUTBotSettingsChanged() {
57+
project.messageBus.syncPublisher(UTBotSettingsChangedListener.TOPIC).settingsChanged(this)
58+
}
59+
60+
fun predictPaths() {
61+
fun getSourceFoldersFromSources(sources: Collection<File>) = sources.map { it.parent }.toMutableSet()
62+
63+
storedSettings.remotePath = projectPath
64+
storedSettings.buildDirRelativePath = "build-utbot"
65+
storedSettings.targetPath = UTBotTarget.autoTarget.path
66+
67+
try {
68+
storedSettings.testDirPath = Paths.get(projectPath, "tests").toString()
69+
} catch (e: IllegalStateException) {
70+
notifyWarning("Guessing settings failed: could not guess project path! Please specify project path in settings!")
71+
}
72+
73+
val cmakeRunConfiguration = CMakeAppRunConfiguration.getSelectedConfigurationAndTarget(project)?.first
74+
val buildConfigurationSources = cmakeRunConfiguration?.cMakeTarget?.buildConfigurations?.map { it.sources }
75+
//TODO: why do we use firstOrNull here?
76+
val cmakeConfiguration = buildConfigurationSources?.firstOrNull() ?: emptySet()
77+
78+
storedSettings.sourceDirs = getSourceFoldersFromSources(cmakeConfiguration)
79+
}
80+
81+
companion object {
82+
const val clientVersion = "2022.7"
83+
const val DEFAULT_HOST = "localhost"
84+
const val DEFAULT_PORT = 2121
85+
}
86+
}
87+
88+
data class UTBotSettingsModel(
89+
var projectSettings: UTBotProjectStoredSettings.State,
90+
var globalSettings: UTBotProjectIndependentSettings.State,
91+
)

0 commit comments

Comments
 (0)