diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModelBinding.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModelBinding.kt index 12d268b6..3b08f49f 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModelBinding.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModelBinding.kt @@ -110,9 +110,9 @@ class ModelBinding(val model: SModelBase, branch: IBranch, serviceLocator: Servi isDisposed = true - val message = "${name()} is deactivated and model is removed locally${ + val message = "${name()} is deactivated${ if (removeFromServer) { - " and from server" + " and is removed from the server" } else { "" } diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModuleBinding.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModuleBinding.kt index e532cbb0..8637fe0b 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModuleBinding.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/bindings/ModuleBinding.kt @@ -111,9 +111,9 @@ class ModuleBinding(val module: AbstractModule, branch: IBranch, serviceLocator: isDisposed = true - val message = "${name()} is deactivated and module is removed locally${ + val message = "${name()} is deactivated${ if (removeFromServer) { - " and from server" + " and module is removed from the server" } else { "" } diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/tasks/SyncQueue.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/tasks/SyncQueue.kt index e1e67bb7..be81a719 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/tasks/SyncQueue.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/tasks/SyncQueue.kt @@ -29,7 +29,6 @@ import org.modelix.mps.sync.transformation.exceptions.ModelixToMpsSynchronizatio import org.modelix.mps.sync.transformation.exceptions.MpsToModelixSynchronizationException import org.modelix.mps.sync.transformation.exceptions.SynchronizationException import org.modelix.mps.sync.transformation.exceptions.pleaseCheckLogs -import org.modelix.mps.sync.util.completeWithDefault import java.util.concurrent.CompletableFuture import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue @@ -95,7 +94,8 @@ class SyncQueue : InjectableService { if (noTaskIsRunning || isNoneDirection || runningTaskDirectionIsTheSame) { enqueueAndFlush(task) } else { - task.result.completeWithDefault() + // Fail the result in this case, because the follower tasks assume that its predecessor task ran. + task.result.completeExceptionally(IllegalStateException("Predecessor task was not scheduled in the SyncQueue.")) } } diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/incremental/ModelixTreeChangeVisitor.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/incremental/ModelixTreeChangeVisitor.kt index 8f7c82e3..6227c812 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/incremental/ModelixTreeChangeVisitor.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/incremental/ModelixTreeChangeVisitor.kt @@ -221,7 +221,7 @@ class ModelixTreeChangeVisitor( val iNode = getNode(nodeId) if (iNode.isModule()) { - moduleTransformer.transformToModule(nodeId) + moduleTransformer.transformToModuleAndActivate(nodeId) } else if (iNode.isModuleDependency()) { val moduleNodeId = iNode.getModule()?.nodeIdAsLong() val parentModule = nodeMap.getModule(moduleNodeId)!! @@ -233,7 +233,7 @@ class ModelixTreeChangeVisitor( } moduleTransformer.transformModuleDependency(nodeId, parentModule) } else if (iNode.isModel()) { - modelTransformer.transformToModel(nodeId) + modelTransformer.transformToModelAndActivate(nodeId) } else if (iNode.isModelImport()) { modelTransformer.transformModelImport(nodeId) } else if (iNode.isSingleLanguageDependency()) { diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModelTransformer.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModelTransformer.kt index d0289fee..964d2462 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModelTransformer.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModelTransformer.kt @@ -41,7 +41,7 @@ import org.modelix.model.api.getNode import org.modelix.model.mpsadapters.MPSArea import org.modelix.model.mpsadapters.MPSLanguageRepository import org.modelix.model.mpsadapters.MPSModelImportAsNode -import org.modelix.mps.sync.bindings.BindingsRegistry +import org.modelix.mps.sync.IBinding import org.modelix.mps.sync.bindings.EmptyBinding import org.modelix.mps.sync.bindings.ModelBinding import org.modelix.mps.sync.modelix.util.getModel @@ -54,6 +54,7 @@ import org.modelix.mps.sync.mps.util.createModel import org.modelix.mps.sync.mps.util.deleteDevKit import org.modelix.mps.sync.mps.util.deleteLanguage import org.modelix.mps.sync.mps.util.descriptorSuffix +import org.modelix.mps.sync.tasks.ContinuableSyncTask import org.modelix.mps.sync.tasks.SyncDirection import org.modelix.mps.sync.tasks.SyncLock import org.modelix.mps.sync.transformation.cache.ModelWithModelReference @@ -79,6 +80,11 @@ class ModelTransformer( private val notifier = serviceLocator.wrappedNotifier + /** + * The registry to store the [IBinding]s. + */ + private val bindingsRegistry = serviceLocator.bindingsRegistry + private val mpsProject = serviceLocator.mpsProject private val mpsRepository = serviceLocator.mpsRepository @@ -86,7 +92,7 @@ class ModelTransformer( private val resolvableModelImports = mutableListOf() - fun transformToModelCompletely(nodeId: Long, branch: IBranch, bindingsRegistry: BindingsRegistry) = + fun transformToModelCompletely(nodeId: Long) = transformToModel(nodeId) .continueWith(linkedSetOf(SyncLock.MODELIX_READ, SyncLock.MPS_WRITE), SyncDirection.MODELIX_TO_MPS) { val model = branch.getNode(nodeId) @@ -115,7 +121,27 @@ class ModelTransformer( } } - fun transformToModel(nodeId: Long) = + /** + * Transforms a modelix node, identified by its [nodeId], to an [SModel] and then creates and activates its + * [ModelBinding]. + * + * @param nodeId the identifier of the modelix node that represents the [SModel]. + * + * @return the [ContinuableSyncTask] handle to append a new sync task after this one is completed. + * + * @see [transformToModel] + */ + fun transformToModelAndActivate(nodeId: Long) = + transformToModel(nodeId) + .continueWith(linkedSetOf(SyncLock.MODELIX_READ, SyncLock.MPS_WRITE), SyncDirection.MODELIX_TO_MPS) { + val iNode = branch.getNode(nodeId) + val model = nodeMap.getModel(iNode.nodeIdAsLong()) as SModelBase + val binding = ModelBinding(model, branch, serviceLocator) + bindingsRegistry.addModelBinding(binding) + binding.activate() + } + + private fun transformToModel(nodeId: Long) = syncQueue.enqueue(linkedSetOf(SyncLock.MODELIX_READ, SyncLock.MPS_WRITE), SyncDirection.MODELIX_TO_MPS) { val iNode = branch.getNode(nodeId) val name = iNode.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) diff --git a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModuleTransformer.kt b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModuleTransformer.kt index fe25cfcb..f622373d 100644 --- a/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModuleTransformer.kt +++ b/mps-sync-plugin-lib/src/main/kotlin/org/modelix/mps/sync/transformation/modelixToMps/transformers/ModuleTransformer.kt @@ -91,7 +91,7 @@ class ModuleTransformer( val module = branch.getNode(nodeId) val modelBindingsFuture = module.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Module.models) .waitForCompletionOfEachTask(futuresWaitQueue, collectResults = true) { - modelTransformer.transformToModelCompletely(it.nodeIdAsLong(), branch, bindingsRegistry) + modelTransformer.transformToModelCompletely(it.nodeIdAsLong()) } // join the newly added model bindings with the existing bindings @@ -126,6 +126,28 @@ class ModuleTransformer( bindings } + /** + * Transforms a modelix node, identified by its [nodeId], to an [SModule] without transforming the contained models. + * After that it creates and activates the module's [ModuleBinding]. + * + * @param nodeId the identifier of the modelix node that represents the [SModule]. + * @param fetchTargetModule if true, then the target [SModule]s of the Module Dependencies (outgoing from this + * source [SModule]) will be also transformed. + * + * @return the [ContinuableSyncTask] handle to append a new sync task after this one is completed. + * + * @see [transformToModule] + */ + fun transformToModuleAndActivate(nodeId: Long, fetchTargetModule: Boolean = false) = + transformToModule(nodeId, fetchTargetModule) + .continueWith(linkedSetOf(SyncLock.MODELIX_READ, SyncLock.MPS_WRITE), SyncDirection.MODELIX_TO_MPS) { + val iNode = branch.getNode(nodeId) + val module = nodeMap.getModule(iNode.nodeIdAsLong()) as AbstractModule + val moduleBinding = ModuleBinding(module, branch, serviceLocator) + bindingsRegistry.addModuleBinding(moduleBinding) + moduleBinding.activate() + } + fun transformToModule(nodeId: Long, fetchTargetModule: Boolean = false) = syncQueue.enqueue(linkedSetOf(SyncLock.MODELIX_READ, SyncLock.MPS_WRITE), SyncDirection.MODELIX_TO_MPS) { val iNode = branch.getNode(nodeId)