Index

The MPS internal pages deal with topics related to developing with the MPS sources or close to them, and also how they are connected to the IntelliJ platform. The topics are considered advanced and are not essential for new MPS developers. If you are interested how certain parts of MPS work, they might still be of interest for you.

How do you get started using MPS' Open API?

The simplest way to use MPS Open API (Specific Languages' blog)

How do you get MPS core components from code?

From the console:

1
2
3
MPSProject p = ((MPSProject) #project); 
Platform host = (Platform) p.getPlatform();
#print host.findComponent(MakeServiceComponent.class);

I want to change something inside a SModule, such as adding a dependency, but I need help finding the right method.

Try casting it to AbstractModule ⧉ first.

Where can you find built-in icons?

The class AllIcons ⧉ declares all IntelliJ IDEA icons. The class MPSIcons ⧉ declares all MPS icons.

How can you have settings that get saved globally?

You can use preferences only at the project level. Use the workaround described in this answer ⧉ or save your values in the global IntelliJ IDEA Registry ⧉. This Stack Overflow post ⧉ contains more information about the Registry. It can also be shown programmatically by calling new RegistryUi().show().

How can you call make or rebuild?

Use the class MakeActionImpl ⧉. You can find examples in the same model.

How do you add widgets to the status bar? (for example, memory indicator, save transient models)

Have a look at this answer ⧉. Make sure to call this code from a project plugin ⧉.

How do you display a message in the status bar? (left bottom corner)

Note: The message might not be visible when executing the code from the console because the rebuild of the model overrides it with a new message: WindowManager.getInstance().getStatusBar(ProjectHelper.toIdeaProject(#project))

How can I register an IntelliJ extension?

Find the interface you want to add an extension on this page ⧉. The corresponding interface has a static field EP_NAME. If the interface is implemented in Kotlin, it might have a static field Companion with a getEP_NAME() method. Extend this interface (EX) and register it through the extension point. Example: Interface.EP_NAME.getPoint().registerExtension(new Ex())

How can you add a status bar widget?

Implement the interface StatusBarWidgetFactory and register it through the StatusBarWidgetFactory.EP_NAME extension point.

How do you add model imports and used languages programmatically?

Adding model imports and used languages programmatically ⧉ (Specific Languages' blog)

How can you run some MPS code from the command line/CI?

How can you run generated code from within MPS?

Run generated code from within MPS (Specific Languages' blog)

How can you render a node as a text?

Rendering a node as text ⧉ (Specific Languages' blog)

How can you associate more information with a node?

Associating additional information with a node ⧉ (Specific Languages' blog)

How does shrinking of absolute paths work?

Shrinking of absolute paths ⧉ (Specific Languages' blog)

How can you retrieve nodes of other models and modules?

model.nodesIncludingImported returns all nodes, including those from other currently imported models.

How can you make an internal MPS editor read-only?

I want to contribute to a generator in j.mps.lang.editor. When I download the MPS source ⧉, open the project in MPS under code, and open j.m.l.editor/SubstituteMenuPart_ReferenceScope_declare, I see the model being read-only. What can I do?

Open MPS in IDEA (Community Edition is enough), compile and run it from there, then you can edit MPS sources. There are instructions in README ⧉.

How can you do a full-text search in the IDE?

I sometimes need a textual search which MPS doesn't provide out of the box.

In that situation, I am still determining the concept and type of what I see, so a top-down search is not an option. Instead, I would like to search for that string to have a starting point for my investigation.

Examples:

  • I want to investigate an editor in the user interface and avoid reverse engineering what hints, editors, and concepts lead to what I see.
  • Behavioral view code, like custom cells, Java Swing cells, or query lists, makes it hard to figure out where the source logic of that is located.
  • When the console shows something I don't understand, I'd like to see its context source code to figure out what to do next.

Option 0: Use language debugging facilities of MPS instead.

For built-in languages, MPS brings a load of dedicated debugging facilities:

  • Debugging editor cells and nodes: When you right-click an item in the editor, you can find a submenu Language Debug.
  • Debugging menu entries: Select an item you're curious about and press Cmd+Alt+B/Ctrl+Alt+B to open the Menu Trace of it.
  • Set up IntelliJ idea and connect it to step through Java code.

Option 1: Search for literals from the console.

Option 2: Search through serialized Java.

  1. Set up IntelliJ with your project.
  2. Hit Cmd+Shift+F/Ctrl+Shift+F to search in the path.
  3. When you find a class of interest, open it in MPS via Cmd+N/Ctrl+N. The source node usually has a similar name.

This option is great for finding editor nodes. For example, if that Java class is named Vehicle_EditorBuilder, your source node was an editor for the Vehicle concept.

Last Resort: Search XML model directly.

Use this only if you have no assembly and your project doesn't open. The serialized API is subject to change, and using this should be the last barrier.

Then use ack (or a similar tool) on the command line to find the relevant models that contain this string. The output even contains the node ID, as in this example:

1
2
3
4
5
6
7
$ ack "ack com.mbeddr.mpsutil.grammarcells"
<node concept="3bR9La" id="1aL6sVX49Cb" role="1SiIV1">
    <property role="3bR36h" value="false" />
    <ref role="3bR37D" to="90a9:F1NWDqq_DA" resolve="com.mbeddr.mpsutil.grammarcells.runtime" />
</node>

Use new IdEncoder().parseNodeId("1aL6sVX49Cb") to get the node ID. This line will print the corresponding node to the console. Clicking it will open in MPS:

1
2
3
4
5
6
7
8
9
#nodes.where({~it => 
boolean equals = false; 
try { 
    equals = it/.getNodeId().equals(new IdEncoder().parseNodeId("1aL6sVX49Cb")); 
} catch (Exception e) { 
    <no statements> 
} 
return equals; 
})
How to eliminate the error: Shall specify a repository to lock?

When accessing model properties in rendering code, you must encapsulate the model accessing code in a read action:

read action missing repository

It always has an error "Error: shall specify a repository to lock". How can I get rid of it? What is a 'repository' and is there any documentation that explains the concept and how to use it correctly?

asked by: @cwalesch

The repository is what is represented as the "modules pool" in the UI. It contains all the dependencies currently visible. At the moment there is only one global repository which causes several problems. MPS is slowly but steadily moving to project-specific repositories. That would mean each project (window) of MPS would have its separate repository.

To get the repository you will need access to the project. e.g. the editor context will give you access to the repository: editorContext.getRepository().

In other cases, for instance, when you don't have an editor context directly available you need to make sure that from UI (action) you pass the project or repository through to the place where you need it.

answered by: @coolya

How can you get an identifier of a node?

Given I have a node myNode and I need to serialize something that identifies it. When I serialize that something and then deserialize that identifier again, then I will find exactly that node. How can I build such a thing?

Option 1: PersistenceFacade ID

Since the URL does not look nice, you may use this combined string of model ID and node ID that is used for the URL. For that, import the class org.jetbrains.mps.openapi.persistence.PersistenceFacade from the MPS.OpenApi stub and run:

1
2
3
4
5
6
7
# serialize identifier
string mySerializedId = SNodePointer.serialize(node/.getReference())

# find node based on the serialized identifier
node<> myFoundNode = SNodePointer.deserialize(mySerializedId).resolve(repository)

# then, node == myFoundNode

Option 2: URL

Import the httpsupport language and use node.getURL. This will be a URL that you can use locally to open this node. It includes the node ID and the model and thus is a pretty good globally unique id.

This id is a local URL and looks odd though: http://127.0.0.1:63320/node?ref=r%3A4bc03cd1-b1e3-49da-84da-f27e7062f6f7%28integrityOfUpdate%29%2F2209769512593382448&project=SecurityAnalyst. Especially the code to find the node again based on this URL contains some grepping then.

Option 3: Node Id

Use node/.getNodeId().toString() it will yield the node's id. Note that a node ID is only unique within this model. If it should be globally unique, consider option 1.

contributed by: @abstraktor

Where does MPS store preferences?

For a starting point, read Directories used by the IDE. CONFIG_DIR refers to the configuration directory. WORKSPACE_FILE refers to $PROJECT/.mps/workspace.xml:

  • refactoring settings: CONFIG_DIR/options/refactoringSettings.xml
  • override/implement settings: WORKSPACE_FILE/OverrideImplementMethodComponent
  • additional libraries: CONFIG_DIR/options/AdditionalLibrariesManager.xml
  • default search options: WORKSPACE_FILE/DefaultSearchOptions3
  • make configuration: WORKSPACE_FILE/mpsMakeService
  • code style settings: CONFIG_DIR/options/codeStyleSettings.xml
  • breakpoint settings: WORKSPACE_FILE/BreakpointViewSettings
  • migration state: WORKSPACE_FILE/MigrationProperties
  • model validation settings: CONFIG_DIR/options/mpsModelValidationSettings.xml
  • concept editor settings: WORKSPACE_FILE/ConceptEditorHintSettings
  • node search history: WORKSPACE_FILE/NodeEditorSearchHistory
  • project libraries: WORKSPACE_FOLDER/libraries.xml
  • bookmarks: WORKSPACE_FILE/BookmarksTool
  • project view: WORKSPACE_FILE/ProjectView
  • blame dialog: CONFIG_DIR/options/charismaBlameDialog.xml
  • compiler settings: WORKSPACE_FOLDER/compiler.xml
  • model checker settings: CONFIG_DIR/options/modelCheckerSettings.xml
  • modules: WORKSPACE_FOLDER/modules.xml
  • project plugin settings: WORKSPACE_FILE/ProjectPluginManager
  • generation settings: CONFIG_DIR/options/generationSettings.xml
  • console history: WORKSPACE_FILE/ConsoleHistory
  • breakpoints: WORKSPACE_FILE/BreakpointManager
  • bookmarks: WORKSPACE_FILE/MPSBookmarkManager
  • messages view tool settings: WORKSPACE_FILE/MessagesViewTool
  • usages view tool settings: WORKSPACE_FILE/UsagesViewTool
  • disabled intentions: CONFIG_DIR/options/intentions.xml
  • editor settings: CONFIG_DIR/options/mpsEditor.xml
  • migration trigger settings: WORKSPACE_FILE/MigrationTrigger

Where can you find information about environment/JVM variables that are set in MPS?


Last update: July 16, 2023

Comments