By default, MPS automatically assigns unique numeric IDs for any new nodes. But when integrating with other systems you sometimes want to create a node based on an existing entity that has an identifier. To maintain correspondence you might want to give the MPS node an ID that is based on the original entity.

A familiar example of this are Java stubs. They are created dynamically when MPS starts, and using new IDs for the same classes and methods on every start would cause any existing references to them to break. The easiest way to ensure that the ID of a given class stays the same between starts is to assign it explicitly, based on the fully-qualified name of the class. And this is exactly what MPS does.

Such manual IDs are called foreign IDs in MPS speak. They are instances of class jetbrains.mps.smodel.SNodeId.Foreign. The class has a public constructor which accepts a string value, the ID itself. To distinguish it from other kinds of identifiers, the string has to start with a prefix, jetbrains.mps.smodel.SNodeId.Foreign#ID_PREFIX, whose value is the tilde character (~).

How to assign node IDs explicitly

You can assign an ID to a node by casting the node down to jetbrains.mps.smodel.SNode and calling setId(SNodeId). The node must not be part of any model, otherwise the call is ignored and an error message is logged.

If you construct a node using a quotation, you can reveal a hidden clause for setting the node ID by typing a square bracket ([) after the quotation. Here is an example where I use the MPS Console to add a root node with an explicit ID to the sandbox of _theSimplestLanguage MPS sample and query the added node for its pointer (node reference), which consists of the model reference and the node ID:

Handling of duplicate IDs

When a node is added to a model, MPS checks whether a node with the same ID already exists in the model. If that is the case, MPS will silently regenerate the node ID, even if the original ID was a foreign one.

Here is what happens if we execute the same commands again, trying to add another node with the same ID:

Notice that the original foreign ID was silently changed to an automatic numeric one.