This is a fairly rare use case but it comes up at times: how do you implement UI that behaves like a reference but without using a reference?
For example:
- you might want to refer to something that is not a node, such as a model or a module,
- you want to refer to a node in another model but without introducing a dependency on that model (creating a “weak” reference).
In these cases you cannot use built-in references but you can still create something that comes pretty close, what I would call a pseudoreference.
There are four main “ingredients” to a reference:
- Structure: a concept that keeps information about the target of the pseudoreference. It can be a model or node reference, serialized to a string.
- Completion menu: showing all the available targets for the user to choose.
- Navigation: jumping to the target on
Ctrl+Click
orCtrl/Cmd+B
. - Checking for broken references (i.e. when the target is gone).
With pseudoreferences we can make most of these work, though some things might work differently from the normal references.
There are several implementations of pseudoreferences in MPS and I will use them as examples rather than building a separate sample.
Model references
The first example is a model reference represented by ModelIdentity
interface concept and ModelPointer
concept
implementing it (MPS
link).
ModelPointer
defines a few properties and children to contain the information about the target model. It defines a
named substitute menu (AllRepositoryModels_SM
, MPS
link)
that simply returns all available models. The concept is designed to be reusable so the menu isn’t engaged by default
(in case you want to reuse the ModelPointer
concept in your language but have the user choose from a different set of
models).
Unfortunately, the MPS editor language doesn’t provide any means to set up navigation to a model on Ctrl+Click, so navigating to the target model is not supported.
Broken model references are not highlighted in any way, probably left for the reusing language to implement.
“Reflection” node references
The jetbrains.mps.lang.migration
language implements a “dynamic” node reference concept, named
ReflectionNodeReference
(MPS
link).
This concept contains properties to store the ID of the target node and its model. The editor looks up the node if it
exists and shows its presentation. If the target node exists, the editor enables navigation to it via navigatable-node
style function:
The concept does not mark missing targets as an error (as it is not an error in this case). Rather, it highlights them with a yellow background: