New Implementation of Project Model Interfaces in 2020.3

Jakub Chrzanowski

The upcoming 2020.3 releases will include internal changes related to a significant redesign of the representation of project models in the IntelliJ Platform. This shouldn’t affect any plugins using the IntelliJ API properly and which don’t access internal classes. However, we want to give an overview of the changes and offer some insight into the reasons behind them.

There are several problems with the approach that has been used to represent the project model (configuration of modules, libraries, facet, artifacts, etc.) in the IntelliJ Platform for more than 15 years. First, different project model parts are stored in separate project-level and module-level services (ModuleManager, ModuleRootManager, LibraryTable, etc.). They are implemented independently, and the project model has no single entry point. This leads to code duplication and complicates bulk modifications of project model elements, since you need to manually track modifiable instances of the model elements or create special wrappers to do it for you (see IdeModifiableModelsProvider). Also, there is no way to serialize the project model’s entire content in a binary format in order to cache it or pass it to another process.

Second, the project model interfaces (Module, Library, Facet, etc.) are highly coupled with the API that is only available inside the IDE process and its component management system. So it isn’t possible to reuse those interfaces in other processes (e.g., inside the build process or inside the process that imports data from Gradle) or when the project hasn’t yet been initialized (e.g., inside New Project dialog). This means we need to create separate representations of project model elements for these cases (JpsProject, JpsModule, JpsLibrary, etc. for the build process; ProjectData, ModuleData, LibraryData, etc. for the importing process), and we need to update all these places every time we change something in the project model.

Third, the project-model concepts were created for IntelliJ IDEA before the platform accommodated a variety of languages, and many common interfaces like Module and Library still have Java-specific properties. This makes it harder to reuse them for other languages and technologies, and there is no simple way to create new language-specific concepts and use them in the model.

We’re going to solve these problems by providing a unified data structure that stores the project configuration and doesn’t have to be used from the IDE process. The initial variant of its implementation (WorkspaceEntityStorage) is located in the intellij.platform.workspaceModel.storage module. Note that its classes are marked as experimental because its API may change in future versions, so please don’t use it directly from your plugins. We’ve also created new implementations of the project model interfaces (Module, Library, LibraryTable, etc.), storing their data in WorkspaceEntityStorage. The API of these interfaces hasn’t been changed, so code that uses them should work as before. However, if some code tries to access the project model’s internal implementation classes (LibraryImpl, SourceFolderImpl, etc.), it will fail in IntelliJ IDEA 2020.3 because the IntelliJ Platform provides different implementations.

That’s all for now. When the new project model API is stable enough and ready to be used directly from the plugins, we’ll make another announcement. Stay tuned!

Subscribe

Subscribe for updates