From 008c81e9162f023b4decbcbb9af8cd5364e9c1a5 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sat, 30 May 2026 16:18:12 +0200 Subject: [PATCH] IJPL-241314 keep action group dependencies explicit Plugin XML generation now records action group declarations and add-to-group references from plugin descriptors. When a plugin contributes an action into a group declared by another content module, generated dependencies keep that module explicit even if the module is embedded in product layouts. This makes plugin loading order match action registration requirements, including Kotlin's XDebugger.Settings contribution in tests, and prevents bootstrap failures caused by missing action groups. IJ-MR-184958 IJ-MR-184993 IJ-MR-179029 IJ-MR-184126 IJ-MR-181153 IJ-MR-146078 IJ-MR-175479 IJ-MR-186058 IJ-MR-193195 IJ-MR-196957 IJ-MR-199124 IJ-MR-197441 IJ-MR-204135 IJ-MR-204674 IJ-MR-205883 GitOrigin-RevId: 43bfdc4b53dfa836ddbaf626e10399407d2fad24 --- .../src/dependency/ModuleDescriptorCache.kt | 6 ++ .../src/discovery/PluginContentExtractor.kt | 14 ++++ .../generator/PluginXmlDependencyGenerator.kt | 71 ++++++++++++++++++- .../dependency/PluginDependencyTestSupport.kt | 16 ++++- .../dependency/PluginXmlGenerationTest.kt | 68 +++++++++++++++++- .../build/kotlin/KotlinPluginBuilder.kt | 2 - .../CompileOnlyDependenciesInCommunity.kt | 1 + ...intellij.platform.credentialStore.impl.xml | 2 +- .../parser/impl/PluginXmlConst.kt | 6 ++ .../pluginSystem/parser/impl/XmlReader.kt | 59 +++++++++++++++ plugins/grazie/src/test/BUILD.bazel | 4 ++ .../grazie/src/test/intellij.grazie.tests.iml | 2 + plugins/junit5_rt_tests/BUILD.bazel | 2 + .../intellij.junit.v5.rt.tests.iml | 1 + plugins/junit6_rt_tests/BUILD.bazel | 6 +- .../intellij.junit.v6.rt.tests.iml | 1 + .../resources/kotlin.gradle.gradle-java.xml | 1 + .../kotlin.gradle.scripting.k2/BUILD.bazel | 18 ++++- ...intellij.kotlin.gradle.scripting.tests.iml | 7 +- .../kotlin/jvm-debugger/base/util/BUILD.bazel | 2 + ...intellij.kotlin.jvm.debugger.base.util.iml | 1 + ...intellij.kotlin.jvm.debugger.base.util.xml | 10 +++ .../jvm-debugger/coroutines/BUILD.bazel | 10 ++- ...ntellij.kotlin.jvm.debugger.coroutines.iml | 2 +- ...ntellij.kotlin.jvm.debugger.coroutines.xml | 15 ++++ ...ntellij.kotlin.jvm.debugger.evaluation.xml | 1 + plugins/kotlin/plugin/plugin-content.yaml | 8 ++- .../plugin/resources/META-INF/plugin.xml | 6 ++ 28 files changed, 324 insertions(+), 18 deletions(-) create mode 100644 plugins/kotlin/jvm-debugger/base/util/resources/intellij.kotlin.jvm.debugger.base.util.xml create mode 100644 plugins/kotlin/jvm-debugger/coroutines/resources/intellij.kotlin.jvm.debugger.coroutines.xml diff --git a/platform/build-scripts/product-dsl/src/dependency/ModuleDescriptorCache.kt b/platform/build-scripts/product-dsl/src/dependency/ModuleDescriptorCache.kt index d26e0ceeb6a2..cf69cf342555 100644 --- a/platform/build-scripts/product-dsl/src/dependency/ModuleDescriptorCache.kt +++ b/platform/build-scripts/product-dsl/src/dependency/ModuleDescriptorCache.kt @@ -50,6 +50,10 @@ internal class ModuleDescriptorCache( @JvmField val registeredServiceKeys: Set = emptySet(), /** Service keys registered with `overrides="true"`. */ @JvmField val overridingServiceKeys: Set = emptySet(), + /** Action group IDs declared by this descriptor. */ + @JvmField val declaredActionGroupIds: Set = emptySet(), + /** Action group IDs referenced by this descriptor. */ + @JvmField val referencedActionGroupIds: Set = emptySet(), /** * Suppressible error if the descriptor has issues (e.g., non-standard XML root element). * Collected by generators and filtered through suppression config based on [UnsuppressedPipelineError.suppressionKey]. @@ -142,6 +146,8 @@ internal class ModuleDescriptorCache( existingModuleDependencies = parseResult.moduleDependencies, registeredServiceKeys = parseResult.registeredServiceKeys, overridingServiceKeys = parseResult.overridingServiceKeys, + declaredActionGroupIds = parseResult.declaredActionGroupIds, + referencedActionGroupIds = parseResult.referencedActionGroupIds, suppressibleError = suppressibleError, ) } diff --git a/platform/build-scripts/product-dsl/src/discovery/PluginContentExtractor.kt b/platform/build-scripts/product-dsl/src/discovery/PluginContentExtractor.kt index 6b45e5cec12c..100e43b3e14a 100644 --- a/platform/build-scripts/product-dsl/src/discovery/PluginContentExtractor.kt +++ b/platform/build-scripts/product-dsl/src/discovery/PluginContentExtractor.kt @@ -121,6 +121,10 @@ internal data class PluginContentInfo( * Used for IDE capability markers (e.g., `com.intellij.modules.java`, `com.intellij.modules.ruby-capable`). */ @JvmField val pluginAliases: List = emptyList(), + /** Action group IDs declared by this plugin.xml and its xi:includes. */ + @JvmField val declaredActionGroupIds: Set = emptySet(), + /** Action group IDs referenced by this plugin.xml and its xi:includes. */ + @JvmField val referencedActionGroupIds: Set = emptySet(), ) { /** True if DSL-defined (content computed from spec, not extracted from disk) */ val isDslDefined: Boolean get() = source == PluginSource.DSL_TEST @@ -244,6 +248,8 @@ internal suspend fun extractPluginContent( source = source, legacyDepends = extractLegacyDepends(content), pluginAliases = extractedContent.pluginAliases, + declaredActionGroupIds = extractedContent.declaredActionGroupIds, + referencedActionGroupIds = extractedContent.referencedActionGroupIds, ) } @@ -253,6 +259,8 @@ private class ExtractedContent( @JvmField val pluginDependencies: Set, /** Plugin aliases declared via `` elements (main file + xi:includes) */ @JvmField val pluginAliases: List, + @JvmField val declaredActionGroupIds: Set, + @JvmField val referencedActionGroupIds: Set, /** Deps by source file: first entry = main plugin.xml, subsequent = xi:includes */ @JvmField val depsByFile: List, ) @@ -273,6 +281,8 @@ private suspend fun extractContentModules( val allModuleDependencies = LinkedHashSet() val allPluginDependencies = LinkedHashSet() val allPluginAliases = LinkedHashSet() + val allDeclaredActionGroupIds = LinkedHashSet() + val allReferencedActionGroupIds = LinkedHashSet() val depsByFile = ArrayList() val processedPaths = HashSet() @@ -295,6 +305,8 @@ private suspend fun extractContentModules( for (alias in result.pluginAliases) { allPluginAliases.add(PluginId(alias)) } + allDeclaredActionGroupIds.addAll(result.declaredActionGroupIds) + allReferencedActionGroupIds.addAll(result.referencedActionGroupIds) // Track deps per file depsByFile.add(FileDepInfo(relativePath = path, moduleDependencies = moduleDeps, pluginDependencies = pluginDeps)) } @@ -328,6 +340,8 @@ private suspend fun extractContentModules( moduleDependencies = allModuleDependencies, pluginDependencies = allPluginDependencies, pluginAliases = allPluginAliases.toList(), + declaredActionGroupIds = allDeclaredActionGroupIds, + referencedActionGroupIds = allReferencedActionGroupIds, depsByFile = depsByFile, ) } diff --git a/platform/build-scripts/product-dsl/src/generator/PluginXmlDependencyGenerator.kt b/platform/build-scripts/product-dsl/src/generator/PluginXmlDependencyGenerator.kt index 21bdf940532d..04f4ed2089a4 100644 --- a/platform/build-scripts/product-dsl/src/generator/PluginXmlDependencyGenerator.kt +++ b/platform/build-scripts/product-dsl/src/generator/PluginXmlDependencyGenerator.kt @@ -13,7 +13,9 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import org.jetbrains.intellij.build.productLayout.debug import org.jetbrains.intellij.build.productLayout.config.SuppressionConfig +import org.jetbrains.intellij.build.productLayout.dependency.ModuleDescriptorCache import org.jetbrains.intellij.build.productLayout.dependency.PluginContentProvider import org.jetbrains.intellij.build.productLayout.deps.PluginDependencyPlan import org.jetbrains.intellij.build.productLayout.deps.PluginDependencyPlanOutput @@ -66,6 +68,7 @@ internal object PluginDependencyPlanner : PipelineNode { // DSL-defined plugins are generated from Kotlin specs and skipped here. val tasks = ArrayList>() val pluginGraphDeps = collectPluginGraphDeps(graph = graph, allRealProductNames = allRealProductNames) + val actionGroupProviderModules = buildActionGroupProviderModules(graph = graph, descriptorCache = model.descriptorCache) for (graphDeps in pluginGraphDeps) { if (graphDeps.isDslDefined) continue tasks.add(async { @@ -73,6 +76,7 @@ internal object PluginDependencyPlanner : PipelineNode { graph = graph, graphDeps = graphDeps, pluginContentCache = pluginContentCache, + actionGroupProviderModules = actionGroupProviderModules, suppressionConfig = suppressionConfig, updateSuppressions = updateSuppressions, emitError = ctx::emitError, @@ -90,6 +94,7 @@ internal data class PluginGraphDeps( val pluginContentModuleName: ContentModuleName, @JvmField val isDslDefined: Boolean, @JvmField val isTest: Boolean, + @JvmField val contentModules: Set, @JvmField val jpsModuleDependencies: Set, @JvmField val jpsPluginDependencies: Set, /** Plugin deps declared via legacy `` in plugin.xml. */ @@ -156,6 +161,7 @@ internal fun collectPluginGraphDeps( pluginContentModuleName = pluginName, isDslDefined = plugin.isDslDefined, isTest = plugin.isTest, + contentModules = contentModules, jpsModuleDependencies = moduleDeps, jpsPluginDependencies = pluginDeps, legacyConfigFilePluginDependencies = legacyConfigFilePluginDeps, @@ -167,6 +173,59 @@ internal fun collectPluginGraphDeps( return results } +internal suspend fun buildActionGroupProviderModules( + graph: PluginGraph, + descriptorCache: ModuleDescriptorCache, +): Map> { + val moduleNames = LinkedHashSet() + graph.query { + contentModules { contentModule -> + if (hasContentSource(contentModule.id)) { + moduleNames.add(contentModule.contentName()) + } + } + } + + val providers = LinkedHashMap>() + coroutineScope { + moduleNames.map { moduleName -> + async { + moduleName to descriptorCache.getOrAnalyze(moduleName.value)?.declaredActionGroupIds.orEmpty() + } + }.awaitAll() + }.forEach { (moduleName, groupIds) -> + for (groupId in groupIds) { + providers.getOrPut(groupId) { LinkedHashSet() }.add(moduleName) + } + } + return providers +} + +internal fun computeActionGroupModuleDependencies( + pluginInfo: PluginContentInfo, + graphDeps: PluginGraphDeps, + actionGroupProviderModules: Map>, +): Set { + if (pluginInfo.referencedActionGroupIds.isEmpty()) { + return emptySet() + } + + val result = LinkedHashSet() + for (groupId in pluginInfo.referencedActionGroupIds) { + val providers = actionGroupProviderModules[groupId] ?: continue + for (provider in providers) { + if (provider == graphDeps.pluginContentModuleName || provider in graphDeps.contentModules) { + continue + } + result.add(provider) + debug("missingDeps") { + "actionGroupOrder plugin=${graphDeps.pluginContentModuleName.value} group=$groupId dep=${provider.value}" + } + } + } + return result +} + /** * Container for filtered plugin dependencies. * @@ -193,6 +252,7 @@ private suspend fun buildPluginDependencyPlan( graph: PluginGraph, graphDeps: PluginGraphDeps, pluginContentCache: PluginContentProvider, + actionGroupProviderModules: Map>, suppressionConfig: SuppressionConfig, updateSuppressions: Boolean, emitError: (org.jetbrains.intellij.build.productLayout.model.error.ValidationError) -> Unit, @@ -215,13 +275,20 @@ private suspend fun buildPluginDependencyPlan( val mainDependencyEntries = extractDependenciesEntries(info.pluginXmlContent) val managedXmlModuleDeps = mainDependencyEntries?.managedModuleNames?.mapTo(HashSet(), ::ContentModuleName) ?: existingXmlModuleDeps val managedXmlPluginDeps = mainDependencyEntries?.managedPluginIds?.mapTo(HashSet(), ::PluginId) ?: existingXmlPluginDeps + val actionGroupModuleDeps = computeActionGroupModuleDependencies( + pluginInfo = info, + graphDeps = graphDeps, + actionGroupProviderModules = actionGroupProviderModules, + ) + val effectiveJpsModuleDependencies = graphDeps.jpsModuleDependencies + actionGroupModuleDeps + val effectiveGraphDeps = graphDeps.copy(jpsModuleDependencies = effectiveJpsModuleDependencies) val effectiveJpsPluginDependencies = graphDeps.jpsPluginDependencies - graphDeps.legacyConfigFilePluginDependencies val suppressedModules = suppressionConfig.getPluginSuppressedModules(pluginContentModuleName) val suppressedPlugins = suppressionConfig.getPluginSuppressedPlugins(pluginContentModuleName) val moduleHandling = computeExistingDependencyHandling( updateSuppressions = updateSuppressions, existingXmlDeps = existingXmlModuleDeps, - jpsDeps = graphDeps.jpsModuleDependencies, + jpsDeps = effectiveJpsModuleDependencies, suppressedDeps = suppressedModules, xmlOnlySuppressionCandidateDeps = managedXmlModuleDeps, ) @@ -235,7 +302,7 @@ private suspend fun buildPluginDependencyPlan( ) val deps = filterPluginDependencies( - graphDeps = graphDeps, + graphDeps = effectiveGraphDeps, pluginInfo = info, jpsPluginDependencies = effectiveJpsPluginDependencies, suppressedModules = moduleHandling.effectiveSuppressedDeps, diff --git a/platform/build-scripts/product-dsl/testSrc/dependency/PluginDependencyTestSupport.kt b/platform/build-scripts/product-dsl/testSrc/dependency/PluginDependencyTestSupport.kt index 75c43dad57ec..6e3e17027221 100644 --- a/platform/build-scripts/product-dsl/testSrc/dependency/PluginDependencyTestSupport.kt +++ b/platform/build-scripts/product-dsl/testSrc/dependency/PluginDependencyTestSupport.kt @@ -25,7 +25,9 @@ import org.jetbrains.intellij.build.productLayout.deps.ContentModuleDependencyPl import org.jetbrains.intellij.build.productLayout.deps.ContentModuleDependencyPlanOutput import org.jetbrains.intellij.build.productLayout.discovery.PluginContentInfo import org.jetbrains.intellij.build.productLayout.generator.PluginGraphDeps +import org.jetbrains.intellij.build.productLayout.generator.buildActionGroupProviderModules import org.jetbrains.intellij.build.productLayout.generator.collectPluginGraphDeps +import org.jetbrains.intellij.build.productLayout.generator.computeActionGroupModuleDependencies import org.jetbrains.intellij.build.productLayout.generator.computeAliasPreservedPluginDeps import org.jetbrains.intellij.build.productLayout.generator.computeExistingDependencyHandling import org.jetbrains.intellij.build.productLayout.generator.embeddedCheckProductNames @@ -125,6 +127,7 @@ internal suspend fun generatePluginDependencies( val allRealProductNames = embeddedCheckProductNames(testSetup.products.map { it.name }) val pluginGraphDeps = collectPluginGraphDeps(graph = graph, allRealProductNames = allRealProductNames) .associateBy { it.pluginContentModuleName.value } + val actionGroupProviderModules = buildActionGroupProviderModules(graph = graph, descriptorCache = descriptorCache) val generationOutputs = plugins.map { pluginModuleName -> async { @@ -137,6 +140,7 @@ internal suspend fun generatePluginDependencies( allRealProductNames = allRealProductNames, outputProvider = outputProvider, descriptorCache = descriptorCache, + actionGroupProviderModules = actionGroupProviderModules, suppressionConfig = suppressionConfig, updateSuppressions = updateSuppressions, strategy = strategy, @@ -231,6 +235,7 @@ private suspend fun generatePluginDependency( allRealProductNames: Set, outputProvider: ModuleOutputProvider, descriptorCache: ModuleDescriptorCache, + actionGroupProviderModules: Map>, suppressionConfig: SuppressionConfig, updateSuppressions: Boolean, strategy: FileUpdateStrategy, @@ -249,13 +254,20 @@ private suspend fun generatePluginDependency( val mainDependencyEntries = extractDependenciesEntries(info.pluginXmlContent) val managedXmlModuleDeps = mainDependencyEntries?.managedModuleNames?.mapTo(HashSet(), ::ContentModuleName) ?: existingXmlModuleDeps val managedXmlPluginDeps = mainDependencyEntries?.managedPluginIds?.mapTo(HashSet(), ::PluginId) ?: existingXmlPluginDeps + val actionGroupModuleDeps = computeActionGroupModuleDependencies( + pluginInfo = info, + graphDeps = graphDeps, + actionGroupProviderModules = actionGroupProviderModules, + ) + val effectiveJpsModuleDependencies = graphDeps.jpsModuleDependencies + actionGroupModuleDeps + val effectiveGraphDeps = graphDeps.copy(jpsModuleDependencies = effectiveJpsModuleDependencies) val effectiveJpsPluginDependencies = graphDeps.jpsPluginDependencies - graphDeps.legacyConfigFilePluginDependencies val suppressedModules = effectiveConfig.getPluginSuppressedModules(pluginContentModuleName) val suppressedPlugins = effectiveConfig.getPluginSuppressedPlugins(pluginContentModuleName) val moduleHandling = computeExistingDependencyHandling( updateSuppressions = updateSuppressions, existingXmlDeps = existingXmlModuleDeps, - jpsDeps = graphDeps.jpsModuleDependencies, + jpsDeps = effectiveJpsModuleDependencies, suppressedDeps = suppressedModules, xmlOnlySuppressionCandidateDeps = managedXmlModuleDeps, ) @@ -271,7 +283,7 @@ private suspend fun generatePluginDependency( val effectiveSuppressedPlugins = pluginHandling.effectiveSuppressedDeps val deps = filterPluginDependencies( - graphDeps = graphDeps, + graphDeps = effectiveGraphDeps, pluginInfo = info, jpsPluginDependencies = effectiveJpsPluginDependencies, suppressedModules = effectiveSuppressedModules, diff --git a/platform/build-scripts/product-dsl/testSrc/dependency/PluginXmlGenerationTest.kt b/platform/build-scripts/product-dsl/testSrc/dependency/PluginXmlGenerationTest.kt index 43e819fb4ccc..25a158bd1531 100644 --- a/platform/build-scripts/product-dsl/testSrc/dependency/PluginXmlGenerationTest.kt +++ b/platform/build-scripts/product-dsl/testSrc/dependency/PluginXmlGenerationTest.kt @@ -6,7 +6,6 @@ import com.intellij.platform.pluginGraph.PluginGraph import com.intellij.platform.pluginGraph.PluginId import com.intellij.platform.pluginGraph.TargetName import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.runBlocking import org.assertj.core.api.Assertions.assertThat import org.jetbrains.intellij.build.productLayout.TestFailureLogger @@ -205,6 +204,59 @@ class PluginXmlGenerationTest { } } + @Test + fun `plugin action group reference generates module dependency on group owner`(@TempDir tempDir: Path) { + runBlocking(Dispatchers.Default) { + val setup = pluginTestSetup(tempDir) { + contentModule("intellij.platform.debugger.impl.ui") { + descriptor = """ + | + | + | + | + | + """.trimMargin() + } + contentModule("intellij.kotlin.jvm.debugger.core") { + descriptor = """""" + } + plugin("kotlin.plugin") { + pluginId = "org.jetbrains.kotlin" + content("intellij.kotlin.jvm.debugger.core") + } + product("IDEA") { + bundlesPlugin("kotlin.plugin") + moduleSet("debugger") { + module( + "intellij.platform.debugger.impl.ui", + com.intellij.platform.pluginSystem.parser.impl.elements.ModuleLoadingRuleValue.EMBEDDED, + ) + } + } + } + + val kotlinInfo = setup.pluginContentInfos.getValue("kotlin.plugin").withReferencedActionGroup("XDebugger.Settings") + val pluginContentCache = StubPluginContentCache(setup.pluginContentInfos + ("kotlin.plugin" to kotlinInfo)) + + val result = generatePluginDependencies( + plugins = listOf("kotlin.plugin"), + pluginContentCache = pluginContentCache, + testSetup = setup, + graph = setup.pluginGraph, + descriptorCache = ModuleDescriptorCache(setup.jps.outputProvider), + suppressionConfig = SuppressionConfig(), + strategy = setup.strategy, + testFrameworkContentModules = emptySet(), + ) + + assertThat(result.errors).isEmpty() + val pluginXmlDiff = setup.strategy.getDiffs().single { it.path.toString().contains("kotlin/plugin") } + assertThat(pluginXmlDiff.expectedContent) + .describedAs("Kotlin plugin.xml should depend on the content module declaring the referenced action group") + .contains("") + } + } + @Test fun `manual alias plugin dependency is preserved in plugin xml`(@TempDir tempDir: Path) { runBlocking(Dispatchers.Default) { @@ -320,6 +372,20 @@ private fun PluginContentInfo.withManualPluginDependency(pluginId: PluginId): Pl ) } +private fun PluginContentInfo.withReferencedActionGroup(groupId: String): PluginContentInfo { + val actionXml = """ + | + | + | + | + | + """.trimMargin() + return copy( + pluginXmlContent = pluginXmlContent.replace("", "$actionXml\n"), + referencedActionGroupIds = setOf(groupId), + ) +} + private fun PluginContentInfo.withManualAndGeneratedPluginDependency(pluginId: PluginId): PluginContentInfo { val dependencyTag = "" val updatedPluginXmlContent = pluginXmlContent.replace( diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt index 60020129bc1a..c44c7451f2b0 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt @@ -120,11 +120,9 @@ abstract class KotlinPluginBuilder(val kind : KotlinPluginKind = System.getPrope "intellij.kotlin.projectWizard.maven", "intellij.kotlin.projectWizard.gradle", "intellij.kotlin.projectWizard.compose", - "intellij.kotlin.jvm.debugger.base.util", "intellij.kotlin.jvm.debugger.core", "kotlin.jvm-debugger.evaluation", "intellij.kotlin.jvm.debugger.evaluation", - "intellij.kotlin.jvm.debugger.coroutines", "intellij.kotlin.jvm.debugger.eval4j", "intellij.kotlin.uast.base", "intellij.kotlin.uast.idea.base", diff --git a/platform/build-scripts/testFramework/src/com/intellij/platform/buildScripts/testFramework/pluginModel/CompileOnlyDependenciesInCommunity.kt b/platform/build-scripts/testFramework/src/com/intellij/platform/buildScripts/testFramework/pluginModel/CompileOnlyDependenciesInCommunity.kt index 0549ce745cb1..f54aabe01e48 100644 --- a/platform/build-scripts/testFramework/src/com/intellij/platform/buildScripts/testFramework/pluginModel/CompileOnlyDependenciesInCommunity.kt +++ b/platform/build-scripts/testFramework/src/com/intellij/platform/buildScripts/testFramework/pluginModel/CompileOnlyDependenciesInCommunity.kt @@ -9,6 +9,7 @@ val compileOnlyDependenciesInCommunity: List> = listOf( "*" to "intellij.platform.multiplatformSupport", // references are replaced by expects-compiler-plugin "*" to "fleet.util.multiplatform", // references are replaced by expects-compiler-plugin "*" to "intellij.platform.compose.compilerPlugin", // dependency is needed for compose compiler plugin + "intellij.kotlin.jvm.debugger.coroutines" to "intellij.java.rt", // module is used to compile debugger helper classes for external processes "intellij.java.rt" to "intellij.libraries.junit4", // module is used in external processes where the library from user's project is added to the classpath "intellij.platform.util" to "intellij.platform.util.troveCompileOnly", //used only for compilation of deprecated FileUtil.FILE_HASHING_STRATEGY left for compatibility ) \ No newline at end of file diff --git a/platform/credential-store-impl/resources/intellij.platform.credentialStore.impl.xml b/platform/credential-store-impl/resources/intellij.platform.credentialStore.impl.xml index 8a31b916a6b4..bfd629ab65ae 100644 --- a/platform/credential-store-impl/resources/intellij.platform.credentialStore.impl.xml +++ b/platform/credential-store-impl/resources/intellij.platform.credentialStore.impl.xml @@ -1,4 +1,4 @@ - + diff --git a/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/PluginXmlConst.kt b/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/PluginXmlConst.kt index 711630bdddd6..7a35a3e93eab 100644 --- a/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/PluginXmlConst.kt +++ b/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/PluginXmlConst.kt @@ -75,6 +75,12 @@ object PluginXmlConst { const val ACTIONS_ELEM: String = "actions" const val ACTIONS_RESOURCE_BUNDLE_ATTR: String = "resource-bundle" + const val ACTION_ELEM: String = "action" + const val ACTION_GROUP_ELEM: String = "group" + const val ACTION_GROUP_ID_ATTR: String = "id" + const val ACTION_OVERRIDES_ATTR: String = "overrides" + const val ADD_TO_GROUP_ELEM: String = "add-to-group" + const val ADD_TO_GROUP_GROUP_ID_ATTR: String = "group-id" const val APPLICATION_LISTENERS_ELEM: String = "applicationListeners" const val PROJECT_LISTENERS_ELEM: String = "projectListeners" diff --git a/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/XmlReader.kt b/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/XmlReader.kt index b648121b22f6..f6041e8264f0 100644 --- a/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/XmlReader.kt +++ b/platform/pluginSystem/parser/impl/src/com/intellij/platform/pluginSystem/parser/impl/XmlReader.kt @@ -1077,6 +1077,10 @@ class ContentParseResult( @JvmField val registeredServiceKeys: Set = emptySet(), /** Service keys registered with `overrides="true"`. */ @JvmField val overridingServiceKeys: Set = emptySet(), + /** Action group IDs declared by ``. */ + @JvmField val declaredActionGroupIds: Set = emptySet(), + /** Action group IDs referenced by ``. */ + @JvmField val referencedActionGroupIds: Set = emptySet(), ) /** @@ -1087,6 +1091,7 @@ class ContentParseResult( * - `` elements * - `xi:include` elements (at root level) * - service registrations + * - action group declarations and references * * All other elements are skipped efficiently. */ @@ -1116,6 +1121,8 @@ private fun parseElementForContentAndIncludes(reader: XMLStreamReader2): Content val pluginAliases = ArrayList() val registeredServiceKeys = HashSet() val overridingServiceKeys = HashSet() + val declaredActionGroupIds = HashSet() + val referencedActionGroupIds = HashSet() consumeChildElements(reader) { localName -> when (localName) { PluginXmlConst.INCLUDE_ELEM if reader.namespaceURI == PluginXmlConst.XINCLUDE_NAMESPACE_URI -> { @@ -1168,6 +1175,9 @@ private fun parseElementForContentAndIncludes(reader: XMLStreamReader2): Content PluginXmlConst.EXTENSIONS_ELEM -> { readRegisteredServiceKeys(reader, registeredServiceKeys, overridingServiceKeys) } + PluginXmlConst.ACTIONS_ELEM -> { + readActionGroupIds(reader, declaredActionGroupIds, referencedActionGroupIds) + } else -> { // Recursively check nested elements for xi:includes (they can appear at root level only, // but we still need to traverse to find them in case of nested structures) @@ -1186,9 +1196,58 @@ private fun parseElementForContentAndIncludes(reader: XMLStreamReader2): Content pluginAliases = pluginAliases, registeredServiceKeys = registeredServiceKeys, overridingServiceKeys = overridingServiceKeys, + declaredActionGroupIds = declaredActionGroupIds, + referencedActionGroupIds = referencedActionGroupIds, ) } +private fun readActionGroupIds( + reader: XMLStreamReader2, + declaredActionGroupIds: MutableSet, + referencedActionGroupIds: MutableSet, +) { + consumeChildElements(reader) { elementName -> + readActionElementGroupIds(reader, elementName, declaredActionGroupIds, referencedActionGroupIds) + } +} + +private fun readActionElementGroupIds( + reader: XMLStreamReader2, + elementName: String, + declaredActionGroupIds: MutableSet, + referencedActionGroupIds: MutableSet, +) { + when (elementName) { + PluginXmlConst.ACTION_GROUP_ELEM -> { + if (!isActionOverride(reader)) { + XmlReadUtils.findAttributeValue(reader, PluginXmlConst.ACTION_GROUP_ID_ATTR)?.let(declaredActionGroupIds::add) + } + consumeChildElements(reader) { childName -> + readActionElementGroupIds(reader, childName, declaredActionGroupIds, referencedActionGroupIds) + } + } + PluginXmlConst.ACTION_ELEM -> { + consumeChildElements(reader) { childName -> + readActionElementGroupIds(reader, childName, declaredActionGroupIds, referencedActionGroupIds) + } + } + PluginXmlConst.ADD_TO_GROUP_ELEM -> { + XmlReadUtils.findAttributeValue(reader, PluginXmlConst.ADD_TO_GROUP_GROUP_ID_ATTR)?.let(referencedActionGroupIds::add) + reader.skipElement() + } + else -> reader.skipElement() + } +} + +private fun isActionOverride(reader: XMLStreamReader2): Boolean { + for (i in 0 until reader.attributeCount) { + if (reader.getAttributeLocalName(i) == PluginXmlConst.ACTION_OVERRIDES_ATTR) { + return reader.getAttributeAsBoolean(i) + } + } + return false +} + private fun readRegisteredServiceKeys( reader: XMLStreamReader2, registeredServiceKeys: MutableSet, diff --git a/plugins/grazie/src/test/BUILD.bazel b/plugins/grazie/src/test/BUILD.bazel index 17b115db3f99..247ccd83ba7b 100644 --- a/plugins/grazie/src/test/BUILD.bazel +++ b/plugins/grazie/src/test/BUILD.bazel @@ -18,12 +18,14 @@ jvm_library( "@lib//:kotlin-test", "//java/testFramework", "@lib//:grazie-tests-org-jetbrains-intellij-deps-languagetool-languagetool-core", + "//xml/dom-impl", "//platform/structuralsearch:structuralSearch", "//module-set-plugins/generated/intellij.moduleSet.plugin.structuralSearch:moduleSet-plugin-structuralSearch", "//module-set-plugins/generated/intellij.moduleSet.plugin.structureView:moduleSet-plugin-structureView", "//module-set-plugins/generated/intellij.moduleSet.plugin.todoView:moduleSet-plugin-todoView", "//libraries/misc/plugin", "//platform/vcs-api:vcs", + "//platform/testRunner/plugin", ] ) @@ -133,12 +135,14 @@ jvm_library( ], runtime_deps = [ ":grazie-tests", + "//xml/dom-impl:dom-impl_test_lib", "//platform/structuralsearch:structuralSearch_test_lib", "//module-set-plugins/generated/intellij.moduleSet.plugin.structuralSearch:moduleSet-plugin-structuralSearch_test_lib", "//module-set-plugins/generated/intellij.moduleSet.plugin.structureView:moduleSet-plugin-structureView_test_lib", "//module-set-plugins/generated/intellij.moduleSet.plugin.todoView:moduleSet-plugin-todoView_test_lib", "//libraries/misc/plugin:plugin_test_lib", "//platform/ide-core:ide-core_test_lib", + "//platform/testRunner/plugin:plugin_test_lib", ] ) ### auto-generated section `build intellij.grazie.tests` end diff --git a/plugins/grazie/src/test/intellij.grazie.tests.iml b/plugins/grazie/src/test/intellij.grazie.tests.iml index 3cec8151bd30..a2f20cb4a23c 100644 --- a/plugins/grazie/src/test/intellij.grazie.tests.iml +++ b/plugins/grazie/src/test/intellij.grazie.tests.iml @@ -360,6 +360,7 @@ + @@ -383,5 +384,6 @@ + \ No newline at end of file diff --git a/plugins/junit5_rt_tests/BUILD.bazel b/plugins/junit5_rt_tests/BUILD.bazel index 3d401cc48f3e..eabf0193f0eb 100644 --- a/plugins/junit5_rt_tests/BUILD.bazel +++ b/plugins/junit5_rt_tests/BUILD.bazel @@ -9,6 +9,7 @@ jvm_library( runtime_deps = [ "//plugins/junit5_rt:junit-v5-rt", "//platform/smRunner", + "//platform/testRunner/plugin", ] ) @@ -96,6 +97,7 @@ jvm_library( ":junit-v5-rt-tests", "//platform/platform-util-io:ide-util-io_test_lib", "//platform/ide-core:ide-core_test_lib", + "//platform/testRunner/plugin:plugin_test_lib", ] ) ### auto-generated section `build intellij.junit.v5.rt.tests` end diff --git a/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml b/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml index cea566542060..c627cc222a68 100644 --- a/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml +++ b/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml @@ -44,6 +44,7 @@ + \ No newline at end of file diff --git a/plugins/junit6_rt_tests/BUILD.bazel b/plugins/junit6_rt_tests/BUILD.bazel index b508948b6afd..27471b4734d7 100644 --- a/plugins/junit6_rt_tests/BUILD.bazel +++ b/plugins/junit6_rt_tests/BUILD.bazel @@ -6,7 +6,10 @@ jvm_library( module_name = "intellij.junit.v6.rt.tests", visibility = ["//visibility:public"], srcs = glob([], allow_empty = True), - runtime_deps = ["//platform/smRunner"] + runtime_deps = [ + "//platform/smRunner", + "//platform/testRunner/plugin", + ] ) jvm_library( @@ -81,6 +84,7 @@ jvm_library( ":junit-v6-rt-tests", "//platform/platform-util-io:ide-util-io_test_lib", "//platform/ide-core:ide-core_test_lib", + "//platform/testRunner/plugin:plugin_test_lib", ] ) ### auto-generated section `build intellij.junit.v6.rt.tests` end diff --git a/plugins/junit6_rt_tests/intellij.junit.v6.rt.tests.iml b/plugins/junit6_rt_tests/intellij.junit.v6.rt.tests.iml index 346dcb23923d..4268c6733a30 100644 --- a/plugins/junit6_rt_tests/intellij.junit.v6.rt.tests.iml +++ b/plugins/junit6_rt_tests/intellij.junit.v6.rt.tests.iml @@ -37,6 +37,7 @@ + \ No newline at end of file diff --git a/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml b/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml index 3e7e3535fe32..f54bfbb0dcdf 100644 --- a/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml +++ b/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml @@ -13,6 +13,7 @@ + diff --git a/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/BUILD.bazel b/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/BUILD.bazel index 02673fbfb2d7..3be1543d1cd4 100644 --- a/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/BUILD.bazel +++ b/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/BUILD.bazel @@ -155,7 +155,13 @@ jvm_library( name = "kotlin-gradle-scripting-tests", module_name = "intellij.kotlin.gradle.scripting.tests", visibility = ["//visibility:public"], - srcs = glob([], allow_empty = True) + srcs = glob([], allow_empty = True), + runtime_deps = [ + "//plugins/kotlin/plugin/k2", + "//platform/testRunner/plugin", + "//plugins/gradle/plugin", + "//plugins/gradle/java/plugin", + ] ) jvm_library( @@ -172,8 +178,6 @@ jvm_library( "@lib//:kotlin-stdlib", "//platform/projectModel-api:projectModel", "//platform/projectModel-api:projectModel_test_lib", - "//plugins/kotlin/plugin/k2", - "//plugins/kotlin/plugin/k2:k2_test_lib", "//platform/editor-ui-api:editor-ui", "//platform/editor-ui-api:editor-ui_test_lib", "//platform/platform-api:ide", @@ -201,6 +205,10 @@ jvm_library( "//platform/external-system-impl:externalSystem-impl_test_lib", "//platform/execution", "//platform/execution:execution_test_lib", + "//platform/smRunner", + "//platform/smRunner:smRunner_test_lib", + "//platform/testRunner", + "//platform/testRunner:testRunner_test_lib", "//platform/workspace/jps", "//platform/workspace/jps:jps_test_lib", "//plugins/gradle", @@ -303,8 +311,12 @@ jvm_library( ], runtime_deps = [ ":kotlin-gradle-scripting-tests", + "//plugins/kotlin/plugin/k2:k2_test_lib", + "//platform/testRunner/plugin:plugin_test_lib", + "//plugins/gradle/plugin:plugin_test_lib", "//platform/observable:observable_test_lib", "//platform/platform-impl:ide-impl_test_lib", + "//plugins/gradle/java/plugin:plugin_test_lib", ] ) ### auto-generated section `build intellij.kotlin.gradle.scripting.tests` end diff --git a/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/intellij.kotlin.gradle.scripting.tests.iml b/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/intellij.kotlin.gradle.scripting.tests.iml index a07b00b250a0..ced17f32aae4 100644 --- a/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/intellij.kotlin.gradle.scripting.tests.iml +++ b/plugins/kotlin/gradle/scripting/kotlin.gradle.scripting.k2/intellij.kotlin.gradle.scripting.tests.iml @@ -25,7 +25,7 @@ - + @@ -41,8 +41,12 @@ + + + + @@ -83,6 +87,7 @@ + diff --git a/plugins/kotlin/jvm-debugger/base/util/BUILD.bazel b/plugins/kotlin/jvm-debugger/base/util/BUILD.bazel index b76d281795f3..c9a47ea66a3b 100644 --- a/plugins/kotlin/jvm-debugger/base/util/BUILD.bazel +++ b/plugins/kotlin/jvm-debugger/base/util/BUILD.bazel @@ -6,6 +6,8 @@ jvm_library( module_name = "intellij.kotlin.jvm.debugger.base.util", visibility = ["//visibility:public"], srcs = glob(["src/**/*.kt", "src/**/*.java", "src/**/*.form"], allow_empty = True), + resources = glob(["resources/**/*"]), + resource_strip_prefix = "resources", deps = [ "@lib//:kotlin-stdlib", "@lib//:kotlinc-kotlin-compiler-common", diff --git a/plugins/kotlin/jvm-debugger/base/util/intellij.kotlin.jvm.debugger.base.util.iml b/plugins/kotlin/jvm-debugger/base/util/intellij.kotlin.jvm.debugger.base.util.iml index 717e83f4d313..791a236c4135 100644 --- a/plugins/kotlin/jvm-debugger/base/util/intellij.kotlin.jvm.debugger.base.util.iml +++ b/plugins/kotlin/jvm-debugger/base/util/intellij.kotlin.jvm.debugger.base.util.iml @@ -3,6 +3,7 @@ + diff --git a/plugins/kotlin/jvm-debugger/base/util/resources/intellij.kotlin.jvm.debugger.base.util.xml b/plugins/kotlin/jvm-debugger/base/util/resources/intellij.kotlin.jvm.debugger.base.util.xml new file mode 100644 index 000000000000..cc4385cc485e --- /dev/null +++ b/plugins/kotlin/jvm-debugger/base/util/resources/intellij.kotlin.jvm.debugger.base.util.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/plugins/kotlin/jvm-debugger/coroutines/BUILD.bazel b/plugins/kotlin/jvm-debugger/coroutines/BUILD.bazel index 3b5fd23b0b80..5a4ec014d14e 100644 --- a/plugins/kotlin/jvm-debugger/coroutines/BUILD.bazel +++ b/plugins/kotlin/jvm-debugger/coroutines/BUILD.bazel @@ -1,6 +1,6 @@ ### auto-generated section `build intellij.kotlin.jvm.debugger.coroutines` start load("//build:compiler-options.bzl", "create_kotlinc_options") -load("@rules_jvm//:jvm.bzl", "jvm_library") +load("@rules_jvm//:jvm.bzl", "jvm_library", "jvm_provided_library") create_kotlinc_options( name = "custom_coroutines", @@ -11,6 +11,11 @@ create_kotlinc_options( x_context_parameters = True ) +jvm_provided_library( + name = "java_rt_provided", + lib = "//java/java-runtime:rt" +) + jvm_library( name = "coroutines", module_name = "intellij.kotlin.jvm.debugger.coroutines", @@ -59,7 +64,6 @@ jvm_library( "//java/execution/impl", "//java/debugger/impl", "//plugins/kotlin/code-insight/utils", - "//java/java-runtime:rt", "//libraries/kotlinx/serialization/core", "//libraries/kotlinx/serialization/json", "//java/java-impl:impl", @@ -68,6 +72,7 @@ jvm_library( "//platform/execution", "//platform/statistics", "//platform/util:util-ui", + ":java_rt_provided", ] ) @@ -116,6 +121,7 @@ jvm_library( "//java/execution/impl:impl_test_lib", "//java/debugger/impl:impl_test_lib", "//plugins/kotlin/code-insight/utils:utils_test_lib", + "//java/java-runtime:rt", "//java/java-runtime:rt_test_lib", "//libraries/kotlinx/serialization/core:core_test_lib", "//libraries/kotlinx/serialization/json:json_test_lib", diff --git a/plugins/kotlin/jvm-debugger/coroutines/intellij.kotlin.jvm.debugger.coroutines.iml b/plugins/kotlin/jvm-debugger/coroutines/intellij.kotlin.jvm.debugger.coroutines.iml index e3a87d296103..2c9f1224f430 100644 --- a/plugins/kotlin/jvm-debugger/coroutines/intellij.kotlin.jvm.debugger.coroutines.iml +++ b/plugins/kotlin/jvm-debugger/coroutines/intellij.kotlin.jvm.debugger.coroutines.iml @@ -69,7 +69,7 @@ - + diff --git a/plugins/kotlin/jvm-debugger/coroutines/resources/intellij.kotlin.jvm.debugger.coroutines.xml b/plugins/kotlin/jvm-debugger/coroutines/resources/intellij.kotlin.jvm.debugger.coroutines.xml new file mode 100644 index 000000000000..b5865d65a8e3 --- /dev/null +++ b/plugins/kotlin/jvm-debugger/coroutines/resources/intellij.kotlin.jvm.debugger.coroutines.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/plugins/kotlin/jvm-debugger/evaluation/k2/resources/intellij.kotlin.jvm.debugger.evaluation.xml b/plugins/kotlin/jvm-debugger/evaluation/k2/resources/intellij.kotlin.jvm.debugger.evaluation.xml index 4008f415c7d9..87f90e468692 100644 --- a/plugins/kotlin/jvm-debugger/evaluation/k2/resources/intellij.kotlin.jvm.debugger.evaluation.xml +++ b/plugins/kotlin/jvm-debugger/evaluation/k2/resources/intellij.kotlin.jvm.debugger.evaluation.xml @@ -5,6 +5,7 @@ + diff --git a/plugins/kotlin/plugin/plugin-content.yaml b/plugins/kotlin/plugin/plugin-content.yaml index 2f2f48f58800..fd511bd97c57 100644 --- a/plugins/kotlin/plugin/plugin-content.yaml +++ b/plugins/kotlin/plugin/plugin-content.yaml @@ -17,6 +17,12 @@ - name: lib/intellij.kotlin.codeInsight.shared.jar contentModules: - name: intellij.kotlin.codeInsight.shared +- name: lib/intellij.kotlin.jvm.debugger.base.util.jar + contentModules: + - name: intellij.kotlin.jvm.debugger.base.util +- name: lib/intellij.kotlin.jvm.debugger.coroutines.jar + contentModules: + - name: intellij.kotlin.jvm.debugger.coroutines - name: lib/javax-inject.jar library: javax-inject files: @@ -198,11 +204,9 @@ - name: intellij.kotlin.projectWizard.maven - name: intellij.kotlin.projectWizard.gradle - name: intellij.kotlin.projectWizard.compose - - name: intellij.kotlin.jvm.debugger.base.util - name: intellij.kotlin.jvm.debugger.core - name: kotlin.jvm-debugger.evaluation - name: intellij.kotlin.jvm.debugger.evaluation - - name: intellij.kotlin.jvm.debugger.coroutines - name: intellij.kotlin.jvm.debugger.eval4j - name: intellij.kotlin.uast.base - name: intellij.kotlin.uast.idea.base diff --git a/plugins/kotlin/plugin/resources/META-INF/plugin.xml b/plugins/kotlin/plugin/resources/META-INF/plugin.xml index fab42b498f1c..18c2c6ef7dd4 100644 --- a/plugins/kotlin/plugin/resources/META-INF/plugin.xml +++ b/plugins/kotlin/plugin/resources/META-INF/plugin.xml @@ -18,6 +18,10 @@ + + + + @@ -32,6 +36,8 @@ + +