From 1eb616c8cc405f737afe99d15398df026baa78f1 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 10 Apr 2025 11:24:49 +0200 Subject: [PATCH] support platform-specific custom plugin assets GitOrigin-RevId: fbb03cf3bfda02bb2d6a5fce7b0b36e0d626d808 --- .../intellij/build/CustomAssetDescriptor.kt | 8 +- .../org/jetbrains/intellij/build/Source.kt | 25 ++++++ .../intellij/build/SourceAndCacheStrategy.kt | 1 + .../intellij/build/dev/IdeBuilder.kt | 59 +------------ .../intellij/build/dev/PluginBuilder.kt | 76 ++++++++++++++-- .../build/impl/DistributionJARsBuilder.kt | 21 ----- .../intellij/build/impl/JarPackager.kt | 4 + .../intellij/build/impl/PluginLayout.kt | 19 +++- .../pluginPlatformSpecificResourcePackager.kt | 87 +++++++++++++++++++ .../org/jetbrains/intellij/build/mergeJars.kt | 4 + 10 files changed, 212 insertions(+), 92 deletions(-) create mode 100644 platform/build-scripts/src/org/jetbrains/intellij/build/impl/pluginPlatformSpecificResourcePackager.kt diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/CustomAssetDescriptor.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/CustomAssetDescriptor.kt index ac268b98717b..4c4974ee1fa8 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/CustomAssetDescriptor.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/CustomAssetDescriptor.kt @@ -1,10 +1,14 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.intellij.build +import org.jetbrains.intellij.build.impl.SupportedDistribution + internal interface CustomAssetDescriptor { /** Relative to plugin dir (not to plugin lib dir) */ val relativePath: String? get() = null - suspend fun getSources(context: BuildContext): Sequence? + val platformSpecific: SupportedDistribution? + + suspend fun getSources(context: BuildContext): Sequence? } \ No newline at end of file diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/Source.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/Source.kt index 9b6bae0e9bf1..edf2ad26ed9d 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/Source.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/Source.kt @@ -30,6 +30,31 @@ class LazySource( override fun toString(): String = "LazySource(name=$name, precomputedHash=$precomputedHash)" } +data class UnpackedZipSource( + @JvmField val file: Path, + override val filter: ((String) -> Boolean), +) : Source, Comparable { + override fun compareTo(other: ZipSource): Int { + return if (isWindows) file.toString().compareTo(other.file.toString()) else file.compareTo(other.file) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is ZipSource) return false + + if (file != other.file) return false + if (filter != other.filter) return false + + return true + } + + override fun hashCode(): Int { + var result = file.hashCode() + result = 31 * result + filter.hashCode() + return result + } +} + data class ZipSource( @JvmField val file: Path, @JvmField val isPreSignedAndExtractedCandidate: Boolean = false, diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/SourceAndCacheStrategy.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/SourceAndCacheStrategy.kt index 11e0e620c49f..378eaf7ea210 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/SourceAndCacheStrategy.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/SourceAndCacheStrategy.kt @@ -46,6 +46,7 @@ internal fun createSourceAndCacheStrategyList(sources: Collection, produ } } is LazySource -> LazySourceAndCacheStrategy(source) + is UnpackedZipSource -> throw UnsupportedOperationException("UnpackedZipSource is expected to be wrapped into LazySourceAndCacheStrategy") } } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt index d3785f77602b..dfbbf619e967 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope @@ -37,7 +36,6 @@ import org.jetbrains.intellij.build.LinuxDistributionCustomizer import org.jetbrains.intellij.build.MacDistributionCustomizer import org.jetbrains.intellij.build.OsFamily import org.jetbrains.intellij.build.PluginBuildDescriptor -import org.jetbrains.intellij.build.PluginBundlingRestrictions import org.jetbrains.intellij.build.ProductProperties import org.jetbrains.intellij.build.ProprietaryBuildTools import org.jetbrains.intellij.build.ScrambleTool @@ -54,23 +52,19 @@ import org.jetbrains.intellij.build.impl.CompilationContextImpl import org.jetbrains.intellij.build.impl.ModuleOutputPatcher import org.jetbrains.intellij.build.impl.PLUGIN_CLASSPATH import org.jetbrains.intellij.build.impl.PlatformLayout -import org.jetbrains.intellij.build.impl.PluginLayout import org.jetbrains.intellij.build.impl.asArchivedIfNeeded import org.jetbrains.intellij.build.impl.collectIncludedPluginModules import org.jetbrains.intellij.build.impl.collectPlatformModules -import org.jetbrains.intellij.build.impl.copyAdditionalPlugins import org.jetbrains.intellij.build.impl.copyDistFiles import org.jetbrains.intellij.build.impl.createIdeaPropertyFile import org.jetbrains.intellij.build.impl.createPlatformLayout import org.jetbrains.intellij.build.impl.generateRuntimeModuleRepositoryForDevBuild import org.jetbrains.intellij.build.impl.getOsDistributionBuilder -import org.jetbrains.intellij.build.impl.getPluginLayoutsByJpsModuleNames import org.jetbrains.intellij.build.impl.getToolModules import org.jetbrains.intellij.build.impl.layoutPlatformDistribution import org.jetbrains.intellij.build.impl.productInfo.PRODUCT_INFO_FILE_NAME import org.jetbrains.intellij.build.impl.projectStructureMapping.DistributionFileEntry import org.jetbrains.intellij.build.impl.projectStructureMapping.ModuleOutputEntry -import org.jetbrains.intellij.build.impl.satisfiesBundlingRequirements import org.jetbrains.intellij.build.jarCache.LocalDiskJarCacheManager import org.jetbrains.intellij.build.postData import org.jetbrains.intellij.build.readSearchableOptionIndex @@ -421,34 +415,6 @@ private suspend fun computeIdeFingerprint( Span.current().addEvent("IDE fingerprint: $fingerprint") } -private suspend fun buildPlugins( - request: BuildRequest, - context: BuildContext, - runDir: Path, - platformLayout: Deferred, - artifactTask: Job, - searchableOptionSet: SearchableOptionSetDescriptor?, - buildPlatformJob: Job, - moduleOutputPatcher: ModuleOutputPatcher, -): Pair>>, List>>?> { - val bundledMainModuleNames = getBundledMainModuleNames(context, request.additionalModules) - - val pluginRootDir = runDir.resolve("plugins") - - val plugins = getPluginLayoutsByJpsModuleNames(bundledMainModuleNames, context.productProperties.productLayout) - .filter { isPluginApplicable(bundledMainModuleNames, plugin = it, context) } - - withContext(Dispatchers.IO) { - Files.createDirectories(pluginRootDir) - } - - artifactTask.join() - - val pluginEntries = buildPlugins(plugins, platformLayout.await(), searchableOptionSet, context, pluginRootDir, buildPlatformJob, moduleOutputPatcher) - val additionalPlugins = copyAdditionalPlugins(context, pluginRootDir) - return pluginEntries to additionalPlugins -} - private suspend fun createBuildContext( createProductProperties: suspend (CompilationContext) -> ProductProperties, request: BuildRequest, @@ -458,8 +424,8 @@ private suspend fun createBuildContext( ): BuildContext { return coroutineScope { val buildOptionsTemplate = request.buildOptionsTemplate - val useCompiledClassesFromProjectOutput = - buildOptionsTemplate == null || (buildOptionsTemplate.useCompiledClassesFromProjectOutput && buildOptionsTemplate.unpackCompiledClassesArchives) + val useCompiledClassesFromProjectOutput = buildOptionsTemplate == null || + (buildOptionsTemplate.useCompiledClassesFromProjectOutput && buildOptionsTemplate.unpackCompiledClassesArchives) val classOutDir = if (useCompiledClassesFromProjectOutput) { request.productionClassOutput.parent } @@ -572,19 +538,6 @@ private suspend fun createBuildContext( } } -private fun isPluginApplicable(bundledMainModuleNames: Set, plugin: PluginLayout, context: BuildContext): Boolean { - if (!bundledMainModuleNames.contains(plugin.mainModule)) { - return false - } - - if (plugin.bundlingRestrictions == PluginBundlingRestrictions.NONE) { - return true - } - - return satisfiesBundlingRequirements(plugin = plugin, osFamily = OsFamily.currentOs, arch = JvmArchitecture.currentJvmArch, context = context) || - satisfiesBundlingRequirements(plugin = plugin, osFamily = null, arch = JvmArchitecture.currentJvmArch, context = context) -} - internal suspend fun createProductProperties(productConfiguration: ProductConfiguration, compilationContext: CompilationContext, request: BuildRequest): ProductProperties { val classPathFiles = coroutineScope { getBuildModules(productConfiguration).map { async { compilationContext.getModuleOutputDir(compilationContext.findRequiredModule(it)) } }.toList() @@ -669,14 +622,6 @@ private suspend fun layoutPlatform( return entries to sortedClassPath } -private suspend fun getBundledMainModuleNames(context: BuildContext, additionalModules: List): Set { - val bundledPluginModules = context.getBundledPluginModules() - val result = LinkedHashSet(bundledPluginModules.size + additionalModules.size) - result.addAll(bundledPluginModules) - result.addAll(additionalModules) - return result -} - private fun computeAdditionalModulesFingerprint(additionalModules: List): String { if (additionalModules.isEmpty()) { return "" diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/PluginBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/PluginBuilder.kt index 50f7fcbe44ae..7a8463603957 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/PluginBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/PluginBuilder.kt @@ -1,38 +1,96 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. @file:Suppress("PrivatePropertyName", "LiftReturnOrAssignment") package org.jetbrains.intellij.build.dev import io.opentelemetry.api.common.AttributeKey +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.withContext import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.JvmArchitecture +import org.jetbrains.intellij.build.OsFamily import org.jetbrains.intellij.build.PluginBuildDescriptor +import org.jetbrains.intellij.build.PluginBundlingRestrictions import org.jetbrains.intellij.build.SearchableOptionSetDescriptor -import org.jetbrains.intellij.build.impl.* +import org.jetbrains.intellij.build.impl.DistributionBuilderState +import org.jetbrains.intellij.build.impl.ModuleOutputPatcher +import org.jetbrains.intellij.build.impl.PlatformLayout +import org.jetbrains.intellij.build.impl.PluginLayout +import org.jetbrains.intellij.build.impl.SupportedDistribution +import org.jetbrains.intellij.build.impl.buildPlugins +import org.jetbrains.intellij.build.impl.copyAdditionalPlugins +import org.jetbrains.intellij.build.impl.getPluginLayoutsByJpsModuleNames +import org.jetbrains.intellij.build.impl.handleCustomPlatformSpecificAssets import org.jetbrains.intellij.build.impl.projectStructureMapping.DistributionFileEntry +import org.jetbrains.intellij.build.impl.satisfiesBundlingRequirements import org.jetbrains.intellij.build.telemetry.TraceManager.spanBuilder import org.jetbrains.intellij.build.telemetry.use +import java.nio.file.Files import java.nio.file.Path internal suspend fun buildPlugins( - plugins: List, - platformLayout: PlatformLayout, - searchableOptionSet: SearchableOptionSetDescriptor?, + request: BuildRequest, context: BuildContext, - pluginRootDir: Path, + runDir: Path, + platformLayout: Deferred, + artifactTask: Job, + searchableOptionSet: SearchableOptionSetDescriptor?, buildPlatformJob: Job, moduleOutputPatcher: ModuleOutputPatcher, -): List>> { - return spanBuilder("build plugins").setAttribute(AttributeKey.longKey("count"), plugins.size.toLong()).use { +): Pair>>, List>>?> { + val bundledMainModuleNames = getBundledMainModuleNames(context, request.additionalModules) + + val pluginRootDir = runDir.resolve("plugins") + + val plugins = getPluginLayoutsByJpsModuleNames(bundledMainModuleNames, context.productProperties.productLayout) + .filter { isPluginApplicable(bundledMainModuleNames = bundledMainModuleNames, plugin = it, context = context) } + + withContext(Dispatchers.IO) { + Files.createDirectories(pluginRootDir) + } + + artifactTask.join() + + val platform = platformLayout.await() + val pluginEntries = spanBuilder("build plugins").setAttribute(AttributeKey.longKey("count"), plugins.size.toLong()).use { + val targetPlatform = SupportedDistribution(OsFamily.currentOs, JvmArchitecture.currentJvmArch) buildPlugins( moduleOutputPatcher = moduleOutputPatcher, plugins = plugins, targetDir = pluginRootDir, - state = DistributionBuilderState(platform = platformLayout, pluginsToPublish = emptySet(), context = context), + state = DistributionBuilderState(platform = platform, pluginsToPublish = emptySet(), context = context), context = context, buildPlatformJob = buildPlatformJob, searchableOptionSet = searchableOptionSet, os = null, + pluginBuilt = { layout, pluginDirOrFile -> + handleCustomPlatformSpecificAssets(layout = layout, targetPlatform = targetPlatform, context = context, pluginDir = pluginDirOrFile) + }, ) } + val additionalPlugins = copyAdditionalPlugins(context, pluginRootDir) + return pluginEntries to additionalPlugins +} + +private fun isPluginApplicable(bundledMainModuleNames: Set, plugin: PluginLayout, context: BuildContext): Boolean { + if (!bundledMainModuleNames.contains(plugin.mainModule)) { + return false + } + + if (plugin.bundlingRestrictions == PluginBundlingRestrictions.NONE) { + return true + } + + return satisfiesBundlingRequirements(plugin = plugin, osFamily = OsFamily.currentOs, arch = JvmArchitecture.currentJvmArch, context = context) || + satisfiesBundlingRequirements(plugin = plugin, osFamily = null, arch = JvmArchitecture.currentJvmArch, context = context) +} + +private suspend fun getBundledMainModuleNames(context: BuildContext, additionalModules: List): Set { + val bundledPluginModules = context.getBundledPluginModules() + val result = LinkedHashSet(bundledPluginModules.size + additionalModules.size) + result.addAll(bundledPluginModules) + result.addAll(additionalModules) + return result } \ No newline at end of file diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt index dca24416cc65..befa8e07b841 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt @@ -714,27 +714,6 @@ internal suspend fun buildPlugins( return entries } -private suspend fun buildPlatformSpecificPluginResources( - plugin: PluginLayout, - targetDirs: List>, - context: BuildContext, -) { - for ((dist, generators) in plugin.platformResourceGenerators) { - val targetPath = targetDirs.firstOrNull { it.first == dist }?.second ?: continue - val pluginDir = targetPath.resolve(plugin.directoryName) - val relativePluginDir = context.paths.buildOutputDir.relativize(pluginDir).toString() - for (generator in generators) { - spanBuilder("plugin platform-specific resources") - .setAttribute("path", relativePluginDir) - .setAttribute("os", dist.os.toString()) - .setAttribute("arch", dist.arch.toString()) - .use { - generator(pluginDir, context) - } - } - } -} - private const val PLUGINS_DIRECTORY = "plugins" private const val LIB_DIRECTORY = "lib" diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/JarPackager.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/JarPackager.kt index 0064f73841da..5b5bc54d4b49 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/JarPackager.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/JarPackager.kt @@ -364,6 +364,10 @@ class JarPackager private constructor( private suspend fun handleCustomAssets(layout: PluginLayout, jarAsset: Lazy) { for (customAsset in layout.customAssets) { + if (customAsset.platformSpecific != null) { + continue + } + val relativePath = customAsset.relativePath if (relativePath == null) { customAsset.getSources(context)?.let { jarAsset.value.sources.addAll(it) } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PluginLayout.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PluginLayout.kt index c1ca560eafa8..203de1dd3f6c 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PluginLayout.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/PluginLayout.kt @@ -20,7 +20,6 @@ import org.jetbrains.intellij.build.JvmArchitecture import org.jetbrains.intellij.build.LazySource import org.jetbrains.intellij.build.OsFamily import org.jetbrains.intellij.build.PluginBundlingRestrictions -import org.jetbrains.intellij.build.Source import org.jetbrains.intellij.build.io.copyDir import org.jetbrains.intellij.build.io.copyFileToDir import java.nio.file.FileSystemException @@ -105,7 +104,7 @@ class PluginLayout(val mainModule: String, @Internal @JvmField val auto: Boolean private set val hasPlatformSpecificResources: Boolean - get() = platformResourceGenerators.isNotEmpty() + get() = platformResourceGenerators.isNotEmpty() || customAssets.any { it.platformSpecific != null } fun getMainJarName(): String = mainJarName @@ -238,7 +237,21 @@ class PluginLayout(val mainModule: String, @Internal @JvmField val auto: Boolean fun withCustomAsset(lazySourceSupplier: (context: BuildContext) -> LazySource?) { layout.customAssets += object : CustomAssetDescriptor { - override suspend fun getSources(context: BuildContext): Sequence? { + override val platformSpecific: SupportedDistribution? + get() = null + + override suspend fun getSources(context: BuildContext): Sequence? { + return sequenceOf(lazySourceSupplier(context) ?: return null) + } + } + } + + fun withCustomAsset(platform: SupportedDistribution, lazySourceSupplier: (context: BuildContext) -> LazySource?) { + layout.customAssets += object : CustomAssetDescriptor { + override val platformSpecific: SupportedDistribution? + get() = platform + + override suspend fun getSources(context: BuildContext): Sequence? { return sequenceOf(lazySourceSupplier(context) ?: return null) } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/pluginPlatformSpecificResourcePackager.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/pluginPlatformSpecificResourcePackager.kt new file mode 100644 index 000000000000..d318016268d5 --- /dev/null +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/pluginPlatformSpecificResourcePackager.kt @@ -0,0 +1,87 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.intellij.build.impl + +import org.jetbrains.annotations.ApiStatus +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.UnpackedZipSource +import org.jetbrains.intellij.build.io.W_OVERWRITE +import org.jetbrains.intellij.build.io.ZipEntryProcessorResult +import org.jetbrains.intellij.build.io.readZipFile +import org.jetbrains.intellij.build.io.writeToFileChannelFully +import org.jetbrains.intellij.build.telemetry.TraceManager.spanBuilder +import org.jetbrains.intellij.build.telemetry.use +import java.nio.channels.FileChannel +import java.nio.file.Files +import java.nio.file.Path + +internal suspend fun buildPlatformSpecificPluginResources( + plugin: PluginLayout, + targetDirs: List>, + context: BuildContext, +) { + for ((dist, generators) in plugin.platformResourceGenerators) { + val targetPath = targetDirs.firstOrNull { it.first == dist }?.second ?: continue + val pluginDir = targetPath.resolve(plugin.directoryName) + val relativePluginDir = context.paths.buildOutputDir.relativize(pluginDir).toString() + for (generator in generators) { + spanBuilder("plugin platform-specific resources") + .setAttribute("path", relativePluginDir) + .setAttribute("os", dist.os.toString()) + .setAttribute("arch", dist.arch.toString()) + .use { + generator(pluginDir, context) + } + } + } + + for ((platform, pluginDir) in targetDirs) { + handleCustomPlatformSpecificAssets(layout = plugin, targetPlatform = platform, context = context, pluginDir = pluginDir) + } +} + +@ApiStatus.Internal +fun unpackTrustedZip( + source: UnpackedZipSource, + rootDir: Path, + createdParents: MutableSet, +) { + readZipFile(source.file) { name, dataProvider -> + if (!source.filter(name)) { + return@readZipFile ZipEntryProcessorResult.CONTINUE + } + + val file = rootDir.resolve(name) + val parent = file.parent + if (createdParents.add(parent)) { + Files.createDirectories(parent) + } + + val data = dataProvider() + FileChannel.open(file, W_OVERWRITE).use { + writeToFileChannelFully(channel = it, data = data) + } + ZipEntryProcessorResult.CONTINUE + } +} + +internal suspend fun handleCustomPlatformSpecificAssets(layout: PluginLayout, targetPlatform: SupportedDistribution, context: BuildContext, pluginDir: Path) { + for (customAsset in layout.customAssets) { + val platformSpecific = customAsset.platformSpecific ?: continue + if (platformSpecific != targetPlatform) { + continue + } + + val rootDir = customAsset.relativePath?.let { pluginDir.resolve(it) } ?: pluginDir + val lazySources = customAsset.getSources(context) ?: continue + val createdParents = HashSet() + for (lazySource in lazySources) { + for (source in lazySource.getSources()) { + require(source is UnpackedZipSource) { + "Only UnpackedZipSource is supported for custom plugin platform-specific assets, got $source for $customAsset" + } + + unpackTrustedZip(source = source, rootDir = rootDir, createdParents = createdParents) + } + } + } +} \ No newline at end of file diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/mergeJars.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/mergeJars.kt index e02ef703797b..8a7fcae1a435 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/mergeJars.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/mergeJars.kt @@ -184,6 +184,10 @@ private suspend fun writeSource( ) } } + + is UnpackedZipSource -> { + throw UnsupportedOperationException("UnpackedZipSource is not supported") + } } }