From b864b06e519fb92bc915bcc657130473931d9f16 Mon Sep 17 00:00:00 2001 From: Nikolay Chashnikov Date: Tue, 13 Feb 2024 14:36:29 +0100 Subject: [PATCH] [modular loader] search for files included in plugin.xml in the plugin libraries when started from sources (RDCT-773) We have a case with Terminal plugin where plugin.xml includes 'completion-specs.xml' file from a library JAR. When IDE is started from sources, this JAR isn't merged with the main plugin JAR, so we need to use custom PathResolver when loading plugin.xml to be able to load it. GitOrigin-RevId: 625c8aa0daf224159d17d70160637ff8b0d3f896 --- .../ModuleBasedPluginXmlPathResolver.kt | 36 +++++++++---------- .../ModuleBasedProductLoadingStrategy.kt | 35 ++++++++++-------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedPluginXmlPathResolver.kt b/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedPluginXmlPathResolver.kt index 22fc58c9b5b6..94e2c2ff44a1 100644 --- a/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedPluginXmlPathResolver.kt +++ b/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedPluginXmlPathResolver.kt @@ -3,14 +3,12 @@ package com.intellij.platform.bootstrap import com.intellij.ide.plugins.* import com.intellij.platform.runtime.repository.IncludedRuntimeModule -import java.nio.file.Path /** * Implementation of [PathResolver] which can load module descriptors not only from the main plugin JAR file, unlike [PluginXmlPathResolver] * which always loads them from the JAR file containing plugin.xml file. */ internal class ModuleBasedPluginXmlPathResolver( - private val allResourceRoots: List, private val includedModules: List, private val fallbackResolver: PathResolver, ) : PathResolver { @@ -21,24 +19,22 @@ internal class ModuleBasedPluginXmlPathResolver( path: String, readInto: RawPluginDescriptor?, ): RawPluginDescriptor { - if (allResourceRoots.size > 1) { - // if there are multiple JARs, - // it may happen that module descriptor is located in other JARs (e.g., in case of 'com.intellij.java.frontend' plugin), - // so try loading it from the root of the corresponding module - val moduleName = path.removeSuffix(".xml") - val moduleDescriptor = includedModules.find { it.moduleDescriptor.moduleId.stringId == moduleName }?.moduleDescriptor - if (moduleDescriptor != null) { - val input = moduleDescriptor.readFile(path) ?: error("Cannot resolve $path in $moduleDescriptor") - return readModuleDescriptor( - input = input, - readContext = readContext, - pathResolver = this, - dataLoader = dataLoader, - includeBase = null, - readInto = readInto, - locationSource = path, - ) - } + // if there are multiple JARs, + // it may happen that module descriptor is located in other JARs (e.g., in case of 'com.intellij.java.frontend' plugin), + // so try loading it from the root of the corresponding module + val moduleName = path.removeSuffix(".xml") + val moduleDescriptor = includedModules.find { it.moduleDescriptor.moduleId.stringId == moduleName }?.moduleDescriptor + if (moduleDescriptor != null) { + val input = moduleDescriptor.readFile(path) ?: error("Cannot resolve $path in $moduleDescriptor") + return readModuleDescriptor( + input = input, + readContext = readContext, + pathResolver = this, + dataLoader = dataLoader, + includeBase = null, + readInto = readInto, + locationSource = path, + ) } return fallbackResolver.resolveModuleFile(readContext = readContext, dataLoader = dataLoader, path = path, readInto = readInto) } diff --git a/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedProductLoadingStrategy.kt b/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedProductLoadingStrategy.kt index e882ea8bb644..fadd62b60598 100644 --- a/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedProductLoadingStrategy.kt +++ b/platform/bootstrap/src/com/intellij/platform/bootstrap/ModuleBasedProductLoadingStrategy.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.async import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.exists +import kotlin.io.path.extension internal class ModuleBasedProductLoadingStrategy(internal val moduleRepository: RuntimeModuleRepository) : ProductLoadingStrategy() { @OptIn(ExperimentalStdlibApi::class) @@ -167,6 +168,13 @@ internal class ModuleBasedProductLoadingStrategy(internal val moduleRepository: } val allResourceRoots = includedModules.flatMapTo(LinkedHashSet()) { it.moduleDescriptor.resourceRootPaths } + val requiredLibraries = collectRequiredLibraryModules(pluginModuleGroup) + if (requiredLibraries.isNotEmpty()) { + thisLogger().debug("Additional library modules will be added to classpath of $pluginModuleGroup: $requiredLibraries") + requiredLibraries.flatMapTo(allResourceRoots) { it.resourceRootPaths } + } + val allResourceRootsList = allResourceRoots.toList(); + val descriptor = if (Files.isDirectory(mainResourceRoot)) { loadDescriptorFromDir( dir = mainResourceRoot, @@ -174,33 +182,30 @@ internal class ModuleBasedProductLoadingStrategy(internal val moduleRepository: context = context, isBundled = true, pathResolver = ModuleBasedPluginXmlPathResolver( - allResourceRoots = allResourceRoots.toList(), - includedModules = includedModules, - fallbackResolver = PluginXmlPathResolver.DEFAULT_PATH_RESOLVER, + includedModules = includedModules, + fallbackResolver = PluginXmlPathResolver(allResourceRootsList.filter { it.extension == "jar" }, zipFilePool), ) ) } else { - val includedModulesRootsList = allResourceRoots.toList() + val defaultResolver = PluginXmlPathResolver(allResourceRootsList, zipFilePool) + val pathResolver = + if (allResourceRootsList.size == 1) { + defaultResolver + } + else { + ModuleBasedPluginXmlPathResolver(includedModules = includedModules, fallbackResolver = defaultResolver) + } loadDescriptorFromJar( file = mainResourceRoot, - pathResolver = ModuleBasedPluginXmlPathResolver( - allResourceRoots = includedModulesRootsList, - includedModules = includedModules, - fallbackResolver = PluginXmlPathResolver(includedModulesRootsList, zipFilePool), - ), + pathResolver = pathResolver, parentContext = context, isBundled = true, pluginDir = mainResourceRoot.parent.parent, pool = zipFilePool, ) } - val requiredLibraries = collectRequiredLibraryModules(pluginModuleGroup) - if (requiredLibraries.isNotEmpty()) { - thisLogger().debug("Additional library modules will be added to classpath of $pluginModuleGroup: $requiredLibraries") - requiredLibraries.flatMapTo(allResourceRoots) { it.resourceRootPaths } - } - descriptor?.jarFiles = allResourceRoots.toList() + descriptor?.jarFiles = allResourceRootsList return descriptor }