Skip to content

Commit 26b1400

Browse files
committed
Settings refactoring in CLion plugin
1 parent dffca68 commit 26b1400

29 files changed

+339
-449
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ 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) {
@@ -20,7 +21,6 @@ class UTBotStartupActivity : StartupActivity {
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 & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
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
18+
import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest
2419
import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest
2520
import org.utbot.cpp.clion.plugin.grpc.getVersionGrpcRequest
26-
import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest
2721
import org.utbot.cpp.clion.plugin.listeners.ConnectionStatus
2822
import org.utbot.cpp.clion.plugin.listeners.UTBotEventsListener
23+
import org.utbot.cpp.clion.plugin.settings.projectIndependentSettings
2924
import org.utbot.cpp.clion.plugin.utils.hasChildren
3025
import org.utbot.cpp.clion.plugin.utils.logger
31-
import org.utbot.cpp.clion.plugin.utils.utbotSettings
26+
import testsgen.Testgen
3227

3328
/**
3429
* Sends requests to grpc server via stub
@@ -38,13 +33,12 @@ class Client(
3833
clientId: String,
3934
private val loggingChannels: List<LoggingChannel>
4035
) : Disposable,
41-
GrpcClient(project.utbotSettings.port, project.utbotSettings.serverName, clientId) {
36+
GrpcClient(projectIndependentSettings.port, projectIndependentSettings.serverName, clientId) {
4237
var connectionStatus = ConnectionStatus.INIT
4338
private set
4439

4540
private val messageBus = project.messageBus
4641
private var newClient = true
47-
private val settings = project.utbotSettings
4842
private val logger = project.logger
4943

5044
/*
@@ -67,7 +61,7 @@ class Client(
6761
val servicesCS: CoroutineScope = CoroutineScope(dispatcher + excHandler + SupervisorJob())
6862

6963
init {
70-
logger.info { "Connecting to server on host: ${settings.serverName} , port: ${settings.port}" }
64+
logger.info { "Connecting to server on host: ${projectIndependentSettings.serverName} , port: ${projectIndependentSettings.port}" }
7165
startPeriodicHeartBeat()
7266
}
7367

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: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 fromModel(model: UTBotSettingsModel) {
57+
storedSettings.fromSettingsModel(model)
58+
projectIndependentSettings.fromSettingsModel(model)
59+
}
60+
61+
fun fireUTBotSettingsChanged() {
62+
project.messageBus.syncPublisher(UTBotSettingsChangedListener.TOPIC).settingsChanged(this)
63+
}
64+
65+
fun predictPaths() {
66+
fun getSourceFoldersFromSources(sources: Collection<File>) = sources.map { it.parent }.toMutableSet()
67+
68+
storedSettings.remotePath = projectPath
69+
storedSettings.buildDirRelativePath = "build-utbot"
70+
storedSettings.targetPath = UTBotTarget.autoTarget.path
71+
72+
try {
73+
storedSettings.testDirPath = Paths.get(projectPath, "tests").toString()
74+
} catch (e: IllegalStateException) {
75+
notifyWarning("Guessing settings failed: could not guess project path! Please specify project path in settings!")
76+
}
77+
78+
val cmakeRunConfiguration = CMakeAppRunConfiguration.getSelectedConfigurationAndTarget(project)?.first
79+
val buildConfigurationSources = cmakeRunConfiguration?.cMakeTarget?.buildConfigurations?.map { it.sources }
80+
//TODO: why do we use firstOrNull here?
81+
val cmakeConfiguration = buildConfigurationSources?.firstOrNull() ?: emptySet()
82+
83+
storedSettings.sourceDirs = getSourceFoldersFromSources(cmakeConfiguration)
84+
}
85+
86+
companion object {
87+
const val clientVersion = "2022.7"
88+
const val DEFAULT_HOST = "localhost"
89+
const val DEFAULT_PORT = 2121
90+
}
91+
}
92+
93+
data class UTBotSettingsModel(
94+
var projectSettings: UTBotProjectStoredSettings.State,
95+
var globalSettings: UTBotProjectIndependentSettings.State,
96+
)

0 commit comments

Comments
 (0)