Skip to content

Commit 6f21f64

Browse files
authored
Merge pull request #299 from modelix/fix/bulk-sync-ref-exception
MODELIX-587 IllegalStateException when syncing references
2 parents 16a0b1f + fab5252 commit 6f21f64

File tree

9 files changed

+62
-9
lines changed

9 files changed

+62
-9
lines changed

bulk-model-sync-gradle-test/src/test/kotlin/org/modelix/model/sync/bulk/gradle/test/PullTest.kt

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,45 @@
1616

1717
package org.modelix.model.sync.bulk.gradle.test
1818

19+
import org.junit.jupiter.api.BeforeAll
1920
import org.junit.jupiter.api.Test
2021
import org.xmlunit.builder.Input
2122
import org.xmlunit.xpath.JAXPXPathEngine
2223
import java.io.File
24+
import javax.xml.transform.Source
2325
import kotlin.test.assertContentEquals
2426

2527
class PullTest {
28+
companion object {
29+
private lateinit var source: Source
30+
31+
@JvmStatic
32+
@BeforeAll
33+
fun initSource() {
34+
val localModel = File("build/test-repo/solutions/GraphSolution/models/GraphSolution.example.mps").readText()
35+
source = Input.fromString(localModel).build()
36+
}
37+
}
2638

2739
@Test
28-
fun `nodes were synced to local`() {
29-
val localModel = File("build/test-repo/solutions/GraphSolution/models/GraphSolution.example.mps").readText()
30-
val source = Input.fromString(localModel).build()
31-
val properties = JAXPXPathEngine().selectNodes("model/node/node[@concept='1DmExO']/property", source)
40+
fun `properties were synced to local`() {
41+
val properties = JAXPXPathEngine()
42+
.selectNodes("model/node/node[@concept='1DmExO']/property", source)
3243

3344
val actual = properties.map { it.attributes.getNamedItem("value").nodeValue }
3445
val expected = listOf("X", "Y", "Z", "D", "E")
3546

3647
assertContentEquals(expected, actual)
3748
}
49+
50+
@Test
51+
fun `references were synced to local`() {
52+
val references = JAXPXPathEngine()
53+
.selectNodes("model/node/node[@id='pSCM1J8Fg1']/ref", source)
54+
55+
val actual = references.map { it.attributes.getNamedItem("node").nodeValue }
56+
val expected = listOf("pSCM1J8FfX", "pSCM1J8FfZ")
57+
58+
assertContentEquals(expected, actual)
59+
}
3860
}

bulk-model-sync-gradle-test/src/test/kotlin/org/modelix/model/sync/bulk/gradle/test/PushTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.modelix.model.sync.bulk.gradle.test
22

33
import GraphLang.L_GraphLang
4+
import GraphLang.N_Edge
45
import GraphLang.N_Node
6+
import GraphLang._C_UntypedImpl_Edge
57
import GraphLang._C_UntypedImpl_Node
68
import jetbrains.mps.lang.core.L_jetbrains_mps_lang_core
79
import kotlinx.coroutines.runBlocking
@@ -67,6 +69,15 @@ class PushTest {
6769
graphNodes[0].name = "X"
6870
graphNodes[1].name = "Y"
6971
graphNodes[2].name = "Z"
72+
73+
val edges = rootNode
74+
.getDescendants(false)
75+
.filter { it.getConceptReference() == ConceptReference(_C_UntypedImpl_Edge.getUID()) }
76+
.map { it.typed<N_Edge>() }
77+
.toList()
78+
79+
edges[0].source = graphNodes[1]
80+
edges[0].target = graphNodes[3]
7081
}
7182
}
7283
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
139139
it.exportFlag.set(true)
140140
it.includedModules.set(syncDirection.includedModules)
141141
it.includedModulePrefixes.set(syncDirection.includedModulePrefixes)
142+
it.debugPort.set(localSource.mpsDebugPort)
142143
}
143144

144145
val exportFromMps = project.tasks.register("${syncDirection.name}ExportFromMps", ExportFromMps::class.java) {
@@ -205,6 +206,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
205206
it.exportFlag.set(false)
206207
it.includedModules.set(syncDirection.includedModules)
207208
it.includedModulePrefixes.set(syncDirection.includedModulePrefixes)
209+
it.debugPort.set(localTarget.mpsDebugPort)
208210
}
209211

210212
val importName = "${syncDirection.name}ImportIntoMps"

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ data class SyncDirection(
4242
internal val includedModules: Set<String> = mutableSetOf(),
4343
internal val registeredLanguages: Set<ILanguage> = mutableSetOf(),
4444
internal val includedModulePrefixes: Set<String> = mutableSetOf(),
45+
internal var mpsDebugEnabled: Boolean = false,
4546
) {
4647
fun fromModelServer(action: Action<ServerSource>) {
4748
val endpoint = ServerSource()
@@ -88,6 +89,7 @@ sealed interface LocalEndpoint : SyncEndpoint {
8889
var mpsHome: File?
8990
var mpsHeapSize: String
9091
var repositoryDir: File?
92+
var mpsDebugPort: Int?
9193

9294
override fun getValidationErrors(): List<String> {
9395
val errors = mutableListOf<String>()
@@ -105,12 +107,14 @@ data class LocalSource(
105107
override var mpsHome: File? = null,
106108
override var mpsHeapSize: String = "2g",
107109
override var repositoryDir: File? = null,
110+
override var mpsDebugPort: Int? = null,
108111
) : LocalEndpoint
109112

110113
data class LocalTarget(
111114
override var mpsHome: File? = null,
112115
override var mpsHeapSize: String = "2g",
113116
override var repositoryDir: File? = null,
117+
override var mpsDebugPort: Int? = null,
114118
) : LocalEndpoint
115119

116120
sealed interface ServerEndpoint : SyncEndpoint {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import org.gradle.api.provider.ListProperty
2323
import org.gradle.api.provider.Property
2424
import org.gradle.api.tasks.CacheableTask
2525
import org.gradle.api.tasks.Input
26+
import org.gradle.api.tasks.Optional
2627
import org.gradle.api.tasks.OutputFile
2728
import org.gradle.api.tasks.TaskAction
2829
import java.io.File
@@ -59,6 +60,10 @@ abstract class GenerateAntScriptForMps @Inject constructor(of: ObjectFactory) :
5960
@Input
6061
val includedModulePrefixes: ListProperty<String> = of.listProperty(String::class.java)
6162

63+
@Optional
64+
@Input
65+
val debugPort: Property<Int> = of.property(Int::class.javaObjectType)
66+
6267
@TaskAction
6368
fun generate() {
6469
val isExport = exportFlag.get()
@@ -108,6 +113,7 @@ abstract class GenerateAntScriptForMps @Inject constructor(of: ObjectFactory) :
108113
<arg value="-Didea.system.path=${"$"}{build.mps.system.path}" />
109114
<arg value="-ea" />
110115
<arg value="-Xmx${mpsHeapSize.get()}" />
116+
${if (debugPort.isPresent) """<arg value="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=${debugPort.get()}" />""" else ""}
111117
</jvmargs>
112118
</runMPS>
113119
</target>

bulk-model-sync-lib/src/commonMain/kotlin/org/modelix/model/sync/bulk/ModelImporter.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import mu.KotlinLogging
2020
import org.modelix.model.api.ConceptReference
2121
import org.modelix.model.api.INode
2222
import org.modelix.model.api.INodeReference
23+
import org.modelix.model.api.INodeResolutionScope
2324
import org.modelix.model.api.SerializedNodeReference
2425
import org.modelix.model.api.getDescendants
2526
import org.modelix.model.api.remove
@@ -84,7 +85,9 @@ class ModelImporter(private val root: INode) {
8485
print("\r($currentNodeProgress / $numExpectedNodes) Synchronizing nodes... ")
8586
syncProperties(node, data)
8687
syncChildren(node, data)
87-
syncReferences(node, data)
88+
INodeResolutionScope.runWithAdditionalScope(node.getArea()) {
89+
syncReferences(node, data)
90+
}
8891
}
8992

9093
private fun syncChildren(node: INode, data: NodeData) {

bulk-model-sync-solution/solutions/org.modelix.mps.model.sync.bulk/org.modelix.mps.model.sync.bulk.msd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
<sourceRoot location="model-api-jvm.jar" />
1818
<sourceRoot location="slf4j-api.jar" />
1919
</modelRoot>
20+
<modelRoot contentPath="${module}/lib/kotlin-utils-jvm.jar!/" type="java_classes">
21+
<sourceRoot location="." />
22+
</modelRoot>
2023
</models>
2124
<facets>
2225
<facet type="java">
@@ -36,6 +39,7 @@
3639
<stubModelEntry path="${module}/lib/slf4j-api.jar" />
3740
<stubModelEntry path="${module}/lib/mps-model-adapters.jar" />
3841
<stubModelEntry path="${module}/lib/bulk-model-sync-lib-jvm.jar" />
42+
<stubModelEntry path="${module}/lib/kotlin-utils-jvm.jar" />
3943
</stubModelEntries>
4044
<sourcePath />
4145
<dependencies>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ This means that only a minimal amount of write operations is used to update the
9494
|`repositoryDir`
9595
|File
9696
|Directory in which the modules are stored.
97+
98+
|`mpsDebugPort`
99+
|Int
100+
|If set, the headless MPS will suspend on startup and wait for a remote debugger on the specified port.
97101
|===
98102

99103
=== ServerSource/-Target configuration

mps-model-adapters/src/main/kotlin/org/modelix/model/mpsadapters/MPSNode.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ data class MPSNode(val node: SNode) : IDeprecatedNodeDefaults {
7070

7171
override fun getChildren(link: IChildLink): Iterable<INode> {
7272
return node.children.map { MPSNode(it) }.filter {
73-
val actualLink = it.getContainmentLink() ?: return@filter false
74-
actualLink.getUID() == link.getUID() ||
75-
actualLink.getSimpleName() == link.getSimpleName() ||
76-
link.getUID().contains(actualLink.getSimpleName())
73+
it.getContainmentLink().conformsTo(link)
7774
}
7875
}
7976

0 commit comments

Comments
 (0)