Skip to content

Commit

Permalink
feat(mps-sync-plugin-lib): do not synchronize read-only modules and m…
Browse files Browse the repository at this point in the history
…odels
  • Loading branch information
benedekh committed Jul 1, 2024
1 parent 64ff943 commit 52ce802
Show file tree
Hide file tree
Showing 17 changed files with 605 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.modelix.mps.sync.modelix

import org.modelix.model.api.BuiltinLanguages
import org.modelix.model.api.BuiltinLanguages.MPSRepositoryConcepts.Module
import org.modelix.model.api.SimpleChildLink
import org.modelix.model.api.SimpleConcept
import org.modelix.model.api.SimpleLanguage
import org.modelix.model.api.SimpleReferenceLink

object ModelixSyncPluginConcepts :
SimpleLanguage("org.modelix.model.syncpluginconcepts", uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81") {

override var includedConcepts =
arrayOf(ReadonlyModel, ReadonlyModule, ReadonlyModuleDependency, ReadonlyModelReference)

object ReadonlyModel : SimpleConcept(
conceptName = "ReadonlyModel",
uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81/474657388638618893",
directSuperConcepts = listOf(BuiltinLanguages.MPSRepositoryConcepts.Model),
) {
init {
addConcept(this)
}
}

object ReadonlyModule : SimpleConcept(
conceptName = "ReadonlyModule",
uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81/474657388638618896",
directSuperConcepts = listOf(Module),
) {
init {
addConcept(this)
}

val readonlyModels = SimpleChildLink(
simpleName = "readonlyModels",
isMultiple = true,
isOptional = true,
isOrdered = false,
targetConcept = ReadonlyModel,
uid = "0a7577d1-d4e5-431d-98b1-fae38f9aee81/474657388638618896/474657388638618899",
).also(this::addChildLink)
}

object ReadonlyModuleDependency : SimpleConcept(
conceptName = "ReadonlyModuleDependency",
uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81/2206727074858242416",
directSuperConcepts = listOf(BuiltinLanguages.MPSRepositoryConcepts.ModuleDependency),
) {

init {
addConcept(this)
}
}

object ReadonlyModelReference : SimpleConcept(
conceptName = "ReadonlyModelReference",
uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81/6402965165736932004",
directSuperConcepts = listOf(BuiltinLanguages.MPSRepositoryConcepts.ModelReference),
) {
init {
addConcept(this)
}

val readonlyModel = SimpleReferenceLink(
simpleName = "readonlyModel",
isOptional = false,
targetConcept = ReadonlyModel,
uid = "0a7577d1-d4e5-431d-98b1-fae38f9aee81/6402965165736932004/6402965165736932005",
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import org.modelix.model.api.BuiltinLanguages
import org.modelix.model.api.IBranch
import org.modelix.model.api.INode
import org.modelix.model.api.getRootNode
import org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts
import org.modelix.mps.sync.modelix.util.isDevKitDependency
import org.modelix.mps.sync.modelix.util.isModel
import org.modelix.mps.sync.modelix.util.isModule
import org.modelix.mps.sync.modelix.util.isReadonlyModel
import org.modelix.mps.sync.modelix.util.isReadonlyModelImport
import org.modelix.mps.sync.modelix.util.isReadonlyModule
import org.modelix.mps.sync.modelix.util.isReadonlyModuleDependency
import org.modelix.mps.sync.modelix.util.isSingleLanguageDependency
import org.modelix.mps.sync.modelix.util.nodeIdAsLong

Expand Down Expand Up @@ -48,8 +53,23 @@ class ITreeTraversal(val branch: IBranch) {
childrenJobs.joinAll()
}

private suspend fun visit(node: INode, visitor: IBranchVisitor) {
if (node.isModule()) {
private suspend fun visit(node: INode, visitor: IBranchVisitor): Unit =
if (node.isReadonlyModule()) {
visitor.visitReadonlyModule(node)
val modelsJobs = mutableListOf<Job>()
coroutineScope {
branch.runRead {
modelsJobs.addAll(
node.getChildren(ModelixSyncPluginConcepts.ReadonlyModule.readonlyModels).map {
launch {
visit(it, visitor)
}
},
)
}
}
modelsJobs.joinAll()
} else if (node.isModule()) {
visitor.visitModule(node)

val dependenciesJobs = mutableListOf<Job>()
Expand All @@ -58,7 +78,11 @@ class ITreeTraversal(val branch: IBranch) {
dependenciesJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Module.dependencies).map {
launch {
visitor.visitModuleDependency(node, it)
if (it.isReadonlyModuleDependency()) {
visitor.visitReadonlyModuleDependency(node, it)
} else {
visitor.visitModuleDependency(node, it)
}
}
},
)
Expand All @@ -79,6 +103,8 @@ class ITreeTraversal(val branch: IBranch) {
}
}
modelsJobs.joinAll()
} else if (node.isReadonlyModel()) {
visitor.visitReadonlyModel(node)
} else if (node.isModel()) {
visitor.visitModel(node)

Expand All @@ -88,7 +114,11 @@ class ITreeTraversal(val branch: IBranch) {
modelImportJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Model.modelImports).map {
launch {
visitor.visitModelImport(node, it)
if (it.isReadonlyModelImport()) {
visitor.visitReadonlyModelImport(node, it)
} else {
visitor.visitModelImport(node, it)
}
}
},
)
Expand Down Expand Up @@ -151,7 +181,6 @@ class ITreeTraversal(val branch: IBranch) {
}
childrenJobs.joinAll()
}
}
}

/**
Expand Down Expand Up @@ -218,4 +247,38 @@ interface IBranchVisitor {
* @param modelImport the node to visit
*/
suspend fun visitModelImport(sourceModel: INode, modelImport: INode)

/**
* Visits a [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModule] node.
*
* @param node the node to visit
*/
suspend fun visitReadonlyModule(node: INode)

/**
* Visits a [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModel] node.
*
* @param node the node to visit
*/
suspend fun visitReadonlyModel(node: INode)

/**
* Visits a [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModuleDependency] node.
*
* @param sourceModule the source [org.modelix.model.api.BuiltinLanguages.MPSRepositoryConcepts.Module] node from
* which the [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModuleDependency] originates
*
* @param readonlyModuleDependency the node to visit
*/
suspend fun visitReadonlyModuleDependency(sourceModule: INode, readonlyModuleDependency: INode)

/**
* Visits a [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModelReference] node.
*
* @param sourceModel the source [org.modelix.model.api.BuiltinLanguages.MPSRepositoryConcepts.Model] node from
* which the [org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts.ReadonlyModelReference] originates
*
* @param readonlyModelImport the node to visit
*/
suspend fun visitReadonlyModelImport(sourceModel: INode, readonlyModelImport: INode)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.modelix.model.api.INode
import org.modelix.model.api.PNodeAdapter
import org.modelix.model.api.isSubConceptOf
import org.modelix.model.mpsadapters.MPSNode
import org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.nodeIdAsLong(): Long =
Expand Down Expand Up @@ -83,6 +84,36 @@ fun INode.isModuleDependency(): Boolean {
return concept.isSubConceptOf(moduleDepConceptRef)
}

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.isReadonlyModule(): Boolean {
val concept = this.concept ?: return false
val moduleConceptRef = ModelixSyncPluginConcepts.ReadonlyModule.getReference()
return concept.isSubConceptOf(moduleConceptRef)
}

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.isReadonlyModel(): Boolean {
val concept = this.concept ?: return false
val modelConceptRef = ModelixSyncPluginConcepts.ReadonlyModel.getReference()
return concept.isSubConceptOf(modelConceptRef)
}

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.isReadonlyModuleDependency(): Boolean {
val concept = this.concept ?: return false
val moduleDepConceptRef = ModelixSyncPluginConcepts.ReadonlyModuleDependency.getReference()
return concept.isSubConceptOf(moduleDepConceptRef)
}

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.isReadonlyModelImport(): Boolean {
val concept = this.concept ?: return false
val modelReferenceConceptRef = ModelixSyncPluginConcepts.ReadonlyModelReference.getReference()
val isModelReference = concept.isSubConceptOf(modelReferenceConceptRef)
val isModelImportRole = BuiltinLanguages.MPSRepositoryConcepts.Model.modelImports == this.getContainmentLink()
return isModelReference && isModelImportRole
}

@UnstableModelixFeature(reason = "The new modelix MPS plugin is under construction", intendedFinalization = "This feature is finalized when the new sync plugin is ready for release.")
fun INode.getModel(): INode? = findNode { it.isModel() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import jetbrains.mps.smodel.MPSModuleRepository
import org.modelix.kotlin.utils.UnstableModelixFeature
import org.modelix.model.api.ILanguageRepository
import org.modelix.model.mpsadapters.MPSLanguageRepository
import org.modelix.mps.sync.modelix.ModelixSyncPluginConcepts

@UnstableModelixFeature(
reason = "The new modelix MPS plugin is under construction",
Expand All @@ -17,8 +18,8 @@ class MPSLanguageRepositoryProvider {
val mpsLanguageRepository: MPSLanguageRepository

init {
// just a dummy call, to initialize the modelix built-in languages
ILanguageRepository.default.javaClass
// initialize the modelix built-in languages
ILanguageRepository.default.registerLanguage(ModelixSyncPluginConcepts)

// MPS-internal convention that they use to get the SRepository
val repository = MPSCoreComponents.getInstance().platform.findComponent(MPSModuleRepository::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.modelix.mps.sync.transformation.cache.MpsToModelixMap
class ServiceLocator(val project: Project) : Disposable {

val syncService = SyncServiceImpl()

val syncQueue = SyncQueue()
val bindingsRegistry = BindingsRegistry()
val branchRegistry = BranchRegistry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ class MpsToModelixMapInitializerVisitor(
cache.put(model, targetModelImport, nodeId)
}

override suspend fun visitReadonlyModule(node: INode) = visitModule(node)

override suspend fun visitReadonlyModel(node: INode) = visitModel(node)

override suspend fun visitReadonlyModuleDependency(sourceModule: INode, readonlyModuleDependency: INode) =
visitModuleDependency(sourceModule, readonlyModuleDependency)

override suspend fun visitReadonlyModelImport(sourceModel: INode, readonlyModelImport: INode) =
visitModelImport(sourceModel, readonlyModelImport)

private fun getMpsModel(modelNode: INode): SModel {
val modelixModelId = modelNode.getPropertyValue(BuiltinLanguages.MPSRepositoryConcepts.Model.id)
requireNotNull(modelixModelId) {
Expand Down
Loading

0 comments on commit 52ce802

Please sign in to comment.