Skip to content

Commit b7528ca

Browse files
author
Oleksandr Dzhychko
committed
feat(bulk-model-sync): add a configuration option to load plugins
In simple cases, `MPSBulkSynchronizer` does not rely on concepts (and in turn of languages and plugins) of the synced nodes to be loaded. Plugins might become necessary when they provide custom persistence and in other, yet unknown cases.
1 parent 0bd9e7d commit b7528ca

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

bulk-model-sync-gradle/src/main/kotlin/org/modelix/model/sync/bulk/gradle/ModelSyncGradlePlugin.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ import org.gradle.api.Plugin
2020
import org.gradle.api.Project
2121
import org.gradle.api.artifacts.Configuration
2222
import org.gradle.api.tasks.TaskProvider
23+
import org.modelix.buildtools.runner.BundledPluginPath
24+
import org.modelix.buildtools.runner.ExternalPluginPath
2325
import org.modelix.buildtools.runner.MPSRunnerConfig
26+
import org.modelix.buildtools.runner.PluginConfig
2427
import org.modelix.gradle.mpsbuild.MPSBuildPlugin
28+
import org.modelix.model.sync.bulk.gradle.config.BundledPluginSpec
29+
import org.modelix.model.sync.bulk.gradle.config.ExternalPluginSpec
2530
import org.modelix.model.sync.bulk.gradle.config.LocalSource
2631
import org.modelix.model.sync.bulk.gradle.config.LocalTarget
2732
import org.modelix.model.sync.bulk.gradle.config.ModelSyncGradleSettings
33+
import org.modelix.model.sync.bulk.gradle.config.PluginSpec
2834
import org.modelix.model.sync.bulk.gradle.config.ServerSource
2935
import org.modelix.model.sync.bulk.gradle.config.ServerTarget
3036
import org.modelix.model.sync.bulk.gradle.config.SyncDirection
@@ -151,6 +157,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
151157
mpsHome = localSource.mpsHome,
152158
workDir = jsonDir,
153159
additionalModuleDirs = localSource.mpsLibraries.toList() + listOfNotNull(localSource.repositoryDir),
160+
plugins = createPluginConfig(localSource.mpsPlugins),
154161
jvmArgs = listOfNotNull(
155162
"-Dmodelix.mps.model.sync.bulk.output.path=${jsonDir.absolutePath}",
156163
"-Dmodelix.mps.model.sync.bulk.output.modules=${syncDirection.includedModules.joinToString(",")}",
@@ -212,6 +219,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
212219
mpsHome = localTarget.mpsHome,
213220
workDir = jsonDir,
214221
additionalModuleDirs = localTarget.mpsLibraries.toList() + listOfNotNull(localTarget.repositoryDir),
222+
plugins = createPluginConfig(localTarget.mpsPlugins),
215223
jvmArgs = listOfNotNull(
216224
"-Dmodelix.mps.model.sync.bulk.input.path=${jsonDir.absolutePath}",
217225
"-Dmodelix.mps.model.sync.bulk.input.modules=${syncDirection.includedModules.joinToString(",")}",
@@ -238,6 +246,16 @@ class ModelSyncGradlePlugin : Plugin<Project> {
238246
}
239247
}
240248

249+
private fun createPluginConfig(mpsPlugins: Set<PluginSpec>): List<PluginConfig> {
250+
return mpsPlugins.map {
251+
val pluginPath = when (it) {
252+
is BundledPluginSpec -> BundledPluginPath(it.folder)
253+
is ExternalPluginSpec -> ExternalPluginPath(it.folder)
254+
}
255+
PluginConfig(it.id, pluginPath)
256+
}
257+
}
258+
241259
private fun getBaseDir(project: Project): File {
242260
return project.layout.buildDirectory.dir("model-sync").get().asFile
243261
}

bulk-model-sync-gradle/src/main/kotlin/org/modelix/model/sync/bulk/gradle/config/ModelSyncGradleSettings.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ sealed interface LocalEndpoint : SyncEndpoint {
9595
var repositoryDir: File?
9696
var mpsDebugPort: Int?
9797

98+
/**
99+
* Add a plugin to be loaded when running MPS.
100+
* `jetbrains.mps.core`, `jetbrains.mps.testing`, `jetbrains.mps.ide.make` are always loaded.
101+
*
102+
* All other plugins, even bundled ones, must be configured explicitly.
103+
* In general cases, the sync does not rely on concepts (and in turn on languages and plugins) of the synced nodes.
104+
*
105+
* Loading other plugins might become necessary when they provide custom persistence
106+
* and in other, yet unknown cases.
107+
* First, try if the sync works for your project without adding plugins.
108+
*
109+
* Example usage:
110+
* ```
111+
* mpsPlugin(BundledPluginSpec("jetbrains.mps.vcs", File("plugins/mps-vcs")))
112+
* mpsPlugin(ExternalPluginSpec("com.example.mps.aPlugin", File("/full/path/to/aPlugin")))
113+
* ```
114+
*/
115+
fun mpsPlugin(plugin: PluginSpec)
116+
98117
fun mpsLibrary(folder: File)
99118

100119
override fun getValidationErrors(): List<String> {
@@ -112,10 +131,14 @@ data class LocalSource(
112131
override var mpsHeapSize: String = "2g",
113132
override var repositoryDir: File? = null,
114133
override var mpsDebugPort: Int? = null,
134+
internal var mpsPlugins: Set<PluginSpec> = emptySet(),
115135
) : LocalEndpoint {
116136
override fun mpsLibrary(folder: File) {
117137
mpsLibraries += folder
118138
}
139+
override fun mpsPlugin(plugin: PluginSpec) {
140+
mpsPlugins += plugin
141+
}
119142
}
120143

121144
data class LocalTarget(
@@ -124,12 +147,36 @@ data class LocalTarget(
124147
override var mpsHeapSize: String = "2g",
125148
override var repositoryDir: File? = null,
126149
override var mpsDebugPort: Int? = null,
150+
internal var mpsPlugins: Set<PluginSpec> = emptySet(),
127151
) : LocalEndpoint {
128152
override fun mpsLibrary(folder: File) {
129153
mpsLibraries += folder
130154
}
155+
override fun mpsPlugin(plugin: PluginSpec) {
156+
mpsPlugins += plugin
157+
}
158+
}
159+
160+
/**
161+
* Specifies an MPS-plugin to be loaded.
162+
* The [id] is the one that can be found in the `META-INF/plugin.xml` of a plugin.
163+
*/
164+
sealed interface PluginSpec {
165+
val id: String
131166
}
132167

168+
/**
169+
* Specifies a plugin by specifying its installation [folder]
170+
* that will be resolved against the installation of MPS.
171+
*/
172+
data class BundledPluginSpec(override val id: String, val folder: File) : PluginSpec
173+
174+
/**
175+
* Specifies a plugin by specifying its installation [folder]
176+
* that can be absolute or will be resolved depending on the JVM process it is executed in.
177+
*/
178+
data class ExternalPluginSpec(override val id: String, val folder: File) : PluginSpec
179+
133180
private const val DEFAULT_REQUEST_TIMEOUT_SECONDS = 5 * 60
134181

135182
sealed interface ServerEndpoint : SyncEndpoint {

docs/global/modules/core/pages/reference/component-bulk-model-sync-gradle.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ mpsBuild {
112112
|`mpsDebugPort`
113113
|Int
114114
|If set, the headless MPS will suspend on startup and wait for a remote debugger on the specified port.
115+
|`mpsPlugin`
116+
| PluginSpec
117+
| Add a plugin to be loaded when running MPS.
118+
`jetbrains.mps.core`, `jetbrains.mps.testing`, `jetbrains.mps.ide.make` are always loaded.
119+
120+
All other plugins, even bundled ones, must be configured explicitly.
121+
In general cases, the sync does not rely on concepts (and in turn on languages and plugins) of the synced nodes.
122+
123+
Loading other plugins might become necessary when they provide custom persistence and in other, yet unknown cases.
124+
First, try if the sync works for your project without adding plugins.
115125
|===
116126

117127
=== ServerSource/-Target configuration

0 commit comments

Comments
 (0)