Skip to content

Commit 4575aa0

Browse files
committed
Settings refactoring in CLion plugin
1 parent dffca68 commit 4575aa0

29 files changed

+328
-448
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 & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
package org.utbot.cpp.clion.plugin.grpc
22

33
import com.intellij.openapi.components.service
4+
import com.intellij.openapi.actionSystem.AnActionEvent
45
import com.intellij.openapi.project.Project
5-
import org.utbot.cpp.clion.plugin.settings.UTBotAllSettings
6+
import org.utbot.cpp.clion.plugin.settings.settings
67
import testsgen.Testgen
78

89
fun getSettingsContextMessage(project: Project): Testgen.SettingsContext {
9-
val settings = project.allSettings()
10+
val storedSettings = project.settings.storedSettings
1011
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)
12+
.setVerbose(storedSettings.verbose)
13+
.setUseStubs(storedSettings.useStubs)
14+
.setTimeoutPerTest(storedSettings.timeoutPerTest)
15+
.setTimeoutPerFunction(storedSettings.timeoutPerFunction)
16+
.setGenerateForStaticFunctions(storedSettings.generateForStaticFunctions)
17+
.setUseDeterministicSearcher(storedSettings.useDeterministicSearcher)
1718
.build()
1819
}
1920

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-
}
21+
fun getProjectContextMessage(project: Project): Testgen.ProjectContext = Testgen.ProjectContext.newBuilder()
22+
.setProjectName(project.name)
23+
.setProjectPath(project.settings.convertedProjectPath)
24+
.setBuildDirRelativePath(project.settings.storedSettings.buildDirRelativePath)
25+
.setResultsDirRelativePath("") // this path is used only by command line interface, server doesn't require it.
26+
.setTestDirPath(project.settings.convertedTestDirPath)
27+
.build()
3028

31-
fun Project.allSettings() = this.service<UTBotAllSettings>()
29+
fun AnActionEvent.activeProject() = this.project
30+
?: 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: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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+
//TODO: it is unclear, requires a comment
45+
val isRemoteScenario: Boolean
46+
get() {
47+
val isLocalHost = projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
48+
return !(storedSettings.remotePath == projectPath && isLocalHost) || isWindows
49+
}
50+
51+
fun asModel() = UTBotSettingsModel(storedSettings, projectIndependentSettings)
52+
53+
fun fromModel(model: UTBotSettingsModel) {
54+
projectIndependentSettings.port = model.globalSettings.port
55+
projectIndependentSettings.serverName = model.globalSettings.serverName
56+
storedSettings.buildDirRelativePath = model.projectSettings.buildDirRelativePath
57+
storedSettings.testDirPath = model.projectSettings.testDirPath
58+
storedSettings.targetPath = model.projectSettings.targetPath
59+
storedSettings.remotePath = model.projectSettings.remotePath
60+
storedSettings.sourceDirs = model.projectSettings.sourceDirs
61+
storedSettings.cmakeOptions = model.projectSettings.cmakeOptions
62+
storedSettings.generateForStaticFunctions = model.projectSettings.generateForStaticFunctions
63+
storedSettings.useStubs = model.projectSettings.useStubs
64+
storedSettings.useDeterministicSearcher = model.projectSettings.useDeterministicSearcher
65+
storedSettings.verbose = model.projectSettings.verbose
66+
storedSettings.timeoutPerFunction = model.projectSettings.timeoutPerFunction
67+
storedSettings.timeoutPerTest = model.projectSettings.timeoutPerTest
68+
}
69+
70+
71+
fun fireUTBotSettingsChanged() {
72+
project.messageBus.syncPublisher(UTBotSettingsChangedListener.TOPIC).settingsChanged(this)
73+
}
74+
75+
fun predictPaths() {
76+
fun getSourceFoldersFromSources(sources: Collection<File>) = sources.map { it.parent }.toMutableSet()
77+
78+
storedSettings.remotePath = projectPath
79+
storedSettings.buildDirRelativePath = "build-utbot"
80+
storedSettings.targetPath = UTBotTarget.autoTarget.path
81+
82+
try {
83+
storedSettings.testDirPath = Paths.get(projectPath, "tests").toString()
84+
} catch (e: IllegalStateException) {
85+
notifyWarning("Guessing settings failed: could not guess project path! Please specify project path in settings!")
86+
}
87+
88+
val cmakeRunConfiguration = CMakeAppRunConfiguration.getSelectedConfigurationAndTarget(project)?.first
89+
val buildConfigurationSources = cmakeRunConfiguration?.cMakeTarget?.buildConfigurations?.map { it.sources }
90+
//TODO: why do we use firstOrNull here?
91+
val cmakeConfiguration = buildConfigurationSources?.firstOrNull() ?: emptySet()
92+
93+
storedSettings.sourceDirs = getSourceFoldersFromSources(cmakeConfiguration)
94+
}
95+
96+
companion object {
97+
const val clientVersion = "2022.7"
98+
const val DEFAULT_HOST = "localhost"
99+
const val DEFAULT_PORT = 2121
100+
}
101+
}
102+
103+
data class UTBotSettingsModel(
104+
var projectSettings: UTBotProjectStoredSettings.State,
105+
var globalSettings: UTBotProjectIndependentSettings.State,
106+
)

0 commit comments

Comments
 (0)