Skip to content

Commit

Permalink
Merge pull request #269 from modelix/mps-plugin-range
Browse files Browse the repository at this point in the history
Prepared mps-model-server-plugin for the JetBrains marketplace
  • Loading branch information
slisson authored Oct 3, 2023
2 parents 66eff8e + 29e52ac commit d95cec2
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 87 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/mps-compatibility.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: MPS compatibility

on:
push:
branches:
- 'main'
pull_request: {}
# allow manual execution just in case
workflow_dispatch:

jobs:
build-mps-components:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build with MPS 2020.3.6
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2020.3.6
- name: Build with MPS 2021.1.4
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.1.4
- name: Build with MPS 2021.2.6
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.2.6
- name: Build with MPS 2021.3.3
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2021.3.3
- name: Build with MPS 2022.2
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2022.2
- name: Build with MPS 2022.3
run: ./gradlew :mps-model-adapters:build :mps-model-server-plugin:build -Pmps.version=2022.3
34 changes: 0 additions & 34 deletions .github/workflows/mps-model-adapters.yaml

This file was deleted.

40 changes: 34 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ import kotlinx.html.unsafe
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration
import org.jetbrains.dokka.gradle.DokkaTaskPartial
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin
import org.semver.Version

buildscript {
Expand Down Expand Up @@ -63,6 +66,7 @@ dependencies {
}

subprojects {
val subproject = this
apply(plugin = "maven-publish")
apply(plugin = "org.jetbrains.dokka")
apply(plugin = "org.jlleitschuh.gradle.ktlint")
Expand All @@ -82,18 +86,42 @@ subprojects {
}

val kotlinApiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_6
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all {
subproject.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
if (!name.lowercase().contains("test")) {
kotlinOptions {
this.kotlinOptions {
jvmTarget = "11"
freeCompilerArgs += listOf("-Xjvm-default=all-compatibility")
apiVersion = kotlinApiVersion.version
}
}
}
subproject.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile>().configureEach {
if (!name.lowercase().contains("test")) {
this.kotlinOptions {
jvmTarget = "11"
freeCompilerArgs += listOf("-Xjvm-default=all-compatibility")
apiVersion = kotlinApiVersion.version
}
}
}

subproject.plugins.withType<JavaPlugin> {
subproject.extensions.configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}

subproject.plugins.withType<KotlinPlatformJvmPlugin> {
subproject.extensions.configure<KotlinJvmProjectExtension> {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
}

plugins.withType<KotlinMultiplatformPluginWrapper> {
project.extensions.configure<KotlinMultiplatformExtension> {
subproject.plugins.withType<KotlinMultiplatformPluginWrapper> {
subproject.extensions.configure<KotlinMultiplatformExtension> {
sourceSets.all {
if (!name.lowercase().contains("test")) {
languageSettings {
Expand All @@ -104,8 +132,8 @@ subprojects {
}
}

plugins.withType<NodePlugin> {
project.extensions.configure<NodeExtension> {
subproject.plugins.withType<NodePlugin> {
subproject.extensions.configure<NodeExtension> {
version.set(libs.versions.node)
download.set(true)
}
Expand Down
37 changes: 33 additions & 4 deletions mps-model-server-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
id("org.jetbrains.kotlin.jvm")
id("org.jetbrains.intellij") version "1.15.0"
}

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

dependencies {
implementation(project(":model-server-lib"))
Expand All @@ -19,20 +37,31 @@ dependencies {
intellij {

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

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

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

java {
sourceCompatibility = JavaVersion.toVersion(mpsJavaVersion)
targetCompatibility = JavaVersion.toVersion(mpsJavaVersion)
}

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.fromTarget(mpsJavaVersion.toString()))
}
}

tasks {
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "11"
kotlinOptions.jvmTarget = mpsJavaVersion.toString()
}

patchPluginXml {
sinceBuild.set("211")
sinceBuild.set("203")
untilBuild.set("231.*")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,68 @@
*/
package org.modelix.model.server.mps

import com.intellij.ide.AppLifecycleListener
import com.intellij.ide.plugins.DynamicPluginListener
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity
import jetbrains.mps.ide.project.ProjectHelper
import jetbrains.mps.project.ProjectBase
import jetbrains.mps.project.ProjectManager
import jetbrains.mps.smodel.MPSModuleRepository
import jetbrains.mps.project.MPSProject
import org.modelix.model.api.INode
import org.modelix.model.api.runSynchronized
import org.modelix.model.mpsadapters.MPSRepositoryAsNode
import org.modelix.model.server.light.LightModelServer
import java.util.Collections

@Service(Service.Level.PROJECT)
class MPSModelServerForProject(private val project: Project) : Disposable {

@Service(Service.Level.APP)
class MPSModelServer : Disposable {
init {
println("modelix server created")
service<MPSModelServer>().registerProject(project)
}

override fun dispose() {
service<MPSModelServer>().unregisterProject(project)
}
}

@Service(Service.Level.APP)
class MPSModelServer : Disposable {

private var server: LightModelServer? = null
private val projects: MutableSet<Project> = Collections.synchronizedSet(HashSet())

fun registerProject(project: Project) {
projects.add(project)
ensureStarted()
}

fun unregisterProject(project: Project) {
projects.remove(project)
}

private fun getMPSProjects(): List<MPSProject> {
return runSynchronized(projects) {
projects.mapNotNull { it.getComponent(MPSProject::class.java) }
}
}

private fun getRootNode(): INode? {
return getMPSProjects().asSequence().map {
MPSRepositoryAsNode(it.repository)
}.firstOrNull()
}

fun ensureStarted() {
runSynchronized(this) {
if (server != null) return

println("starting modelix server")

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

override fun run(output: java.lang.StringBuilder): Boolean {
var allSmart = true
val projects = ProjectManager.getInstance().openedProjects
for (project in projects) {
for (project in getMPSProjects()) {
project.repository.modelAccess.runReadAction {
val indexerDone =
!DumbService.getInstance(ProjectHelper.toIdeaProject(project)).isDumb
if (!indexerDone) {
output.append(" indexer running on project ").append(project.name)
output.append(" indexer running on project ").append(project.toString())
allSmart = false
}
}
Expand All @@ -77,10 +103,10 @@ class MPSModelServer : Disposable {
get() = false

override fun run(output: StringBuilder): Boolean {
val projects = ProjectManager.getInstance().openedProjects
val projects = getMPSProjects()
output.append("${projects.size} projects found")
projects.forEach { output.append(" ${it.name}") }
return ProjectManager.getInstance().openedProjects.isNotEmpty()
projects.forEach { output.append(" $it") }
return projects.isNotEmpty()
}
})
.healthCheck(object : LightModelServer.IHealthCheck {
Expand All @@ -90,13 +116,13 @@ class MPSModelServer : Disposable {
get() = false

override fun run(output: StringBuilder): Boolean {
val projects = ProjectManager.getInstance().openedProjects.filterIsInstance<ProjectBase>()
val projects = getMPSProjects()
for (project in projects) {
val modules = project.projectModules
val virtualFolders = modules
.mapNotNull { project.getPath(it)?.virtualFolder }
.filter { it.isNotEmpty() }
output.append("project ${project.name} contains ${modules.size} modules with ${virtualFolders.size} virtual folders")
output.append("project $project contains ${modules.size} modules with ${virtualFolders.size} virtual folders")
if (virtualFolders.isNotEmpty()) return true
}
return false
Expand All @@ -121,18 +147,8 @@ class MPSModelServer : Disposable {
}
}

class MPSModelServerDynamicPluginListener : DynamicPluginListener {
override fun pluginLoaded(pluginDescriptor: IdeaPluginDescriptor) {
service<MPSModelServer>().ensureStarted()
}
}

class MPSModelServerAppLifecycleListener : AppLifecycleListener {
override fun appStarting(projectFromCommandLine: Project?) {
service<MPSModelServer>().ensureStarted()
}

override fun appStarted() {
service<MPSModelServer>().ensureStarted()
class MPSModelServerStartupActivity : StartupActivity.Background {
override fun runActivity(project: Project) {
project.service<MPSModelServerForProject>() // just ensure it's initialized
}
}
14 changes: 3 additions & 11 deletions mps-model-server-plugin/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,12 @@

<!-- Product and plugin compatibility requirements.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
<depends>com.intellij.modules.platform</depends>

<applicationListeners>
<listener
class="org.modelix.model.server.mps.MPSModelServerDynamicPluginListener"
topic="com.intellij.ide.plugins.DynamicPluginListener"/>
<listener
class="org.modelix.model.server.mps.MPSModelServerAppLifecycleListener"
topic="com.intellij.ide.AppLifecycleListener"/>
</applicationListeners>
<depends>com.intellij.modules.mps</depends>
<depends>jetbrains.mps.core</depends>

<!-- Extension points defined by the plugin.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
<extensions defaultExtensionNs="com.intellij">

<backgroundPostStartupActivity implementation="org.modelix.model.server.mps.MPSModelServerStartupActivity" />
</extensions>
</idea-plugin>

0 comments on commit d95cec2

Please sign in to comment.