Skip to content

Commit 5f613c0

Browse files
mhuster23slisson
andcommitted
fix(bulk-model-sync): workaround for renamed files if file per root persistence is used
Co-authored-by: Sascha Lisson <[email protected]>
1 parent 86653d2 commit 5f613c0

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

bulk-model-sync-mps/src/main/kotlin/org/modelix/mps/model/sync/bulk/MPSBulkSynchronizer.kt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,18 @@ package org.modelix.mps.model.sync.bulk
1919
import com.intellij.openapi.application.ApplicationManager
2020
import com.intellij.openapi.project.ProjectManager
2121
import jetbrains.mps.ide.project.ProjectHelper
22+
import jetbrains.mps.smodel.SNodeUtil
23+
import jetbrains.mps.smodel.adapter.ids.MetaIdHelper
24+
import jetbrains.mps.smodel.adapter.ids.SConceptId
25+
import jetbrains.mps.smodel.adapter.structure.concept.SConceptAdapterById
26+
import jetbrains.mps.smodel.language.ConceptRegistry
27+
import jetbrains.mps.smodel.language.StructureRegistry
28+
import jetbrains.mps.smodel.runtime.ConceptDescriptor
29+
import jetbrains.mps.smodel.runtime.illegal.IllegalConceptDescriptor
2230
import kotlinx.serialization.ExperimentalSerializationApi
2331
import kotlinx.serialization.json.Json
2432
import kotlinx.serialization.json.decodeFromStream
33+
import org.jetbrains.mps.openapi.model.EditableSModel
2534
import org.jetbrains.mps.openapi.module.SModule
2635
import org.jetbrains.mps.openapi.module.SRepository
2736
import org.modelix.model.data.ModelData
@@ -125,12 +134,60 @@ object MPSBulkSynchronizer {
125134
ApplicationManager.getApplication().invokeAndWait {
126135
println("Persisting changes...")
127136
repository.modelAccess.runWriteAction {
137+
enableWorkaroundForFilePerRootPersistence(repository)
128138
repository.saveAll()
129139
}
130140
println("Changes persisted.")
131141
}
132142
}
133143

144+
/**
145+
* Workaround for MPS not being able to read the name property of the node during the save process
146+
* in case FilePerRootPersistence is used.
147+
* This is because the concept is not properly loaded and in the MPS code it checks if the concept is a subconcept
148+
* of INamedConcept.
149+
* Without this workaround the id of the root node will be used instead of the name, resulting in renamed files.
150+
*/
151+
@JvmStatic
152+
private fun enableWorkaroundForFilePerRootPersistence(repository: SRepository) {
153+
val structureRegistry: StructureRegistry = ConceptRegistry.getInstance().readField("myStructureRegistry")
154+
val myConceptDescriptorsById: MutableMap<SConceptId, ConceptDescriptor> = structureRegistry.readField("myConceptDescriptorsById")
155+
156+
repository.modules
157+
.asSequence()
158+
.flatMap { it.models }
159+
.mapNotNull { it as? EditableSModel }
160+
.filter { it.isChanged }
161+
.flatMap { it.rootNodes }
162+
.mapNotNull { (it.concept as? SConceptAdapterById) }
163+
.forEach {
164+
myConceptDescriptorsById.putIfAbsent(it.id, DummyNamedConceptDescriptor(it))
165+
}
166+
}
167+
168+
@Suppress("UNCHECKED_CAST")
169+
private fun <R> Any.readField(name: String): R {
170+
return this::class.java.getDeclaredField(name).also { it.isAccessible = true }.get(this) as R
171+
}
172+
173+
private class DummyNamedConceptDescriptor(concept: SConceptAdapterById) : ConceptDescriptor by IllegalConceptDescriptor(concept.id, concept.qualifiedName) {
174+
override fun isAssignableTo(other: SConceptId?): Boolean {
175+
return MetaIdHelper.getConcept(SNodeUtil.concept_INamedConcept) == other
176+
}
177+
178+
override fun getSuperConceptId(): SConceptId {
179+
return MetaIdHelper.getConcept(SNodeUtil.concept_BaseConcept)
180+
}
181+
182+
override fun getAncestorsIds(): MutableSet<SConceptId> {
183+
return mutableSetOf(MetaIdHelper.getConcept(SNodeUtil.concept_INamedConcept))
184+
}
185+
186+
override fun getParentsIds(): MutableList<SConceptId> {
187+
return mutableListOf(MetaIdHelper.getConcept(SNodeUtil.concept_INamedConcept))
188+
}
189+
}
190+
134191
@JvmStatic
135192
private fun parseRawPropertySet(rawProperty: String): Set<String> {
136193
return if (rawProperty.isEmpty()) {

0 commit comments

Comments
 (0)