What’s New in MPS 2024.1

MPS 2024.1 brings a new asynchronous implementation of the Logical View pane in the Project tool window, substantial improvements to the Kotlin support for various platforms, and noticeably faster test run times. You will also find conditional forks in generator plans, the deprecation of project paths in TestInfo, improvements to the new UI, and numerous platform updates.

Check out the detailed list of enhancements below.

Enhanced platform support for Kotlin

The Kotlin support in MPS was initially designed to support only common code. However, the only possible use case in MPS was compilation to the JVM, and the distinction between common code and JVM code was unclear.

In this release, we’re introducing platform source set configuration for Kotlin nodes. This allows you to identify which target platforms a piece of code supports and hide declarations from incompatible code.

Source sets

In a regular Kotlin project, you can use source sets to separate code targeting different platforms. In MPS, we introduced this at the root level, with the option to specify the set of supported platforms for each Kotlin root node. These source sets can be configured at the root node level with the help of an intention action.

In practice, this means that:

  • Code under a given source set can only access declarations with compatible platforms. For example, code specific to the JVM may access only JVM-specific code and common code that targets the JVM.
  • Generated sources are structured under source-set-specific directories. If a directory is unspecified, it uses the default source set, which corresponds to the module’s default.
  • Expected and actual declarations are now supported.

By default, Kotlin code without an explicit platform uses the JVM, maintaining backward compatibility.

Loading and compilation for stubs

Stubs have been improved to support new multiplatform use cases. In the past, MPS offered separate options for Kotlin and Kotlin/JVM stubs, which loaded common and JVM stubs, respectively.

These two options have now been unified under the one for Kotlin stubs, which now automatically determines whether a provided artifact exposes common code, JVM code, or code for other platforms.

As declarations between common and platform-specific libraries are redundant (as both artifacts contain all necessary declarations), we’ve introduced a new mechanism for filtering duplication to keep stubs tidy. When platform-specific libraries are declared under the same module, they can access common declarations, so you don’t have to declare them again.

Dependency configuration is the same as before:

  • Both common and platform-specific libraries can be used as stubs.
  • JVM libraries are required to compile common code to the JVM, and they should be declared in the Java facet.

For instance, writing common code requires you to use a common library for stubs, using the common source set, but you also have to declare the Java artifact in the Java facet.

Improved Kotlin readability without the CodeRules typesystem

Kotlin code in MPS used to raise a lot of typesystem and scope errors when the Kotlin Typesystem plugin, based on CodeRules, was not available. In order to improve readability and testability, these checks and errors are now muted when the CodeRules-based typesystem plugin is not available.

In such cases, all scopes in Kotlin languages are replaced with a default scope including all nodes of compatible concepts. This removes any false-positive errors, as all valid nodes are in the scope.

The guidelines for dealing with Kotlin code remain the same as before:

  • Writing and checking Kotlin code should be done with CodeRules enabled and the Kotlin Typesystem plugin installed.
  • Reading Kotlin and generating it can be safely performed without them.

Reimplementation of the Logical View pane

The Logical View pane is now based on an asynchronous architecture, which helps keep the UI responsive and contributes to the overall performance of the IDE. The new implementation also allows for easier extensions and modifications. For more details, refer to our article in the knowledge base entitled ProjectPane implementation on top of ProjectViewTree.

This new implementation has resulted in a few notable changes:

  • Error and warning indicators are no longer available.
  • Both errors and warnings found in the hierarchy are underlined in red.
  • The Show Descriptor Models option affects all descriptor models.
  • Some drag-and-drop operations work differently.
  • The settings in the Logical View pane have been reorganized slightly.

Placeholder cells

We’ve introduced a new style into BaseLanguage that allows constant cells to serve as placeholders if there’s a missing value (a child node or a reference). For example, when no constructor is present in a class, a <no default constructor> placeholder cell can be displayed instead. The style causes constant cells to exhibit the behavior you would expect from such placeholder cells. The cursor can only be placed on the first position, and it is not possible to edit the value. Only modifications provided by attached transformation menus are permitted.

Changes to the build language

The Boolean doNotCompile option of modules in the build language has been replaced with a Java enum to better distinguish the cases when:

  • The module contains no code at all.
  • The module contains code, but the code is compiled by tools other than MPS.

Both of these cases used to be represented by the value true.

The new Java enum has three possible values:

  • compile in MPS
  • compile externally
  • no code

When migrating to 2024.1, the original false value of doNotCompile will be migrated to compile in MPS, while the true value of doNotCompile will be migrated to compile externally.

Conditional forks in generation plans

A small experimental new feature enables you to add a fork for a generation plan without actually modifying the original plan that is being forked. A generation plan can be marked as a fork of another generation plan. The marked plan will be treated as if it were referred to explicitly with the standard fork statement inserted at the very beginning of the forked generation plan.

Additionally, when defining a fork, you can use a string modifier that will serve as a trigger. The fork will only happen if the model being generated is owned by a module that has a generation target facet with a facet ID matching the string trigger.

JUnit5 XML reports in MPS

JUnit tests in MPS can now generate test reports not only in the Vintage and Jupiter formats, but also in the Open Test Reporting format. A new option is available in the build language’s test options to control whether the Open Test report is included in the generated reports. If the option is set to true, report files named junit-platform-events*-$BUILD_NAME$.xml are created in the project directory.

If the option is set to false, the legacy reports for Vintage and Jupiter engines are created.

JUnit5 annotation @DisplayName propagated to test reports

MPS test reports now respect the JUnit @DisplayName annotation and propagate the name to reports shown in the test report tool window.

Test runtime improvements

When running a node or editor test, MPS used to copy the whole test model into transient models and make additional copies of every test case node (starting from the root NodeTestCase or EditorTestCase). For large test models, this tended to have a noticeable impact on performance. It also resulted in a rather odd setup with duplicated test nodes. In MPS 2024.1, models with tests will no longer be copied; only the TestNode children of NodeTestCase or EditorTestCase will be, along with their respective environment nodes (the targets of their references).

The project path in TestInfo is no longer needed

TestInfo declarations are no longer required for tests that need an MPS project to be open. This applies to all approaches to executing the JUnit tests:

  • If the test is run from the IDE, either in-process or out-of-process, the project currently open will be used.
  • If the test is run with the <launchtests> task, the project path can be specified as an additional project path option of the task. If left unspecified, ${basedir} is used, which corresponds to the home directory of the current project.
  • For special cases where neither of the above approaches can be used, you can specify the project location via the -Dmps.test.project.path system property.

Existing TestInfo declarations are still supported and can be kept.

Complete overhaul of module class loading

In our endeavor to separate class loading from model access and the deprecation of ReloadableSModule, we’ve changed how class loading works for modules. Although we worked hard to avoid making any noticeable changes for end users, the updates may lead to class loading issues that previously did not exist.

As part of this overhaul, MPS now sticks to dependencies declared in module.xml for deployed modules without trying to calculate them on startup based on information scattered in module files. During the design phase, dependencies are derived from information collected during the model transformation phase, and they are not re-calculated here either. The old logic that analyzes module dependencies from .mpl or .msd files is still in place as a fallback in case the new method fails.

These changes are part of an ongoing effort to improve Java module facets and module facets in general.

Exclude commented-out nodes from scopes (also available in 2022.3.2)

When relying on the default scope calculation, commented-out potential target nodes are now automatically excluded from the scope.

Other

  • A hexadecimal long literal has been introduced into BaseLanguage.
  • When a project requires migration and there are module/model version incompatibilities (for instance, if the module mentions a language version different from the version mentioned in a model), a popup notification window is displayed with an action that shows all modules with incompatibilities. This is helpful when you’re merging migrated code, as you can make sure the merged state reflects the correct language and module versions.
  • Modules under a devkit in the Logical View pane are shown as module-reference nodes. This is similar to how runtime modules under a language module are presented.

Numerous bug fixes

  • As usual, this build fixes quite a few bugs. You can find a full list of all the issues we’ve fixed here.

Platform updates

New terminal in the new UI

Beta

MPS 2024.1 unveils an overhauled terminal featuring both visual and functional enhancements to streamline command-line tasks. This update gives the familiar tool a fresh new look, with commands separated into distinct blocks, along with an expanded set of features, such as smooth navigation between blocks, command completion, and easy access to the command history. Learn more in this blog post.

Option to scale down the entire IDE

You can now scale the IDE down to 90%, 80%, or 70%, giving you the flexibility to adjust the size of IDE elements both upward and downward.

Gradle version support update

Starting from this version, MPS 2024.1 no longer supports projects using Gradle versions older than 4.5, and the IDE will not perform Gradle sync for projects with unsupported Gradle versions.

Numerous VCS features

Option to display review branch changes in a Log tab

MPS 2024.1 streamlines the code review workflow by offering a focused view of branch-related changes. For GitHub, GitLab, and Space, it is now possible to see changes in a certain branch in a separate Log tab within the Git tool window. To do so, click on the branch name in the Pull Requests tool window and pick Show in Git Log from the menu.

Support for reactions on code review comments

MPS 2024.1 brings support for posting reactions to review comments for GitHub pull requests and GitLab merge requests, with a set of emojis already available to choose from.

Create pull/merge requests from push notifications

After successfully pushing your changes to the version control system, the IDE will now alert you with a single notification informing you about the successful push and suggesting an action to create a pull/merge request.

Visual indicators for pending GitHub updates

We’ve introduced visual indicators to inform you about pending updates within your code review workflow. When there are changes that require your attention, a dot will appear on the tool window icon. Unseen pull requests will also be marked with a blue dot, ensuring you don’t miss updates in your code review process.

Preventing large file commits to repositories

To help you avoid version control rejections due to oversized files, the IDE now includes a pre-commit check that prevents you from committing such files and notifies you of the restriction.

Branch filter for the History tab in the Git tool window

In the Git tool window, the Show all branches button has been replaced with a branch filter, allowing you to review changes made to a file within a designated branch. We’ve also adjusted the orientation of the toolbar, positioning it horizontally for improved usability.

Improved search in the Branches popup

In the Branches popup, you can now filter search results by actions and repositories for quicker and more precise navigation within your version control system.

Allow unrelated histories merge option

The Merge into dialog now has an Allow unrelated histories option in the drop-down menu. When selected, it allows two branches to be merged even if they have no common history.

Option to exclude folders and files from comparison

In the diff viewer, you can now specify folders and files to be ignored during the comparison process in order to focus solely on relevant changes. Just right-click on any file or folder you don’t want to appear in the comparison results and select Exclude from results from the context menu.

Migration guide

For every major release, we prepare instructions on how to migrate from older MPS versions to ensure everything goes smoothly. Please review them carefully in the updated Migration Guide.