platform/build-scripts/product-dsl/docs/module-sets.md
Module sets are reusable collections of modules that can be referenced as a single entity in product configurations. They solve the problem of:
Module sets are defined in Kotlin code and auto-generate XML files:
CommunityModuleSets.kt or UltimateModuleSets.ktmoduleSet() in their content descriptorsKey principle: Code is the source of truth, XML files are generated artifacts.
| Location | File Path | Description |
|---|---|---|
| Community | community/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt | IDE feature sets (essential, vcs, xml, debugger) |
| Community (Core) | community/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CoreModuleSets.kt | Platform infrastructure (libraries, corePlatform, rpc) |
| Ultimate | platform/buildScripts/src/productLayout/UltimateModuleSets.kt | Ultimate-only module sets |
Each module set is defined as a Kotlin function (e.g., fun essential(): ModuleSet) that returns a ModuleSet object. The XML files (pattern: intellij.moduleSets.<name>.xml) are auto-generated from this Kotlin code.
Module sets are discovered automatically via reflection. The generator scans provider objects (like CommunityModuleSets) for all public no-argument functions that return ModuleSet:
// From discovery/ModuleSetDiscovery.kt
fun discoverModuleSets(provider: Any): List<ModuleSet> {
// Finds all public functions returning ModuleSet with no parameters
// Caches method handles for performance
}
This means: Any public function returning ModuleSet in a provider object will be automatically discovered and have its XML generated.
To regenerate XML files from Kotlin code:
Using JetBrains MCP (Recommended):
mcp__jetbrains__execute_run_configuration(configurationName="Generate Product Layouts")
From IDE: Run the "Generate Product Layouts" run configuration.
To query module set structure, relationships, and usage programmatically, use the JSON analysis endpoint:
UltimateModuleSets.main(args = ["--json"])
See the Programmatic Content documentation for details.
The moduleSet() DSL provides these functions for building module sets. For the complete DSL reference including all loading modes and product-level functions, see dsl-api-reference.md.
moduleSet() - Create a Module Setfun moduleSet(
name: String, // Required: identifier for the set
alias: String? = null, // Optional: module alias (e.g., "com.intellij.modules.xml")
outputModule: String? = null, // Optional: module whose resources dir receives generated XML
selfContained: Boolean = false, // Optional: validate in isolation
includeDependencies: Boolean = false, // Optional: default for embedded modules
block: ModuleSetBuilder.() -> Unit
): ModuleSet
module() - Add a Regular Modulefun module(name: String, loading: ModuleLoadingRuleValue? = null)
Adds a module with default or specified loading mode. Most modules use this.
embeddedModule() - Add an Embedded Modulefun embeddedModule(name: String)
Adds a module with loading="embedded". Use for modules that must load in the core classloader:
requiredModule() - Add a Required Modulefun requiredModule(name: String)
Adds a module with loading="required". Use for test framework modules and other modules that must be present but don't need embedded loading.
moduleSet() - Include a Nested Module Setfun moduleSet(set: ModuleSet)
Includes another module set. Creates hierarchical composition:
fun ideCommon() = moduleSet("ide.common") {
moduleSet(essential()) // Nest essential modules
moduleSet(vcs()) // Nest VCS modules
moduleSet(xml()) // Nest XML modules
}
plugin(name) - Create Pluginized Module Setfun plugin(
name: String,
pluginId: String? = null,
outputModule: String? = null,
addToMainModule: Boolean = true,
block: ModuleSetBuilder.() -> Unit
): ModuleSet
Creates a module set and marks it to be materialized as a standalone bundled plugin wrapper.
The Product DSL pipeline generates the wrapper module files, plugin-content.yaml, and modules.xml entries during generation.
The resulting set must not be referenced through product-level or nested moduleSet(...) composition; bundle the generated wrapper plugin module instead.
fun recentFiles() = plugin("recentFiles") {
module("intellij.platform.recentFiles")
module("intellij.platform.recentFiles.frontend")
module("intellij.platform.recentFiles.backend")
}
Set addToMainModule = false when the wrapper must not be added to intellij.moduleSet.plugin.main for flat-classpath launches.
alias - Module AliasGenerates a <module value="..."/> declaration in the XML, allowing plugins to depend on this module set as a module:
fun xml() = moduleSet("xml", alias = "com.intellij.modules.xml") {
// ...
}
Generated XML includes:
<module value="com.intellij.modules.xml"/>
outputModule - Custom Output LocationSpecifies which module's resources directory should contain the generated XML:
fun corePlatform() = moduleSet("core.platform", outputModule = "intellij.platform.ide.core") {
// Generated XML goes to intellij.platform.ide.core's META-INF/ instead of default location
}
Use when the module set needs to be in a specific location for classloader or packaging reasons.
selfContained - Isolated ValidationWhen true, the module set is validated in isolation to ensure all dependencies are resolvable within the set itself:
fun corePlatform() = moduleSet("core.platform", selfContained = true) {
// Must include ALL dependencies - no external module references allowed
}
Use for module sets designed to be standalone building blocks.
includeDependencies - Auto-Include DependenciesWhen true, embedded modules in this set automatically include their implementation-only transitive dependencies:
fun essential() = moduleSet("essential", includeDependencies = true) {
embeddedModule("intellij.platform.core") // Inherits includeDependencies=true
}
See programmatic-content.md for details on content vs implementation modules.
/**
* VCS frontend modules.
*/
fun vcsFrontend(): ModuleSet = plugin("vcs.frontend") {
module("intellij.platform.vcs.impl.frontend")
}
/**
* VCS (Version Control System) modules including shared and frontend parts.
*/
fun vcs(): ModuleSet = moduleSet("vcs") {
module("intellij.platform.vcs.impl")
module("intellij.platform.vcs.impl.exec")
module("intellij.platform.vcs.log")
module("intellij.platform.vcs.log.impl")
embeddedModule("intellij.platform.vcs")
moduleSet(vcsShared()) // Nest shared modules
moduleSet(vcsFrontend()) // Nest frontend modules
}
/**
* XML support modules.
*/
fun xml(): ModuleSet = moduleSet("xml", alias = "com.intellij.modules.xml") {
embeddedModule("intellij.xml.dom")
embeddedModule("intellij.xml.psi")
embeddedModule("intellij.xml.psi.impl")
module("intellij.xml.emmet")
module("intellij.relaxng")
// ...
}
requiredModule)/**
* Test framework libraries (JUnit 4, JUnit 5, Hamcrest).
* Use when a product (or test plugin) must bundle these explicitly; avoid adding it to a DSL test
* plugin when the product already provides the same modules (auto-add will skip resolvable deps).
*/
fun librariesTestFrameworks(): ModuleSet = moduleSet("libraries.testFrameworks") {
requiredModule("intellij.libraries.assertj.core")
requiredModule("intellij.libraries.hamcrest")
requiredModule("intellij.libraries.junit4")
requiredModule("intellij.libraries.junit5")
requiredModule("intellij.libraries.junit5.jupiter")
}
/**
* Essential platform modules required by most IDE products.
*/
fun essential(): ModuleSet = moduleSet("essential", includeDependencies = true) {
// Include minimal essential modules
moduleSet(essentialMinimal())
moduleSet(debugger())
// Embedded modules (core classloader)
embeddedModule("intellij.platform.scopes")
embeddedModule("intellij.platform.find")
embeddedModule("intellij.platform.polySymbols")
// Regular modules
module("intellij.platform.navbar")
module("intellij.platform.navbar.backend")
module("intellij.platform.clouds")
module("intellij.platform.todo")
// ... many more
}
See /create-module-set slash command for detailed instructions on creating a new module set.
Quick checklist:
CommunityModuleSets.kt or UltimateModuleSets.kt)moduleSet(yourSet())To find available module sets and understand their contents:
Browse the source code - Open the Kotlin files listed in Module Set Locations
Read KDoc comments - Each module set function has comprehensive documentation including:
Use the JSON endpoint - Run UltimateModuleSets.main(args = ["--json"]) for programmatic analysis:
Check generated XML - The generated XML files show expanded module lists:
intellij.moduleSets.<name>.xmlcommunity/platform/platform-resources/generated/META-INF/ (community) or licenseCommon/generated/ (ultimate)Best practice: Start by browsing the Kotlin source files and reading KDoc comments. They are the canonical source of truth.
Create a new module set when:
Don't create a module set if:
vcs, xml, ssh, essentiallibraries.core, ide.common, essential.minimalModule sets can:
module("intellij.platform.vcs.impl")moduleSet(corePlatform())embeddedModule("intellij.platform.core") for core classloaderrequiredModule("intellij.libraries.junit5") for test frameworksincludeDependencies = true to automatically pull in module dependenciesTip: Prefer nesting existing module sets over duplicating modules. This creates a clean hierarchy and ensures consistency.
Cause: Function is not public or doesn't return ModuleSet directly.
Fix: Ensure your function is:
fun mySet(): ModuleSet = moduleSet("my.set") { ... } // ✓ Correct
private fun mySet() = ... // ✗ Not discovered (private)
fun mySet(): Any = ... // ✗ Not discovered (wrong return type)
Cause: outputModule specifies a module without a resources directory.
Fix: Either:
outputModule to use default locationCause: Module set A includes B, and B includes A.
Fix: Restructure to break the cycle. Usually extract common modules to a third set.
Cause: A module set function was renamed/removed but its XML file remains.
Fix: The generator automatically cleans orphaned files. If persisting, manually delete the .xml file.
See validation-rules.md for validation rules and errors.md for troubleshooting.