Console is a tool which allows developers to conveniently run DSL code directly in the MPS environment against the active models. It enables you to quickly query the model and change it. You can trigger actions against your models or study statistics about your project.

For example, you can quickly get all (or some) instances of a (deprecated) concept and migrate them to a new concept:

#instances(TryStatement).where({~it => it.catchClause.isNotEmpty; }).refactor({~node => 
  if (node.body.statement.size > 5) { 
    node.replace with new(TryCatchStatement); 
  } 
})

The Console tool window allows line-by-line execution of any DSL construction in the realtime. After the command is written in the console, it is generated by the MPS generator and executed in the IDE's context. This way the code in the console can access and modify the program's AST, display project statistic, execute IDE actions, launch code generation or initiate classes reloading.

For discoverability reasons, most of the console-specific DSL constructs start with symbol '#'. Code-completion (Control + Space) assists developers to insert code in the console.

We shot a short informative screen-cast about using the MPS Console to investigate and update the user models. Check it out!

 

In general, there are 3 kinds of commands:

  1. BaseLanguage statement lists. These commands can contain any BaseLanguage constructions. If some construction or class is not available in completion, it may not have been imported. Missing imports can easily be added as in the normal editor, using actions 'Add model import', 'Add model import by root', 'Add language import', or by the corresponding keyboard shortcuts.

  2. BaseLanguage expressions. Expression is evaluated and, if its type is not void, printed in console as text, AST, or interactive response.
  3. Non-BaseLanguage commands. These are simple non-customizable commands, such as #reloadClasses.

Console commands

There is also a set of languages containing the console commands and BaseLanguage constructions, which allow developers to easily make custom refactorings, complex usages search etc.

  1. BaseLanguage constructions for iterating over IDE objects (#nodes, #references, #models, #modules). These expressions are lazy sequences, including all nodes/references/models/modules in project or in custom scope.

    To inspect read-only modules and models, such as imported libraries and used languages, you need to include the r/o+ parameter to the desired search scope.

  2. BaseLanguage constructions for usages searching (#usages, #instances). These expressions are also sequences, which can be iterated over, but not lazy. When these expressions are evaluated, find usages mechanism is called, so it runs faster then iterating over all nodes or references and then filtering by concept/target.
  3. Commands for quering data from the IDE (#stat, #showBrokenRefs, #showGenPlan)
  4. Commands for interacting with the IDE (#reloadClasses, #make, #clean, #removeGenSources

    Te initiate a rebuild of a model, first invoke #clean followed by #make.

  5. BaseLanguage constructions for showing results to user
  6. refactor operation. This operation applies a function to sequence of nodes (like forEach operation), but before that it opens the found nodes in the usages view, where user can review the nodes before the refactoring is started and manually select the nodes to include/exclude in the refactoring and then apply or cancel the refactoring.

Additionally, the console languages can be extended by the user, if needed.

The model-querying commands used in the Console are defined in the jetbrains.mps.lang.smodel.query language. After importing the language you can use the commands in code to programmatically access and query the models, as well. Details can be found in the smodel queries documentation.

Scopes of Console queries

Queries can have scope specified to constraint the area of the repository to search. The scope is specified in pointy brackets:


Copying nodes into Console

In order to point to a concrete node in project from the console, this node can be copied from the editor and then pasted into the console. The node will be pasted as a special construction, called nodeRef, with is a BaseLanguage expression of type node<>, with value of the pasted node. If there is a necessity to paste the piece of code as is, the 'Paste Original Node' action is available from the context menu.