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 @@ + +