Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not completely synchronize read-only modules and models #126

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
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.BuiltinLanguages.jetbrains_mps_lang_core
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, ReadonlyModelNode)

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",
)
}

object ReadonlyModelNode : SimpleConcept(
conceptName = "ReadonlyModelNode",
uid = "mps:0a7577d1-d4e5-431d-98b1-fae38f9aee81/6402965165736932005",
directSuperConcepts = listOf(jetbrains_mps_lang_core.BaseConcept),
) {
init {
addConcept(this)
}
}
}
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 @@ -49,16 +54,37 @@ class ITreeTraversal(val branch: IBranch) {
}

private suspend fun visit(node: INode, visitor: IBranchVisitor) {
if (node.isModule()) {
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>()
coroutineScope {
branch.runRead {
dependenciesJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Module.dependencies).map {
launch {
visitor.visitModuleDependency(node, it)
if (it.isReadonlyModuleDependency()) {
launch {
visitor.visitReadonlyModuleDependency(node, it)
}
} else {
launch {
visitor.visitModuleDependency(node, it)
}
}
},
)
Expand All @@ -79,6 +105,22 @@ class ITreeTraversal(val branch: IBranch) {
}
}
modelsJobs.joinAll()
} else if (node.isReadonlyModel()) {
visitor.visitReadonlyModel(node)

val rootNodesJobs = mutableListOf<Job>()
coroutineScope {
branch.runRead {
rootNodesJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Model.rootNodes).map {
launch {
visitor.visitReadonlyModelNode(it)
}
},
)
}
}
rootNodesJobs.joinAll()
} else if (node.isModel()) {
visitor.visitModel(node)

Expand All @@ -87,8 +129,14 @@ class ITreeTraversal(val branch: IBranch) {
branch.runRead {
modelImportJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Model.modelImports).map {
launch {
visitor.visitModelImport(node, it)
if (it.isReadonlyModelImport()) {
launch {
visitor.visitReadonlyModelImport(node, it)
}
} else {
launch {
visitor.visitModelImport(node, it)
}
}
},
)
Expand All @@ -101,19 +149,19 @@ class ITreeTraversal(val branch: IBranch) {
branch.runRead {
usedLanguagesJobs.addAll(
node.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Model.usedLanguages).map {
launch {
if (it.isDevKitDependency()) {
// visit devkit dependency
if (it.isDevKitDependency()) {
launch {
visitor.visitDevKitDependency(node, it)
} else if (it.isSingleLanguageDependency()) {
// visit language dependency
}
} else if (it.isSingleLanguageDependency()) {
launch {
visitor.visitLanguageDependency(node, it)
} else {
val nodeId = node.nodeIdAsLong()
val message =
"Node ($nodeId) is not transformed, because it is neither DevKit nor SingleLanguageDependency."
throw IllegalStateException(message)
}
} else {
val nodeId = node.nodeIdAsLong()
val message =
"Node ($nodeId) is not transformed, because it is neither DevKit nor SingleLanguageDependency."
throw IllegalStateException(message)
}
},
)
Expand Down Expand Up @@ -218,4 +266,45 @@ 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.ReadonlyModelNode] node.
*
* @param node the node to visit
*/
suspend fun visitReadonlyModelNode(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,43 @@ 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.isReadonlyModelNode(): Boolean {
val concept = this.concept ?: return false
val modelConceptRef = ModelixSyncPluginConcepts.ReadonlyModelNode.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
Loading
Loading