Skip to content

Conversation

@abstraktor
Copy link
Collaborator

@abstraktor abstraktor commented Dec 17, 2025

Changes

  • Allow mps bindings to be readonly.
  • If a binding is readonly, they are loaded with the yellow bar just like stub solutions.
  • Readonly modules are never tried to be synced from MPS to the model-server to make the sync more resilient here

Todos

  • with this change, msd and mps files are not created anymore. even without the change to MPSProjectSyncMask

@abstraktor abstraktor force-pushed the feature/update-binding branch from 9d0dc96 to 760e30f Compare December 17, 2025 14:24
@abstraktor abstraktor force-pushed the feature/readonly-bindings branch from 3a4c1d9 to 3cba36e Compare December 17, 2025 14:33
@github-actions
Copy link
Contributor

github-actions bot commented Dec 17, 2025

Test Results

  241 files  + 98    241 suites  +98   48m 20s ⏱️ - 3m 51s
1 380 tests +597  1 369 ✅ +596  11 💤 +2  0 ❌  - 1 
1 390 runs  +597  1 379 ✅ +596  11 💤 +2  0 ❌  - 1 

Results for commit 9922f41. ± Comparison against base commit c2c9512.

This pull request removes 1 and adds 598 tests. Note that renamed tests count towards both.
org.modelix.mps.sync3.MultipleBindingsTest ‑ test no overlap
AddNewChildrenTest ‑ addManyChildren[js, browser]
AddNewChildrenTest ‑ addManyChildren[js, node]
AddNewChildrenTest ‑ addManyDescendants[js, browser]
AddNewChildrenTest ‑ addManyDescendants[js, node]
CapturedInsertPositionTest ‑ insertAfter_3[js, browser]
CapturedInsertPositionTest ‑ insertAfter_3[js, node]
CapturedInsertPositionTest ‑ insertAtSamePosition[js, browser]
CapturedInsertPositionTest ‑ insertAtSamePosition[js, node]
CapturedInsertPositionTest ‑ insertBefore_1[js, browser]
CapturedInsertPositionTest ‑ insertBefore_1[js, node]
…

♻️ This comment has been updated with latest results.

@abstraktor abstraktor force-pushed the feature/readonly-bindings branch from 3cba36e to 7cd12ec Compare December 18, 2025 08:11
@slisson slisson force-pushed the feature/update-binding branch from 760e30f to 14563d4 Compare January 12, 2026 12:18
Base automatically changed from feature/update-binding to main January 12, 2026 12:40
@slisson slisson force-pushed the feature/readonly-bindings branch 2 times, most recently from c0e7dc3 to 280bab0 Compare January 13, 2026 10:41
@github-actions
Copy link
Contributor

github-actions bot commented Jan 13, 2026

JVM coverage report

Overall Project 58.93% -0.23%
Files changed 77.96%

File Coverage
BuiltinLanguages.kt 100% 🍏
MPSProjectSyncMask.kt 97.18% 🍏
SolutionProducer.kt 90.85% -1.68%
MPSModuleAsNode.kt 88.23% -0.8% 🍏
BindingWorker.kt 83.03% -0.96% 🍏
MPSProjectModuleAsNode.kt 82.22% 🍏
MPSProjectAsNode.kt 80.92% -2.54% 🍏
MPSRepositoryAsNode.kt 78.11% 🍏
ModelSyncService.kt 71.66% -0.31% 🍏
SyncServiceState.kt 62.53% -37.47%
SyncTargetModel.kt 60.99% -4.06% 🍏

class SolutionProducer(private val myProject: IMPSProject) {

fun create(name: String, id: ModuleId): Solution {
fun create(name: String, id: ModuleId, readOnly: Boolean = false): Solution {

Check warning

Code scanning / detekt

The function create is missing documentation. Warning

The function create is missing documentation.
}

fun create(namespace: String, id: ModuleId, moduleDir: IFile): Solution {
fun create(namespace: String, id: ModuleId, moduleDir: IFile, readOnly: Boolean): Solution {

Check warning

Code scanning / detekt

The function create is missing documentation. Warning

The function create is missing documentation.
private fun IWritableNode.unwrap() = if (this is NodeWrapper) this.node else this

inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {
open inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {

Check warning

Code scanning / detekt

NodeWrapper is missing required documentation. Warning

NodeWrapper is missing required documentation.
private fun IWritableNode.unwrap() = if (this is NodeWrapper) this.node else this

inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {
open inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {

Check warning

Code scanning / detekt

Class 'NodeWrapper' with '15' functions detected. Defined threshold inside classes is set to '11' Warning

Class 'NodeWrapper' with '15' functions detected. Defined threshold inside classes is set to '11'
private fun IWritableNode.unwrap() = if (this is NodeWrapper) this.node else this

inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {
open inner class NodeWrapper(private val model: IMutableModel, val node: IWritableNode) : IWritableNode by node, ISyncTargetNode {

Check warning

Code scanning / detekt

The property node is missing documentation. Warning

The property node is missing documentation.
@abstraktor
Copy link
Collaborator Author

we tested it on this branch. In 18.1.0-readonly-bindings-SNAPSHOT, we observed the following exceptions:

2026-01-14 11:14:27,759 [ 347688]  DEBUG - org.modelix.model.client2.ModelClientV2 - 29f6.pullIfExists(branch_read_only_tara_main) -> cE1bf*1yoIze6HAHyV1BoB6jLPNRKZr5X57ENxQW_mKM 
2026-01-14 11:14:29,035 [ 348964]  DEBUG - org.modelix.model.client2.ModelClientV2 - 29f5.pullIfExists(branch_read_only_cata_versions/1.0.0) -> GhRrB*TTXpz7xFqOVHds_mx8rG0IhmuMgTsXX3lAIQZw 
2026-01-14 11:14:29,104 [ 349033]  DEBUG - org.modelix.mps.sync3.BindingWorker - Repository exists. Will checkout version [cE1bf*1yoIze6HAHyV1BoB6jLPNRKZr5X57ENxQW_mKM, GhRrB*TTXpz7xFqOVHds_mx8rG0IhmuMgTsXX3lAIQZw] 
2026-01-14 11:14:29,110 [ 349039]  DEBUG - org.modelix.mps.sync3.BindingWorker - Updating MPS project from [null, null] to [NewVersionSpec(version=cE1bf*1yoIze6HAHyV1BoB6jLPNRKZr5X57ENxQW_mKM, readonly=false), NewVersionSpec(version=GhRrB*TTXpz7xFqOVHds_mx8rG0IhmuMgTsXX3lAIQZw, readonly=true)] 
2026-01-14 11:14:29,459 [ 349388]  DEBUG - org.modelix.model.sync.bulk.ModelSynchronizer - Synchronizing nodes... 
2026-01-14 11:14:29,652 [ 349581]   WARN - jetbrains.mps.persistence.DefaultModelRoot - Models have not been found within the Path [IdeaFile[path: C:/Users/dalbrecht/SECUREProjects/readonlyfinalProject/solutions/ISOExample/models]] 
2026-01-14 11:14:29,860 [ 349789]   WARN - jetbrains.mps.ide.vfs.IdeaFile - could not find the virtual find for IdeaFile[path: X:/secure-rcp/build/project-libraries/com.mbeddr.platform/com.mbeddr.mpsutil.httpsupport/languages/group.httpsupport/lib/slf4j-api-1.7.10.jar] 
2026-01-14 11:14:29,860 [ 349789]   WARN - jetbrains.mps.ide.vfs.IdeaFile - could not find the virtual find for IdeaFile[path: X:/secure-rcp/build/project-libraries/com.mbeddr.platform/com.mbeddr.mpsutil.httpsupport/languages/group.httpsupport/lib/slf4j-log4j12-1.7.10.jar] 
2026-01-14 11:14:29,991 [ 349920]   WARN - jetbrains.mps.ide.vfs.IdeaFile - could not find the virtual find for IdeaFile[path: X:/secure-rcp/build/project-libraries/com.mbeddr.platform/com.mbeddr.mpsutil.httpsupport/languages/group.httpsupport/lib/slf4j-api-1.7.10.jar] 
2026-01-14 11:14:29,991 [ 349920]   WARN - jetbrains.mps.ide.vfs.IdeaFile - could not find the virtual find for IdeaFile[path: X:/secure-rcp/build/project-libraries/com.mbeddr.platform/com.mbeddr.mpsutil.httpsupport/languages/group.httpsupport/lib/slf4j-log4j12-1.7.10.jar] 
2026-01-14 11:14:30,066 [ 349995]   WARN - jetbrains.mps.persistence.DefaultModelRoot - Models have not been found within the Path [IdeaFile[path: C:/Users/dalbrecht/SECUREProjects/readonlyfinalProject/solutions/ISO21434/models]] 
2026-01-14 11:14:30,095 [ 350024]   WARN - jetbrains.mps.persistence.DefaultModelRoot - Models have not been found within the Path [IdeaFile[path: C:/Users/dalbrecht/SECUREProjects/readonlyfinalProject/solutions/ISOExample/models]] 
2026-01-14 11:14:30,168 [ 350097]  ERROR - org.modelix.model.sync.bulk.ModelSynchronizer - Ignoring exception during synchronization 
java.lang.UnsupportedOperationException: read only
	at org.modelix.model.mpsadapters.MPSRepositoryAsNode$Companion$childAccessors$3.addNew(MPSRepositoryAsNode.kt:119)
	at org.modelix.model.mpsadapters.MPSRepositoryAsNode$Companion$childAccessors$3.addNew(MPSRepositoryAsNode.kt:113)
	at org.modelix.model.mpsadapters.MPSGenericNodeAdapter.doSyncNewChildren(MPSGenericNodeAdapter.kt:99)
	at org.modelix.model.mpsadapters.MPSGenericNodeAdapter.syncNewChildren(MPSGenericNodeAdapter.kt:88)
	at org.modelix.model.api.IWritableNodeKt.syncNewChild(IWritableNode.kt:101)
	at org.modelix.model.sync.bulk.ModelSynchronizer.syncChildrenInRole(ModelSynchronizer.kt:268)
	at org.modelix.model.sync.bulk.ModelSynchronizer.syncChildren$lambda$2$0(ModelSynchronizer.kt:195)
	at org.modelix.model.sync.bulk.ModelSynchronizer.runSafe-IoAF18A(ModelSynchronizer.kt:61)
	at org.modelix.model.sync.bulk.ModelSynchronizer.syncChildren$lambda$2(ModelSynchronizer.kt:194)
	at org.modelix.model.sync.bulk.ModelSynchronizer.iterateMergedRoles(ModelSynchronizer.kt:433)
	at org.modelix.model.sync.bulk.ModelSynchronizer.iterateMergedRoles(ModelSynchronizer.kt:424)
	at org.modelix.model.sync.bulk.ModelSynchronizer.syncChildren(ModelSynchronizer.kt:190)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronizeNodeAndChildren$lambda$5(ModelSynchronizer.kt:145)
	at org.modelix.model.sync.bulk.ModelSynchronizer.runSafe-IoAF18A(ModelSynchronizer.kt:61)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronizeNodeAndChildren(ModelSynchronizer.kt:144)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronizeNode(ModelSynchronizer.kt:102)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronize(ModelSynchronizer.kt:74)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronize(ModelSynchronizer.kt:68)
	at org.modelix.mps.sync3.BindingWorker.synchronizeAndStoreInstance(BindingWorker.kt:130)
	at org.modelix.mps.sync3.BindingWorker.doSyncToMPS$lambda$6$1(BindingWorker.kt:408)
	at org.modelix.mps.sync3.MPSInvalidatingListener.runSync(MPSInvalidatingListener.kt:64)
	at org.modelix.mps.sync3.BindingWorker.doSyncToMPS$lambda$6(BindingWorker.kt:379)
java.lang.ClassCastException: class org.modelix.mps.sync3.SyncTargetModel$ProjectWrapper cannot be cast to class org.modelix.mps.sync3.SyncTargetModel$NodeWrapper (org.modelix.mps.sync3.SyncTargetModel$ProjectWrapper and org.modelix.mps.sync3.SyncTargetModel$NodeWrapper are in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @738e966b)
	at org.modelix.mps.sync3.SyncTargetModel$RepositoryWrapper.removeChild(SyncTargetModel.kt:138)
	at org.modelix.model.api.INodeKt.remove(INode.kt:438)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronize$lambda$4$0(ModelSynchronizer.kt:88)
	at org.modelix.model.sync.bulk.ModelSynchronizer.runSafe-IoAF18A(ModelSynchronizer.kt:61)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronize(ModelSynchronizer.kt:86)
	at org.modelix.model.sync.bulk.ModelSynchronizer.synchronize(ModelSynchronizer.kt:68)
	at org.modelix.mps.sync3.BindingWorker.synchronizeAndStoreInstance(BindingWorker.kt:130)
	at org.modelix.mps.sync3.BindingWorker.doSyncFromMPS$lambda$2$sync$2$0(BindingWorker.kt:484)

@slisson slisson force-pushed the feature/readonly-bindings branch from 280bab0 to e985e70 Compare January 16, 2026 16:39
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detekt found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@slisson slisson force-pushed the feature/readonly-bindings branch from e985e70 to 9922f41 Compare January 19, 2026 10:58
@slisson slisson marked this pull request as ready for review January 19, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants