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
This commit is contained in:
Vladimir Krivosheev
2024-04-08 19:33:48 +02:00
committed by intellij-monorepo-bot
parent 523ce16e58
commit 9c22586f83
5 changed files with 74 additions and 132 deletions

View File

@@ -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<ModuleItem>()
@@ -511,14 +509,8 @@ private fun compute(list: List<Pair<String, PersistentList<String>>>,
}
}
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<ModuleItem> {
private suspend fun getProductPluginContentModules(context: BuildContext, productPluginSourceModuleName: String): Set<ModuleItem> {
val result = LinkedHashSet<ModuleItem>()
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<ModuleItem>, 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("<![CDATA["))
"""<module name="$moduleName"><![CDATA[${moduleContent!!}]]></module>"""
}
val content = """
<idea>
<content>
$modules
</content>
</idea>
""".trimIndent()
moduleOutputPatcher.patchModuleOutput(
moduleName = INTELLIJ_PLATFORM_RESOURCES_MODULE_NAME,
path = relativePath,
content = content,
overwrite = true
)
}
}
private fun collectProductModules(root: XmlElement, result: LinkedHashSet<ModuleItem>) {
for (module in (root.getChild("content")?.children("module") ?: emptySequence())) {
val moduleName = module.attributes.get("name") ?: continue

View File

@@ -30,13 +30,8 @@ class PluginContentDescriptor(@JvmField val modules: List<ModuleItem>) {
}
@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")

View File

@@ -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<URL, String>,
context: DescriptorListLoadingContext,
pathResolver: ClassPathXmlPathResolver,
useCoreClassLoader: Boolean,
pool: ZipFilePool,
): List<Deferred<IdeaPluginDescriptorImpl?>> {
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,

View File

@@ -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))
}
}

View File

@@ -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()