Skip to main content

module-set-pluginization

Convert Product DSL module sets into bundled wrapper plugins.

Datos de origen

Repositorio
JetBrains/intellij-community
Última actividad en el origen
12 de agosto de 2026 a las 12:58
Idioma detectado de SKILL.md
inglés
Estrellas
20.445
Forks
6009

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
module-set-pluginization
description
Convert Product DSL module sets into bundled wrapper plugins.
<!-- Generated by community/.ai/render-guides.mjs; edit community/.agents/skills/module-set-pluginization/SKILL.md --> # Module Set Pluginization Use this workflow when a group of platform modules that currently live inside an aggregate Product DSL `ModuleSet` (typically `essential`, `essentialMinimal`, or `ide.common`) should become a standalone bundled plugin wrapper. **New canonical pattern:** the wrapper is a **hand-written** JPS module placed **next to the feature modules** — not auto-generated under `community/module-set-plugins/generated/`. Auto-generation is being phased out; legacy wrappers stay in place until migrated. Reference example: `community/platform/navbar/plugin/` (IJPL-245430, commit `9d61ae6803221`). ## Before Editing - Look at `community/platform/navbar/plugin/` as the reference: a sibling `plugin/` directory of the feature modules with its own `.iml`, `resources/META-INF/plugin.xml`, and `plugin-content.yaml`. - Decide whether the modules should still be inlined inside a parent module set in any product. Pluginized wrappers usually stop being emitted through the aggregate `intellij.moduleSets.<name>.xml` and become a bundled plugin instead. - For library modules with only a small closed consumer set, do **not** create or keep a shared wrapper just to make the library available. Prefer `visibility="private"` on the library descriptor and register the module as unnamed `<content>` in each consuming plugin, so each copy lives in that plugin's implicit private namespace. ## Create the Wrapper Plugin Module Create a new JPS module at `<feature-root>/plugin/`, e.g. `community/platform/<feature>/plugin/`: - `intellij.platform.<feature>.plugin.iml` under `community/platform/` — resources-only `JAVA_MODULE` inheriting JDK; for example: ```xml <?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> </module> ``` After creating the `.iml`, register it with the project-file helper instead of editing `modules.xml` by hand: ```bash bun build/jps-module.mjs register community/platform/<feature>/plugin/intellij.platform.<feature>.plugin.iml --fix-iml-eof ``` - `resources/META-INF/plugin.xml` — a minimal `<idea-plugin>` listing the content modules. Mirror the wrapper shape from navbar, but use the canonical platform plugin id for new wrappers (replace `FEATURE` with the actual short name; the description must be at least 40 characters): ```text <idea-plugin> <id>intellij.platform.FEATURE.plugin</id> <name>FEATURE</name> <description>Provides FEATURE platform modules for the IDE.</description> <vendor>JetBrains</vendor> <content namespace="jetbrains"> <module name="intellij.platform.FEATURE" loading="required"/> <module name="intellij.platform.FEATURE.backend"/> <module name="intellij.platform.FEATURE.frontend"/> <module name="intellij.platform.FEATURE.monolith"/> </content> </idea-plugin> ``` **Naming:** for new hand-written wrappers, use the JPS wrapper module name as the plugin **id** whenever possible: `intellij.platform.FEATURE.plugin` under `community/platform/` (for example, `intellij.platform.tasks.plugin`) or `intellij.FEATURE.plugin` outside the `platform/` subtree. This keeps bundled plugin ids and bundled plugin module names aligned in Product DSL, logs, and dependency declarations. Some older hand-written wrappers still use short ids such as `intellij.navbar.plugin`; do not copy that form for new platform wrappers. Do **not** reuse the legacy `com.intellij.moduleSet.FEATURE` prefix — that is the auto-generated wrapper convention being phased out, kept only on existing wrappers under `community/module-set-plugins/generated/`. The plugin **name** is a short human-readable label (e.g. `Tasks Platform`). No wrapper-specific descriptor marker is needed. Add the JPS wrapper module name to `HAND_WRITTEN_MODULE_SET_PLUGIN_MODULES` in `community/platform/build-scripts/product-dsl/src/ModuleSetPlugins.kt`. Generation intersects that build-time registry with each product's `ProductModulesLayout.bundledPluginModules`, avoiding changes to the runtime plugin descriptor model while keeping complete generated dependencies for wrapper content. Mark **only the shared/anchor module** (the one that loads in every product mode) as `loading="required"` — `intellij.platform.FEATURE` in the example. Plugin-XML inspection requires at least one required/embedded/required-if-available content module per wrapper, so the anchor satisfies that. Do **not** add `loading="required"` to backend / frontend / monolith modules: in frontend product mode (JetBrains Client) the platform's backend module is unavailable, so a required `FEATURE.backend` excludes itself and takes the whole wrapper plugin down — producing a confusing cascade like "Plugin 'FEATURE' depends on plugin 'IDEA CORE' which failed to load". - `plugin-content.yaml` — list the JAR layout. Mirror the navbar example: ```yaml - name: lib/modules/intellij.platform.<feature>.backend.jar contentModules: - name: intellij.platform.<feature>.backend - name: lib/modules/intellij.platform.<feature>.frontend.jar contentModules: - name: intellij.platform.<feature>.frontend - name: lib/modules/intellij.platform.<feature>.jar contentModules: - name: intellij.platform.<feature> - name: lib/modules/intellij.platform.<feature>.monolith.jar contentModules: - name: intellij.platform.<feature>.monolith - name: lib/platform-<feature>-plugin.jar modules: - name: intellij.platform.<feature>.plugin ``` - Suppress `SplitModeMixedDependencies` and `PluginXmlPluginLogo` in `plugin.xml` only if the inspection actually flags the wrapper. ## Update the Product DSL Remove the now-pluginized modules from the aggregate `ModuleSet`: - In `community/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt` (and any product-specific layout file that listed them), delete the `module("intellij.platform.<feature>.…")` / `embeddedModule(...)` calls that the wrapper now owns. - Add the wrapper JPS module name to `DEFAULT_BUNDLED_PLUGINS` in `community/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/ProductModulesLayout.kt`, e.g. `"intellij.platform.<feature>.plugin"`. - Add the wrapper JPS module name to `HAND_WRITTEN_MODULE_SET_PLUGIN_MODULES` in `community/platform/build-scripts/product-dsl/src/ModuleSetPlugins.kt`. - Check products that override or reset default bundled plugins (Rider's `ReSharperExternalProductProperties`, Gateway, JetBrains Client product-modules XML under `remote-dev/`, etc.) and add the wrapper module name where appropriate. Do **not** create a new `plugin("<feature>")` DSL block under the old generator path. The wrapper exists as a standalone JPS module instead. ## Re-trim Content Module Descriptors Pluginization is a good moment to verify that each former direct module declares only the dependencies it really needs: - Trim `intellij.platform.<feature>.<backend|frontend|monolith>.xml` so it declares the actual runtime dependencies (e.g. `intellij.platform.backend`, `intellij.platform.frontend`, the shared `intellij.platform.<feature>` module). - If any extension point was renamed/qualified, grep the repo for the old short name and update every `<extensionPoint …>` reference accordingly. - If a downstream consumer used a module that the new wrapper now hides, switch the consumer's descriptor to depend on the wrapper plugin: `<plugin id="intellij.platform.<feature>.plugin"/>` instead of `<module name="intellij.platform.<feature>.frontend"/>`. Existing references to legacy `com.intellij.moduleSet.<feature>` ids stay valid for the auto-generated wrappers that have not yet been migrated. ## Re-run Code Generation After the source edits, run the generators so the platform descriptors, Bazel files, and `.idea/modules.xml` are updated to match: ```bash bazel run //platform/buildScripts:plugin-model-tool ./build/jpsModelToBazel.cmd ``` Expected diffs: - `community/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.xml`, `…ide.common.xml`, and `licenseCommon/generated/META-INF/intellij.moduleSets.ide.ultimate.xml` no longer list the pluginized modules. - `community/.idea/modules.xml` and `.idea/modules.xml` gain the new `intellij.platform.<feature>.plugin.iml` module in helper-generated canonical order. - `build/bazel-generated-file-list.txt` and `community/build/bazel-generated-file-list.txt` gain the new plugin directory. - Product content snapshots (`build/expected/ultimate-content-platform.yaml`, `dbe/build/datagrip-content.yaml`, etc.) gain the wrapper plugin entry. - `tests/ideaProjectStructure/testResources/com/intellij/ideaProjectStructure/fast/available-in-idea-free-mode.txt` gains the new module if it is free-mode available. - Existing wrappers under `community/module-set-plugins/generated/intellij.moduleSet.plugin.<name>/` are unrelated — do not touch them unless you are migrating one to the new pattern. ## Fix Ordering Bugs When Validation Runs Before Generation Hand-written wrappers usually do not hit the pre-generation-on-disk ordering trap, since the descriptor exists in source from the first build. The cache path remains relevant only for the legacy generated wrappers: - `PluginContentCache` injects `PluginContentInfo` objects for already-generated wrappers during the model-building stage. If you migrate one of those to the new pattern, drop the corresponding cache entry along with the generated directory. ## Downstream Test Runtime Dependencies Pluginization can break narrow test modules even when product packaging tests pass. Test runtime classpaths may still include a plugin module whose extracted platform dependency is no longer embedded. Catch this from `idea.log`, not from test assertion text alone. - Inspect `Plugin set resolution` and `Problems found loading plugins` in local or TeamCity test logs. - Treat messages such as missing `intellij.platform.structureView.impl`, `intellij.platform.execution.serviceView`, or `intellij.platform.navbar.frontend` as a missing wrapper-plugin runtime dependency (`intellij.moduleSet.plugin.structureView`, `intellij.moduleSet.plugin.servicesView`, or the new `intellij.platform.<feature>.plugin`). - Add the wrapper dep only to the affected test module with `scope="RUNTIME"`. Do not add it to broad shared modules such as `intellij.platform.testFramework` or aggregate/global test infrastructure. - After changing `.iml`, run `./build/jpsModelToBazel.cmd` and verify the generated `BUILD.bazel` runtime deps are updated. - For TeamCity, read the published test log artifact when needed: `/app/rest/builds/id:<buildId>/artifacts/content/testlog.zip!.../idea.log`. ## Pre-TeamCity Canary Suite Run this suite before relying on TeamCity after pluginization or plugin dependency changes. Run the listed commands in parallel when resources allow; the order is diagnostic priority, not execution order. Fix failures in checks 1-6 before interpreting downstream canary failures. 1. Embedded dependency closure: `./bazel.cmd run //platform/buildScripts:plugin-model-tool -- --json='{"filter":"embeddedDependencyClosure","pluginSourceOnly":true}'` 2. Product DSL module-set validation: `./tests.cmd --module intellij.platform.buildScripts.productDsl.tests --test org.jetbrains.intellij.build.productLayout.validator.ProductModuleSetValidatorTest` 3. Fast project structure/root packages: `./tests.cmd --module intellij.projectStructureTests --test com.intellij.ideaProjectStructure.fast.IntelliJProjectPackageNamesTest` 4. Product packaging baseline: `./tests.cmd --module intellij.idea.ultimate.build.tests --test com.intellij.idea.ultimate.build.smokeTests.AllProductsPackagingTest` 5. CLion packaging baseline: `./tests.cmd --module intellij.clion.build.tests --test org.jetbrains.intellij.build.clion.CLionPackagingTest` 6. Rider packaging baseline: `./tests.cmd --module intellij.rider.build.tests --test com.jetbrains.rider.build.RiderPackagingTest` 7. Database and SQL plugin loading: `./tests.cmd --module intellij.database.tests --test com.intellij.database.DataGripLiteSuite` `./tests.cmd --module intellij.database.sql.tests --test com.intellij.sql.SqlFileStructureViewTest` `./tests.cmd --module intellij.database.sql.tests --test com.intellij.sql.editor.SqlMultiLineTodoTest` 8. Code Server DB plugin loading: `./tests.cmd --module intellij.codeServer.db.sql.tests --test com.intellij.database.SqlCompletionTest` `./tests.cmd --module intellij.codeServer.db.csv.datagrid.tests --test com.intellij.codeServer.db.csv.datagrid.tests.CsvCoreGridTest` 9. Package Checker plugin loading: `./tests.cmd --module intellij.packageChecker.tests --test com.intellij.packageChecker.model.VulnerabilitiesRepositoryServerTest` 10. Grazie and spellchecker plugin loading: `./community/tests.cmd --module intellij.grazie.tests --test com.intellij.grazie.spellchecker.inspector.SuggestionTest` `./community/tests.cmd --module intellij.grazie.tests --test com.intellij.grazie.spellchecker.inspection.CommentsWithMistakesInspectionTest` 11. Shell plus Markdown plugin loading: `./community/tests.cmd --module intellij.sh.tests --test com.intellij.sh.highlighting.ShHighlightUsagesInMarkdownTest` 12. Ruby plugin loading: `./tests.cmd --module intellij.ruby.tests --test org.jetbrains.plugins.ruby.gem.GemsProviderTest` `./tests.cmd --module intellij.ruby.tests --test org.jetbrains.plugins.ruby.ruby.psi.RubyHeredocInjectorTest#testSqlHeredoc` 13. RustRover structure and SQL loading: `./tests.cmd --module intellij.rustrover.core.test --test org.rust.ide.structure.RsStructureViewModelTest` `./tests.cmd --module intellij.rustrover.sql.tests --test com.jetbrains.rust.sql.SqlInjectorTest` 14. ReSharper external services/DataGrip bridge: `./tests.cmd --module intellij.resharper.external.services.test.cases.rd --test com.jetbrains.resharper.external.services.test.cases.ReSharperDataGripRdTest` 15. AI Assistant plugin loading: `./tests.cmd --module intellij.ml.llm.chat.tests --test com.intellij.ml.llm.core.chat.ui.chat.navigation.FilePathMatcherTest` `./tests.cmd --module intellij.ml.llm.completion.tests --test com.intellij.ml.llm.completion.cloud.context.mainEditor.RecentLocationsContextCollectorTest` `./tests.cmd --module intellij.ml.llm.devkit.tests --test com.intellij.ml.llm.devkit.context.DevKitChatContextProviderTest` `./tests.cmd --module intellij.ml.llm.java.embeddings.tests --test com.intellij.ml.llm.java.embeddings.JavaEmbeddingParsingTest` `./tests.cmd --module intellij.ml.llm.java.inlinePromptDetector.tests --test com.intellij.ml.llm.java.inlinePromptDetector.JavaInlinePromptHighlightingTest` `./tests.cmd --module intellij.ml.llm.nextEdits.tests --test 'com.intellij.ml.llm.nextEdits.tests.history.NextEditFileHistoryTest;com.intellij.ml.llm.nextEdits.tests.diff.CheckFileRangesSyntaxCorrectTest'` `./tests.cmd --module intellij.ml.llm.ruby.test --test com.intellij.ml.llm.ruby.testGeneration.RubyLLMGenerateTestsSupportPromptTest` `./tests.cmd --module intellij.ml.llm.ruby.test --test com.intellij.ml.llm.ruby.testGeneration.rails.RailsGenerateTestsPromptTest` `./tests.cmd --module intellij.ml.llm.sql.tests --test com.intellij.ml.llm.sql.SqlObjectChatInputTest` ## Verification - Run `lint_files()` on every changed Kotlin source and test file. - Run the Pre-TeamCity Canary Suite after generated files and narrow test dependencies are updated. - Keep CLion and Rider packaging tests in the standard suite: wrapper plugins and `DEFAULT_BUNDLED_PLUGINS` changes can affect those product baselines even when `AllProductsPackagingTest` is green. - Run at least one representative test from each affected test module via `./tests.cmd --module <module> --test <FQN or FQN#method>`. Prefer a small smoke test that exercises plugin loading without external fixtures. - If the original CI test needs unavailable data or services, run a nearby smoke test and document the local blocker. Confirm `idea.log` no longer reports the original missing wrapper plugin. - Re-render the skill mirrors: ```bash node community/.ai/render-guides.mjs ```
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub