Skip to content

Commit d95cec2

Browse files
authored
Merge pull request #269 from modelix/mps-plugin-range
Prepared mps-model-server-plugin for the JetBrains marketplace
2 parents 66eff8e + 29e52ac commit d95cec2

File tree

6 files changed

+152
-87
lines changed

6 files changed

+152
-87
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: MPS compatibility
2+
3+
on:
4+
push:
5+
branches:
6+
- 'main'
7+
pull_request: {}
8+
# allow manual execution just in case
9+
workflow_dispatch:
10+
11+
jobs:
12+
build-mps-components:
13+
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v3
18+
- name: Set up JDK 17
19+
uses: actions/setup-java@v3
20+
with:
21+
distribution: 'temurin'
22+
java-version: '17'
23+
- name: Build with MPS 2020.3.6
24+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2020.3.6
25+
- name: Build with MPS 2021.1.4
26+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.1.4
27+
- name: Build with MPS 2021.2.6
28+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.2.6
29+
- name: Build with MPS 2021.3.3
30+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.3.3
31+
- name: Build with MPS 2022.2
32+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2022.2
33+
- name: Build with MPS 2022.3
34+
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2022.3

.github/workflows/mps-model-adapters.yaml

Lines changed: 0 additions & 34 deletions
This file was deleted.

build.gradle.kts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ import kotlinx.html.unsafe
1919
import org.jetbrains.dokka.base.DokkaBase
2020
import org.jetbrains.dokka.base.DokkaBaseConfiguration
2121
import org.jetbrains.dokka.gradle.DokkaTaskPartial
22+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
23+
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
2224
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
2325
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
26+
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin
2427
import org.semver.Version
2528

2629
buildscript {
@@ -63,6 +66,7 @@ dependencies {
6366
}
6467

6568
subprojects {
69+
val subproject = this
6670
apply(plugin = "maven-publish")
6771
apply(plugin = "org.jetbrains.dokka")
6872
apply(plugin = "org.jlleitschuh.gradle.ktlint")
@@ -82,18 +86,42 @@ subprojects {
8286
}
8387

8488
val kotlinApiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_6
85-
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all {
89+
subproject.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
8690
if (!name.lowercase().contains("test")) {
87-
kotlinOptions {
91+
this.kotlinOptions {
8892
jvmTarget = "11"
8993
freeCompilerArgs += listOf("-Xjvm-default=all-compatibility")
9094
apiVersion = kotlinApiVersion.version
9195
}
9296
}
9397
}
98+
subproject.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile>().configureEach {
99+
if (!name.lowercase().contains("test")) {
100+
this.kotlinOptions {
101+
jvmTarget = "11"
102+
freeCompilerArgs += listOf("-Xjvm-default=all-compatibility")
103+
apiVersion = kotlinApiVersion.version
104+
}
105+
}
106+
}
107+
108+
subproject.plugins.withType<JavaPlugin> {
109+
subproject.extensions.configure<JavaPluginExtension> {
110+
sourceCompatibility = JavaVersion.VERSION_11
111+
targetCompatibility = JavaVersion.VERSION_11
112+
}
113+
}
114+
115+
subproject.plugins.withType<KotlinPlatformJvmPlugin> {
116+
subproject.extensions.configure<KotlinJvmProjectExtension> {
117+
compilerOptions {
118+
jvmTarget.set(JvmTarget.JVM_11)
119+
}
120+
}
121+
}
94122

95-
plugins.withType<KotlinMultiplatformPluginWrapper> {
96-
project.extensions.configure<KotlinMultiplatformExtension> {
123+
subproject.plugins.withType<KotlinMultiplatformPluginWrapper> {
124+
subproject.extensions.configure<KotlinMultiplatformExtension> {
97125
sourceSets.all {
98126
if (!name.lowercase().contains("test")) {
99127
languageSettings {
@@ -104,8 +132,8 @@ subprojects {
104132
}
105133
}
106134

107-
plugins.withType<NodePlugin> {
108-
project.extensions.configure<NodeExtension> {
135+
subproject.plugins.withType<NodePlugin> {
136+
subproject.extensions.configure<NodeExtension> {
109137
version.set(libs.versions.node)
110138
download.set(true)
111139
}

mps-model-server-plugin/build.gradle.kts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,27 @@
1+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2+
13
plugins {
24
id("org.jetbrains.kotlin.jvm")
35
id("org.jetbrains.intellij") version "1.15.0"
46
}
57

6-
val mpsVersion = "2021.1.4"
8+
val mpsToIdeaMap = mapOf(
9+
"2020.3.6" to "203.8084.24", // https://github.com/JetBrains/MPS/blob/2020.3.6/build/version.properties
10+
"2021.1.4" to "211.7628.21", // https://github.com/JetBrains/MPS/blob/2021.1.4/build/version.properties
11+
"2021.2.6" to "212.5284.40", // https://github.com/JetBrains/MPS/blob/2021.2.5/build/version.properties (?)
12+
"2021.3.3" to "213.7172.25", // https://github.com/JetBrains/MPS/blob/2021.3.3/build/version.properties
13+
"2022.2" to "222.4554.10", // https://github.com/JetBrains/MPS/blob/2021.2.1/build/version.properties
14+
"2022.3" to "223.8836.41", // https://github.com/JetBrains/MPS/blob/2022.3.0/build/version.properties (?)
15+
)
16+
// use the given MPS version, or 2022.2 (last version with JAVA 11) as default
17+
val mpsVersion = project.findProperty("mps.version")?.toString().takeIf { !it.isNullOrBlank() } ?: "2020.3.6"
18+
if (!mpsToIdeaMap.containsKey(mpsVersion)) {
19+
throw GradleException("Build for the given MPS version '$mpsVersion' is not supported.")
20+
}
21+
// identify the corresponding intelliJ platform version used by the MPS version
22+
val ideaVersion = mpsToIdeaMap.getValue(mpsVersion)
23+
val mpsJavaVersion = if (mpsVersion >= "2022.3") 17 else 11
24+
println("Building for MPS version $mpsVersion and IntelliJ version $ideaVersion and Java $mpsJavaVersion")
725

826
dependencies {
927
implementation(project(":model-server-lib"))
@@ -19,20 +37,31 @@ dependencies {
1937
intellij {
2038

2139
// IDEA platform version used in MPS 2021.1.4: https://github.com/JetBrains/MPS/blob/2021.1.4/build/version.properties#L11
22-
version.set("211.7628.21")
40+
version.set(ideaVersion)
2341

2442
// type.set("IC") // Target IDE Platform
2543

2644
// plugins.set(listOf("jetbrains.mps.core", "com.intellij.modules.mps"))
2745
}
2846

47+
java {
48+
sourceCompatibility = JavaVersion.toVersion(mpsJavaVersion)
49+
targetCompatibility = JavaVersion.toVersion(mpsJavaVersion)
50+
}
51+
52+
kotlin {
53+
compilerOptions {
54+
jvmTarget.set(JvmTarget.fromTarget(mpsJavaVersion.toString()))
55+
}
56+
}
57+
2958
tasks {
3059
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
31-
kotlinOptions.jvmTarget = "11"
60+
kotlinOptions.jvmTarget = mpsJavaVersion.toString()
3261
}
3362

3463
patchPluginXml {
35-
sinceBuild.set("211")
64+
sinceBuild.set("203")
3665
untilBuild.set("231.*")
3766
}
3867

mps-model-server-plugin/src/main/kotlin/org/modelix/model/server/mps/MPSModelServer.kt

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,68 @@
1313
*/
1414
package org.modelix.model.server.mps
1515

16-
import com.intellij.ide.AppLifecycleListener
17-
import com.intellij.ide.plugins.DynamicPluginListener
18-
import com.intellij.ide.plugins.IdeaPluginDescriptor
1916
import com.intellij.openapi.Disposable
2017
import com.intellij.openapi.components.Service
2118
import com.intellij.openapi.components.service
2219
import com.intellij.openapi.project.DumbService
2320
import com.intellij.openapi.project.Project
21+
import com.intellij.openapi.startup.StartupActivity
2422
import jetbrains.mps.ide.project.ProjectHelper
25-
import jetbrains.mps.project.ProjectBase
26-
import jetbrains.mps.project.ProjectManager
27-
import jetbrains.mps.smodel.MPSModuleRepository
23+
import jetbrains.mps.project.MPSProject
2824
import org.modelix.model.api.INode
2925
import org.modelix.model.api.runSynchronized
3026
import org.modelix.model.mpsadapters.MPSRepositoryAsNode
3127
import org.modelix.model.server.light.LightModelServer
28+
import java.util.Collections
29+
30+
@Service(Service.Level.PROJECT)
31+
class MPSModelServerForProject(private val project: Project) : Disposable {
3232

33-
@Service(Service.Level.APP)
34-
class MPSModelServer : Disposable {
3533
init {
36-
println("modelix server created")
34+
service<MPSModelServer>().registerProject(project)
3735
}
3836

37+
override fun dispose() {
38+
service<MPSModelServer>().unregisterProject(project)
39+
}
40+
}
41+
42+
@Service(Service.Level.APP)
43+
class MPSModelServer : Disposable {
44+
3945
private var server: LightModelServer? = null
46+
private val projects: MutableSet<Project> = Collections.synchronizedSet(HashSet())
47+
48+
fun registerProject(project: Project) {
49+
projects.add(project)
50+
ensureStarted()
51+
}
52+
53+
fun unregisterProject(project: Project) {
54+
projects.remove(project)
55+
}
56+
57+
private fun getMPSProjects(): List<MPSProject> {
58+
return runSynchronized(projects) {
59+
projects.mapNotNull { it.getComponent(MPSProject::class.java) }
60+
}
61+
}
62+
63+
private fun getRootNode(): INode? {
64+
return getMPSProjects().asSequence().map {
65+
MPSRepositoryAsNode(it.repository)
66+
}.firstOrNull()
67+
}
4068

4169
fun ensureStarted() {
4270
runSynchronized(this) {
4371
if (server != null) return
4472

4573
println("starting modelix server")
4674

47-
val rootNodeProvider: () -> INode? = { MPSModuleRepository.getInstance()?.let { MPSRepositoryAsNode(it) } }
4875
server = LightModelServer.builder()
4976
.port(48305)
50-
.rootNode(rootNodeProvider)
77+
.rootNode(::getRootNode)
5178
.healthCheck(object : LightModelServer.IHealthCheck {
5279
override val id: String
5380
get() = "indexer"
@@ -56,13 +83,12 @@ class MPSModelServer : Disposable {
5683

5784
override fun run(output: java.lang.StringBuilder): Boolean {
5885
var allSmart = true
59-
val projects = ProjectManager.getInstance().openedProjects
60-
for (project in projects) {
86+
for (project in getMPSProjects()) {
6187
project.repository.modelAccess.runReadAction {
6288
val indexerDone =
6389
!DumbService.getInstance(ProjectHelper.toIdeaProject(project)).isDumb
6490
if (!indexerDone) {
65-
output.append(" indexer running on project ").append(project.name)
91+
output.append(" indexer running on project ").append(project.toString())
6692
allSmart = false
6793
}
6894
}
@@ -77,10 +103,10 @@ class MPSModelServer : Disposable {
77103
get() = false
78104

79105
override fun run(output: StringBuilder): Boolean {
80-
val projects = ProjectManager.getInstance().openedProjects
106+
val projects = getMPSProjects()
81107
output.append("${projects.size} projects found")
82-
projects.forEach { output.append(" ${it.name}") }
83-
return ProjectManager.getInstance().openedProjects.isNotEmpty()
108+
projects.forEach { output.append(" $it") }
109+
return projects.isNotEmpty()
84110
}
85111
})
86112
.healthCheck(object : LightModelServer.IHealthCheck {
@@ -90,13 +116,13 @@ class MPSModelServer : Disposable {
90116
get() = false
91117

92118
override fun run(output: StringBuilder): Boolean {
93-
val projects = ProjectManager.getInstance().openedProjects.filterIsInstance<ProjectBase>()
119+
val projects = getMPSProjects()
94120
for (project in projects) {
95121
val modules = project.projectModules
96122
val virtualFolders = modules
97123
.mapNotNull { project.getPath(it)?.virtualFolder }
98124
.filter { it.isNotEmpty() }
99-
output.append("project ${project.name} contains ${modules.size} modules with ${virtualFolders.size} virtual folders")
125+
output.append("project $project contains ${modules.size} modules with ${virtualFolders.size} virtual folders")
100126
if (virtualFolders.isNotEmpty()) return true
101127
}
102128
return false
@@ -121,18 +147,8 @@ class MPSModelServer : Disposable {
121147
}
122148
}
123149

124-
class MPSModelServerDynamicPluginListener : DynamicPluginListener {
125-
override fun pluginLoaded(pluginDescriptor: IdeaPluginDescriptor) {
126-
service<MPSModelServer>().ensureStarted()
127-
}
128-
}
129-
130-
class MPSModelServerAppLifecycleListener : AppLifecycleListener {
131-
override fun appStarting(projectFromCommandLine: Project?) {
132-
service<MPSModelServer>().ensureStarted()
133-
}
134-
135-
override fun appStarted() {
136-
service<MPSModelServer>().ensureStarted()
150+
class MPSModelServerStartupActivity : StartupActivity.Background {
151+
override fun runActivity(project: Project) {
152+
project.service<MPSModelServerForProject>() // just ensure it's initialized
137153
}
138154
}

mps-model-server-plugin/src/main/resources/META-INF/plugin.xml

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,12 @@
1919

2020
<!-- Product and plugin compatibility requirements.
2121
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
22-
<depends>com.intellij.modules.platform</depends>
23-
24-
<applicationListeners>
25-
<listener
26-
class="org.modelix.model.server.mps.MPSModelServerDynamicPluginListener"
27-
topic="com.intellij.ide.plugins.DynamicPluginListener"/>
28-
<listener
29-
class="org.modelix.model.server.mps.MPSModelServerAppLifecycleListener"
30-
topic="com.intellij.ide.AppLifecycleListener"/>
31-
</applicationListeners>
22+
<depends>com.intellij.modules.mps</depends>
23+
<depends>jetbrains.mps.core</depends>
3224

3325
<!-- Extension points defined by the plugin.
3426
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
3527
<extensions defaultExtensionNs="com.intellij">
36-
28+
<backgroundPostStartupActivity implementation="org.modelix.model.server.mps.MPSModelServerStartupActivity" />
3729
</extensions>
3830
</idea-plugin>

0 commit comments

Comments
 (0)