From 9c22586f83eb5cf102a714052d40b57afc142b26 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 8 Apr 2024 19:33:48 +0200 Subject: [PATCH] Revert "IJPL-973: avoid opening the module file too early - resolve the module descriptor during the build time and embed it" This reverts commit 4c14459bd2f3fb3fe0461e144def3faf9b34f43a. GitOrigin-RevId: 94679752f5ea08da5996c961d8de6741c1c6cdd8 --- .../intellij/build/impl/PlatformModules.kt | 45 ++-------- .../plugins/ModuleDependenciesDescriptor.kt | 9 +- .../ide/plugins/PluginDescriptorLoader.kt | 64 ++++++++------ .../src/com/intellij/ide/plugins/XmlReader.kt | 84 ++++++------------- .../com/intellij/ide/plugins/PluginBuilder.kt | 4 +- 5 files changed, 74 insertions(+), 132 deletions(-) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PlatformModules.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PlatformModules.kt index acd98db54e21..2a815b6ba6b6 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PlatformModules.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PlatformModules.kt @@ -22,7 +22,6 @@ import org.jetbrains.jps.model.java.JpsJavaClasspathKind import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.model.module.JpsModuleDependency import org.jetbrains.jps.model.module.JpsModuleReference -import java.nio.file.Files import java.util.* private val PLATFORM_API_MODULES = persistentListOf( @@ -269,7 +268,6 @@ internal suspend fun createPlatformLayout(addPlatformCoverage: Boolean, ?: context.productProperties.applicationInfoModule val productPluginContentModules = getProductPluginContentModules( context = context, - layout = layout, productPluginSourceModuleName = productPluginSourceModuleName, ) val explicit = mutableListOf() @@ -511,14 +509,8 @@ private fun compute(list: List>>, } } -private const val INTELLIJ_PLATFORM_RESOURCES_MODULE_NAME = "intellij.platform.resources" - // result _must be_ consistent, do not use Set.of or HashSet here -private suspend fun getProductPluginContentModules( - context: BuildContext, - productPluginSourceModuleName: String, - layout: PlatformLayout, -): Set { +private suspend fun getProductPluginContentModules(context: BuildContext, productPluginSourceModuleName: String): Set { val result = LinkedHashSet() withContext(Dispatchers.IO) { @@ -540,13 +532,16 @@ private suspend fun getProductPluginContentModules( // we don't want to allow providing product modules in any x-include, check only specific ones if (root.children.any { it.name == "include" && it.getAttributeValue("href") == "/META-INF/common-ide-modules.xml" }) { - handleCommonModules(layout = layout, result = result, context = context) + collectProductModules( + root = readXmlAsModel(context.findFileInModuleSources("intellij.platform.resources", "META-INF/common-ide-modules.xml")!!), + result = result, + ) } } withContext(Dispatchers.IO) { collectProductModules( - root = readXmlAsModel(context.findFileInModuleSources(INTELLIJ_PLATFORM_RESOURCES_MODULE_NAME, "META-INF/PlatformLangPlugin.xml")!!), + root = readXmlAsModel(context.findFileInModuleSources("intellij.platform.resources", "META-INF/PlatformLangPlugin.xml")!!), result = result, ) } @@ -554,34 +549,6 @@ private suspend fun getProductPluginContentModules( return result } -private fun handleCommonModules(layout: PlatformLayout, result: LinkedHashSet, context: BuildContext) { - val relativePath = "META-INF/common-ide-modules.xml" - val data = readXmlAsModel(context.findFileInModuleSources(INTELLIJ_PLATFORM_RESOURCES_MODULE_NAME, relativePath)!!) - collectProductModules(root = data, result = result) - - layout.withPatch { moduleOutputPatcher, buildContext -> - val modules = data.getChild("content")!!.children("module").joinToString(separator = "") { - val moduleName = it.getAttributeValue("name")!! - val moduleContent = Files.readString(context.findFileInModuleSources(moduleName, "$moduleName.xml")) - require(!moduleContent.contains("""" - } - val content = """ - - - $modules - - - """.trimIndent() - moduleOutputPatcher.patchModuleOutput( - moduleName = INTELLIJ_PLATFORM_RESOURCES_MODULE_NAME, - path = relativePath, - content = content, - overwrite = true - ) - } -} - private fun collectProductModules(root: XmlElement, result: LinkedHashSet) { for (module in (root.getChild("content")?.children("module") ?: emptySequence())) { val moduleName = module.attributes.get("name") ?: continue diff --git a/platform/core-impl/src/com/intellij/ide/plugins/ModuleDependenciesDescriptor.kt b/platform/core-impl/src/com/intellij/ide/plugins/ModuleDependenciesDescriptor.kt index ae8344f7a077..c7518b3de5db 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/ModuleDependenciesDescriptor.kt +++ b/platform/core-impl/src/com/intellij/ide/plugins/ModuleDependenciesDescriptor.kt @@ -30,13 +30,8 @@ class PluginContentDescriptor(@JvmField val modules: List) { } @ApiStatus.Internal - class ModuleItem( - @JvmField val name: String, - @JvmField val configFile: String?, - @JvmField internal val descriptorContent: String?, - ) { - @JvmField - internal var descriptor: IdeaPluginDescriptorImpl? = null + class ModuleItem(@JvmField val name: String, @JvmField val configFile: String?) { + @JvmField internal var descriptor: IdeaPluginDescriptorImpl? = null fun requireDescriptor(): IdeaPluginDescriptorImpl = descriptor ?: throw IllegalStateException("Descriptor is not set for $this") diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt index d076a44d73f7..884bb68e1427 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt @@ -24,7 +24,6 @@ import com.intellij.util.io.URLUtil import com.intellij.util.lang.UrlClassLoader import com.intellij.util.lang.ZipFilePool import com.intellij.util.xml.dom.createNonCoalescingXmlStreamReader -import com.intellij.util.xml.dom.createXmlStreamReader import kotlinx.coroutines.* import org.codehaus.stax2.XMLStreamReader2 import org.jetbrains.annotations.ApiStatus.Internal @@ -740,34 +739,22 @@ private fun loadModuleDescriptors( if (moduleDirExists && !pathResolver.isRunningFromSources && moduleName.startsWith("intellij.")) { val jarFile = loadingStrategy.findProductContentModuleClassesRoot(moduleName, moduleDir) - if (module.descriptorContent == null) { - val resolver = pool.load(jarFile) - try { - moduleRaw = resolver.loadZipEntry(subDescriptorFile)?.let { - readModuleDescriptor( - input = it, - readContext = context, - pathResolver = pathResolver, - dataLoader = dataLoader, - includeBase = null, - readInto = null, - locationSource = jarFile.toString(), - ) - } - } - finally { - (resolver as? Closeable)?.close() + val resolver = pool.load(jarFile) + try { + moduleRaw = resolver.loadZipEntry(subDescriptorFile)?.let { + readModuleDescriptor( + input = it, + readContext = context, + pathResolver = pathResolver, + dataLoader = dataLoader, + includeBase = null, + readInto = null, + locationSource = jarFile.toString(), + ) } } - else { - moduleRaw = readModuleDescriptor( - reader = createXmlStreamReader(module.descriptorContent.reader()), - readContext = context, - pathResolver = pathResolver, - dataLoader = dataLoader, - includeBase = null, - readInto = null, - ) + finally { + (resolver as? Closeable)?.close() } if (moduleRaw != null) { @@ -968,6 +955,29 @@ internal fun CoroutineScope.loadDescriptorsFromDir( } } +// urls here expected to be a file urls to plugin.xml +private fun CoroutineScope.loadDescriptorsFromClassPath( + urlToFilename: Map, + context: DescriptorListLoadingContext, + pathResolver: ClassPathXmlPathResolver, + useCoreClassLoader: Boolean, + pool: ZipFilePool, +): List> { + return urlToFilename.map { (url, filename) -> + async(Dispatchers.IO) { + loadDescriptorFromResource( + resource = url, + filename = filename, + context = context, + pathResolver = pathResolver, + useCoreClassLoader = useCoreClassLoader, + pool = pool, + libDir = null, + ) + } + } +} + // filename - plugin.xml or ${platformPrefix}Plugin.xml private fun loadDescriptorFromResource( resource: URL, diff --git a/platform/core-impl/src/com/intellij/ide/plugins/XmlReader.kt b/platform/core-impl/src/com/intellij/ide/plugins/XmlReader.kt index 4889b3e03c40..80f5e37c9071 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/XmlReader.kt +++ b/platform/core-impl/src/com/intellij/ide/plugins/XmlReader.kt @@ -747,61 +747,33 @@ private fun readComponents(reader: XMLStreamReader2, containerDescriptor: Contai private fun readContent(reader: XMLStreamReader2, descriptor: RawPluginDescriptor, readContext: ReadModuleContext) { reader.consumeChildElements { elementName -> - if (elementName != "module") { - reader.skipElement() - throw RuntimeException("Unknown content item type: $elementName") - } - - var name: String? = null - for (i in 0 until reader.attributeCount) { - when (reader.getAttributeLocalName(i)) { - "name" -> name = readContext.interner.name(reader.getAttributeValue(i)) - } - } - - if (name.isNullOrEmpty()) { - throw RuntimeException("Name is not specified at ${reader.location}") - } - - var configFile: String? = null - val index = name.lastIndexOf('/') - if (index != -1) { - configFile = "${name.substring(0, index)}.${name.substring(index + 1)}.xml" - } - - if (descriptor.contentModules == null) { - descriptor.contentModules = ArrayList() - } - - val isEndElement = reader.next() == XMLStreamConstants.END_ELEMENT - if (isEndElement) { - descriptor.contentModules!!.add(PluginContentDescriptor.ModuleItem( - name = name, - configFile = configFile, - descriptorContent = null, - )) - } - else { - val descriptorContent = reader.text?.takeIf { it.isNotBlank() } - descriptor.contentModules!!.add(PluginContentDescriptor.ModuleItem( - name = name, - configFile = configFile, - descriptorContent = descriptorContent, - )) - - var nesting = 1 - while (true) { - val type = reader.next() - if (type == XMLStreamConstants.START_ELEMENT) { - nesting++ - } - else if (type == XMLStreamConstants.END_ELEMENT) { - if (--nesting == 0) { - break + when (elementName) { + "module" -> { + var name: String? = null + for (i in 0 until reader.attributeCount) { + when (reader.getAttributeLocalName(i)) { + "name" -> name = readContext.interner.name(reader.getAttributeValue(i)) } } + + if (name.isNullOrEmpty()) { + throw RuntimeException("Name is not specified at ${reader.location}") + } + + var configFile: String? = null + val index = name.lastIndexOf('/') + if (index != -1) { + configFile = "${name.substring(0, index)}.${name.substring(index + 1)}.xml" + } + + if (descriptor.contentModules == null) { + descriptor.contentModules = ArrayList() + } + descriptor.contentModules!!.add(PluginContentDescriptor.ModuleItem(name = name, configFile = configFile)) } + else -> throw RuntimeException("Unknown content item type: $elementName") } + reader.skipElement() } assert(reader.isEndElement) } @@ -814,9 +786,8 @@ private fun readDependencies(reader: XMLStreamReader2, descriptor: RawPluginDesc "module" -> { var name: String? = null for (i in 0 until reader.attributeCount) { - if (reader.getAttributeLocalName(i) == "name") { - name = readContext.interner.name(reader.getAttributeValue(i)) - break + when (reader.getAttributeLocalName(i)) { + "name" -> name = readContext.interner.name(reader.getAttributeValue(i)) } } @@ -825,9 +796,8 @@ private fun readDependencies(reader: XMLStreamReader2, descriptor: RawPluginDesc "plugin" -> { var id: String? = null for (i in 0 until reader.attributeCount) { - if (reader.getAttributeLocalName(i) == "id") { - id = readContext.interner.name(reader.getAttributeValue(i)) - break + when (reader.getAttributeLocalName(i)) { + "id" -> id = readContext.interner.name(reader.getAttributeValue(i)) } } diff --git a/platform/platform-tests/testSrc/com/intellij/ide/plugins/PluginBuilder.kt b/platform/platform-tests/testSrc/com/intellij/ide/plugins/PluginBuilder.kt index e971a9da61ae..ce0101e74e92 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/plugins/PluginBuilder.kt +++ b/platform/platform-tests/testSrc/com/intellij/ide/plugins/PluginBuilder.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.plugins import com.intellij.openapi.extensions.PluginId @@ -103,7 +103,7 @@ class PluginBuilder { fun module(moduleName: String, moduleDescriptor: PluginBuilder): PluginBuilder { val fileName = "$moduleName.xml" subDescriptors.put(fileName, moduleDescriptor) - content.add(PluginContentDescriptor.ModuleItem(name = moduleName, configFile = null, descriptorContent = null)) + content.add(PluginContentDescriptor.ModuleItem(name = moduleName, configFile = null)) // remove default dependency on lang moduleDescriptor.noDepends()