mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
require explicit approval of a diff for distribution content, bundle module libs into the same JAR where containing module is packaged
GitOrigin-RevId: b51bebde918ce5d89647badb3f00e5da40e837ae
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0f156b27f4
commit
53a8729ff0
@@ -354,6 +354,8 @@ internal class ZipArchiveOutputStream(private val channel: WritableByteChannel,
|
||||
buffer.putShort(0)
|
||||
}
|
||||
|
||||
internal fun getChannelPosition() = channelPosition
|
||||
|
||||
internal fun getChannelPositionAndAdd(increment: Int): Long {
|
||||
val p = channelPosition
|
||||
channelPosition += increment.toLong()
|
||||
|
||||
@@ -170,7 +170,7 @@ fun buildJar(targetFile: Path, sources: List<Source>, dryRun: Boolean = false) {
|
||||
}
|
||||
}
|
||||
|
||||
source.sizeConsumer?.accept((outChannel.position() - positionBefore).toInt())
|
||||
source.sizeConsumer?.accept((zipCreator.resultStream.getChannelPosition() - positionBefore).toInt())
|
||||
}
|
||||
packageIndexBuilder.writePackageIndex(zipCreator)
|
||||
}
|
||||
@@ -181,6 +181,8 @@ private fun getIgnoredNames(): Set<String> {
|
||||
val set = HashSet<String>()
|
||||
// compilation cache on TC
|
||||
set.add(".hash")
|
||||
@Suppress("SpellCheckingInspection")
|
||||
set.add(".gitattributes")
|
||||
set.add("pom.xml")
|
||||
set.add("about.html")
|
||||
set.add("module-info.class")
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.util.SystemProperties
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@CompileStatic
|
||||
final class BuildOptions {
|
||||
@@ -57,7 +58,7 @@ final class BuildOptions {
|
||||
public static final String BROKEN_PLUGINS_LIST_STEP = "broken_plugins_list"
|
||||
static final String PROVIDED_MODULES_LIST_STEP = "provided_modules_list"
|
||||
public static final String GENERATE_JAR_ORDER_STEP = "jar_order"
|
||||
static final String SOURCES_ARCHIVE_STEP = "sources_archive"
|
||||
public static final String SOURCES_ARCHIVE_STEP = "sources_archive"
|
||||
public static final String SCRAMBLING_STEP = "scramble"
|
||||
public static final String NON_BUNDLED_PLUGINS_STEP = "non_bundled_plugins"
|
||||
/** Build Maven artifacts for IDE modules. */
|
||||
@@ -88,6 +89,7 @@ final class BuildOptions {
|
||||
static final String COMMUNITY_DIST_STEP = "community_dist"
|
||||
public static final String PREBUILD_SHARED_INDEXES = "prebuild_shared_indexes"
|
||||
public static final String SETUP_BUNDLED_MAVEN = "setup_bundled_maven"
|
||||
public static final String VERIFY_CLASS_FILE_VERSIONS = "verify_class_file_versions"
|
||||
/**
|
||||
* Publish artifacts to TeamCity storage while the build is still running, immediately after the artifacts are built.
|
||||
* Comprises many small publication steps.
|
||||
@@ -244,6 +246,9 @@ final class BuildOptions {
|
||||
static final String VALIDATE_MODULES_STRUCTURE = "intellij.build.module.structure"
|
||||
boolean validateModuleStructure = System.getProperty(VALIDATE_MODULES_STRUCTURE, "false").toBoolean()
|
||||
|
||||
@ApiStatus.Internal
|
||||
public boolean compressNonBundledPluginArchive = true
|
||||
|
||||
/**
|
||||
* Max attempts of dependencies resolution on fault. "1" means no retries.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,8 @@ package org.jetbrains.intellij.build.impl
|
||||
import com.intellij.openapi.util.text.Strings
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import groovy.transform.CompileStatic
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
/**
|
||||
@@ -21,7 +23,8 @@ abstract class BaseLayout {
|
||||
final List<ModuleResourceData> resourcePaths = new ArrayList<>()
|
||||
/** module name to entries which should be excluded from its output */
|
||||
final MultiMap<String, String> moduleExcludes = MultiMap.createLinked()
|
||||
final Set<ProjectLibraryData> includedProjectLibraries = new LinkedHashSet<>()
|
||||
@ApiStatus.Internal
|
||||
public final ObjectLinkedOpenHashSet<ProjectLibraryData> includedProjectLibraries = new ObjectLinkedOpenHashSet<>()
|
||||
final Set<ModuleLibraryData> includedModuleLibraries = new LinkedHashSet<>()
|
||||
/** module name to name of the module library */
|
||||
final MultiMap<String, String> excludedModuleLibraries = MultiMap.createLinked()
|
||||
|
||||
+50
-40
@@ -191,22 +191,24 @@ final class BuildTasksImpl extends BuildTasks {
|
||||
/**
|
||||
* Build a list with modules that the IDE will provide for plugins.
|
||||
*/
|
||||
private static void buildProvidedModuleList(BuildContext buildContext, Path targetFile, @NotNull Collection<String> modules) {
|
||||
buildContext.executeStep(spanBuilder("build provided module list").setAttribute("size", modules.size()),
|
||||
BuildOptions.PROVIDED_MODULES_LIST_STEP, new Runnable() {
|
||||
@Override
|
||||
void run() {
|
||||
buildContext.messages.debug("Building provided module list for the following modules: $modules")
|
||||
Files.deleteIfExists(targetFile)
|
||||
// start the product in headless mode using com.intellij.ide.plugins.BundledPluginsLister
|
||||
BuildHelper.runApplicationStarter(buildContext, buildContext.paths.tempDir.resolve("builtinModules"), modules,
|
||||
List.of("listBundledPlugins", targetFile.toString()))
|
||||
if (Files.notExists(targetFile)) {
|
||||
buildContext.messages.error("Failed to build provided modules list: $targetFile doesn't exist")
|
||||
private static void buildProvidedModuleList(BuildContext context, Path targetFile, @NotNull Collection<String> modules) {
|
||||
context.executeStep(
|
||||
spanBuilder("build provided module list")
|
||||
.setAttribute(AttributeKey.stringArrayKey("modules"), List.copyOf(modules)),
|
||||
BuildOptions.PROVIDED_MODULES_LIST_STEP,
|
||||
new Runnable() {
|
||||
@Override
|
||||
void run() {
|
||||
Files.deleteIfExists(targetFile)
|
||||
// start the product in headless mode using com.intellij.ide.plugins.BundledPluginsLister
|
||||
BuildHelper.runApplicationStarter(context, context.paths.tempDir.resolve("builtinModules"), modules,
|
||||
List.of("listBundledPlugins", targetFile.toString()))
|
||||
if (Files.notExists(targetFile)) {
|
||||
context.messages.error("Failed to build provided modules list: $targetFile doesn't exist")
|
||||
}
|
||||
context.notifyArtifactWasBuilt(targetFile)
|
||||
}
|
||||
buildContext.notifyArtifactWasBuilt(targetFile)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private Path patchIdeaPropertiesFile() {
|
||||
@@ -310,8 +312,8 @@ idea.fatal.error.notification=disabled
|
||||
|
||||
@NotNull
|
||||
private static BuildTaskRunnable createDistributionForOsTask(@NotNull OsFamily os,
|
||||
@NotNull Map<OsFamily, Path> result,
|
||||
@NotNull Function<BuildContext, OsSpecificDistributionBuilder> factory) {
|
||||
@NotNull Map<OsFamily, Path> result,
|
||||
@NotNull Function<BuildContext, OsSpecificDistributionBuilder> factory) {
|
||||
return BuildTaskRunnable.task(os.osId, new Consumer<BuildContext>() {
|
||||
@Override
|
||||
void accept(BuildContext context) {
|
||||
@@ -340,36 +342,40 @@ idea.fatal.error.notification=disabled
|
||||
@Override
|
||||
void compileModulesFromProduct() {
|
||||
checkProductProperties()
|
||||
compileModulesForDistribution()
|
||||
compileModulesForDistribution(buildContext)
|
||||
}
|
||||
|
||||
private DistributionJARsBuilder compileModulesForDistribution() {
|
||||
ProductModulesLayout productLayout = buildContext.productProperties.productLayout
|
||||
Collection<String> moduleNames = DistributionJARsBuilder.getModulesToCompile(buildContext)
|
||||
MavenArtifactsProperties mavenArtifacts = buildContext.productProperties.mavenArtifacts
|
||||
private DistributionJARsBuilder compileModulesForDistribution(BuildContext context) {
|
||||
Set<PluginLayout> pluginsToPublish = DistributionJARsBuilder
|
||||
.getPluginsByModules(context, context.productProperties.productLayout.pluginModulesToPublish)
|
||||
compileModulesForDistribution(pluginsToPublish, context)
|
||||
}
|
||||
|
||||
private DistributionJARsBuilder compileModulesForDistribution(Set<PluginLayout> pluginsToPublish, BuildContext context) {
|
||||
ProductProperties productProperties = context.productProperties
|
||||
ProductModulesLayout productLayout = productProperties.productLayout
|
||||
Collection<String> moduleNames = DistributionJARsBuilder.getModulesToCompile(context)
|
||||
MavenArtifactsProperties mavenArtifacts = productProperties.mavenArtifacts
|
||||
|
||||
Set<String> toCompile = new LinkedHashSet<>()
|
||||
toCompile.addAll(moduleNames)
|
||||
toCompile.addAll(buildContext.proprietaryBuildTools.scrambleTool?.additionalModulesToCompile ?: Collections.<String>emptyList())
|
||||
toCompile.addAll(context.proprietaryBuildTools.scrambleTool?.additionalModulesToCompile ?: Collections.<String>emptyList())
|
||||
toCompile.addAll(productLayout.mainModules)
|
||||
toCompile.addAll(mavenArtifacts.additionalModules)
|
||||
toCompile.addAll(mavenArtifacts.proprietaryModules)
|
||||
toCompile.addAll(buildContext.productProperties.modulesToCompileTests)
|
||||
toCompile.addAll(productProperties.modulesToCompileTests)
|
||||
compileModules(toCompile)
|
||||
|
||||
def pluginsToPublish = new LinkedHashSet<>(
|
||||
DistributionJARsBuilder.getPluginsByModules(buildContext, buildContext.productProperties.productLayout.pluginModulesToPublish))
|
||||
|
||||
if (buildContext.shouldBuildDistributions()) {
|
||||
Path providedModulesFile = buildContext.paths.artifactDir.resolve("${buildContext.applicationInfo.productCode}-builtinModules.json")
|
||||
buildProvidedModuleList(buildContext, providedModulesFile, moduleNames)
|
||||
if (buildContext.productProperties.productLayout.buildAllCompatiblePlugins) {
|
||||
if (!buildContext.options.buildStepsToSkip.contains(BuildOptions.PROVIDED_MODULES_LIST_STEP)) {
|
||||
PluginsCollector collector = new PluginsCollector(buildContext)
|
||||
pluginsToPublish.addAll(collector.collectCompatiblePluginsToPublish(providedModulesFile.toString()))
|
||||
if (context.shouldBuildDistributions()) {
|
||||
Path providedModulesFile = context.paths.artifactDir.resolve("${context.applicationInfo.productCode}-builtinModules.json")
|
||||
buildProvidedModuleList(context, providedModulesFile, moduleNames)
|
||||
if (productProperties.productLayout.buildAllCompatiblePlugins) {
|
||||
if (context.options.buildStepsToSkip.contains(BuildOptions.PROVIDED_MODULES_LIST_STEP)) {
|
||||
context.messages.info("Skipping collecting compatible plugins because PROVIDED_MODULES_LIST_STEP was skipped")
|
||||
}
|
||||
else {
|
||||
buildContext.messages.info("Skipping collecting compatible plugins because PROVIDED_MODULES_LIST_STEP was skipped")
|
||||
pluginsToPublish = new LinkedHashSet<>(pluginsToPublish)
|
||||
pluginsToPublish.addAll(PluginsCollector.collectCompatiblePluginsToPublish(providedModulesFile, context))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,7 +420,11 @@ idea.fatal.error.notification=disabled
|
||||
setupBundledMaven()
|
||||
|
||||
logFreeDiskSpace("before compilation")
|
||||
DistributionJARsBuilder distributionJARsBuilder = compileModulesForDistribution()
|
||||
|
||||
Set<PluginLayout> pluginsToPublish = DistributionJARsBuilder
|
||||
.getPluginsByModules(context, context.productProperties.productLayout.pluginModulesToPublish)
|
||||
|
||||
DistributionJARsBuilder distributionJARsBuilder = compileModulesForDistribution(buildContext)
|
||||
logFreeDiskSpace("after compilation")
|
||||
|
||||
ForkJoinTask<?> setupJetBrainsRuntimeTask = context.shouldBuildDistributions() ? createSetupJbreTask()?.fork() : null
|
||||
@@ -453,7 +463,7 @@ idea.fatal.error.notification=disabled
|
||||
Span.current().addEvent("skip building product distributions because " +
|
||||
"\"intellij.build.target.os\" property is set to \"$BuildOptions.OS_NONE\"")
|
||||
DistributionJARsBuilder.buildSearchableOptions(context, distributionJARsBuilder.getModulesForPluginsToPublish())
|
||||
distributionJARsBuilder.createBuildNonBundledPluginsTask(true, null, context)?.fork()?.join()
|
||||
distributionJARsBuilder.createBuildNonBundledPluginsTask(pluginsToPublish, true, null, context)?.fork()?.join()
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -550,7 +560,7 @@ idea.fatal.error.notification=disabled
|
||||
Set<PluginLayout> pluginsToPublish = DistributionJARsBuilder.getPluginsByModules(buildContext, mainPluginModules)
|
||||
DistributionJARsBuilder distributionJARsBuilder = compilePlatformAndPluginModules(pluginsToPublish)
|
||||
DistributionJARsBuilder.buildSearchableOptions(buildContext, distributionJARsBuilder.getModulesForPluginsToPublish())
|
||||
distributionJARsBuilder.createBuildNonBundledPluginsTask(true, null, buildContext)?.fork()?.join()
|
||||
distributionJARsBuilder.createBuildNonBundledPluginsTask(pluginsToPublish, true, null, buildContext)?.fork()?.join()
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -964,7 +974,7 @@ idea.fatal.error.notification=disabled
|
||||
void runTestBuild() {
|
||||
checkProductProperties()
|
||||
setupBundledMaven()
|
||||
DistributionJARsBuilder distributionJARsBuilder = compileModulesForDistribution()
|
||||
DistributionJARsBuilder distributionJARsBuilder = compileModulesForDistribution(buildContext)
|
||||
distributionJARsBuilder.buildJARs(buildContext)
|
||||
layoutShared(buildContext)
|
||||
Map<String, String> checkerConfig = buildContext.productProperties.versionCheckerConfig
|
||||
@@ -987,7 +997,7 @@ idea.fatal.error.notification=disabled
|
||||
buildContext.options.buildStepsToSkip.add(BuildOptions.GENERATE_JAR_ORDER_STEP)
|
||||
|
||||
setupBundledMaven()
|
||||
compileModulesForDistribution().buildJARs(buildContext, true)
|
||||
compileModulesForDistribution(buildContext).buildJARs(buildContext, true)
|
||||
JvmArchitecture arch = CpuArch.isArm64() ? JvmArchitecture.aarch64 : JvmArchitecture.x64
|
||||
if (includeBinAndRuntime) {
|
||||
createSetupJbreTask(arch.name()).fork().join()
|
||||
|
||||
+10
-8
@@ -10,6 +10,7 @@ import org.apache.commons.compress.archivers.zip.ZipFile
|
||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.BuildOptions
|
||||
|
||||
import java.nio.file.DirectoryStream
|
||||
import java.nio.file.Files
|
||||
@@ -17,9 +18,7 @@ import java.nio.file.Path
|
||||
import java.nio.file.StandardOpenOption
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.ForkJoinTask
|
||||
import java.util.function.Supplier
|
||||
import java.util.zip.ZipException
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Recursively checks .class files in directories and .jar/.zip files to ensure that their versions
|
||||
@@ -62,11 +61,15 @@ final class ClassVersionChecker {
|
||||
}
|
||||
|
||||
void checkVersions(BuildContext context, Path root) {
|
||||
context.messages.block(TracerManager.spanBuilder("verify class file versions")
|
||||
.setAttribute("ruleCount", myRules.size())
|
||||
.setAttribute("root", root.toString()), new Supplier<Void>() {
|
||||
if (context.options.buildStepsToSkip.contains(BuildOptions.VERIFY_CLASS_FILE_VERSIONS)) {
|
||||
return
|
||||
}
|
||||
|
||||
BuildHelper.getInstance(context).span(TracerManager.spanBuilder("verify class file versions")
|
||||
.setAttribute("ruleCount", myRules.size())
|
||||
.setAttribute("root", root.toString()), new Runnable() {
|
||||
@Override
|
||||
Void get() {
|
||||
void run() {
|
||||
checkedJarCount = 0
|
||||
checkedClassCount = 0
|
||||
errors = new ConcurrentLinkedQueue<>()
|
||||
@@ -96,9 +99,8 @@ final class ClassVersionChecker {
|
||||
List<Rule> unusedRules = myRules - myUsedRules
|
||||
if (!unusedRules.isEmpty()) {
|
||||
context.messages.error("Class version check rules for the following paths don't match any files, probably entries in " +
|
||||
"ProductProperties::versionCheckerConfig are out of date:\n${String.join("\n", unusedRules.collect { it.path })}")
|
||||
"ProductProperties::versionCheckerConfig are out of date:\n${String.join("\n", unusedRules.collect { it.path })}")
|
||||
}
|
||||
return null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+218
-165
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 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 com.intellij.openapi.util.Pair
|
||||
@@ -14,6 +14,7 @@ import io.opentelemetry.api.common.Attributes
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import it.unimi.dsi.fastutil.Hash
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenCustomHashSet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
||||
import kotlin.Triple
|
||||
import org.apache.tools.ant.types.FileSet
|
||||
import org.apache.tools.ant.types.resources.FileProvider
|
||||
@@ -76,106 +77,151 @@ final class DistributionJARsBuilder {
|
||||
String releaseVersion = "${context.applicationInfo.majorVersion}${context.applicationInfo.minorVersionMainPart}00"
|
||||
pluginXmlPatcher = new PluginXmlPatcher(releaseDate, releaseVersion)
|
||||
|
||||
platform = createPlatformLayout(pluginsToPublish, context)
|
||||
platform = createPlatformLayout(this.pluginsToPublish, context)
|
||||
}
|
||||
|
||||
static PlatformLayout createPlatformLayout(Set<PluginLayout> pluginsToPublish, BuildContext context) {
|
||||
ProductModulesLayout productLayout = context.productProperties.productLayout
|
||||
Set<String> enabledPluginModules = getEnabledPluginModules(pluginsToPublish, context.productProperties)
|
||||
Set<JpsLibrary> projectLibrariesUsedByPlugins = computeProjectLibsUsedByPlugins(context, enabledPluginModules)
|
||||
Set<ProjectLibraryData> projectLibrariesUsedByPlugins = computeProjectLibsUsedByPlugins(context, enabledPluginModules)
|
||||
return PlatformModules.createPlatformLayout(productLayout,
|
||||
hasPlatformCoverage(productLayout, enabledPluginModules, context),
|
||||
projectLibrariesUsedByPlugins,
|
||||
context)
|
||||
}
|
||||
|
||||
private static boolean hasPlatformCoverage(ProductModulesLayout productLayout,
|
||||
Set<String> enabledPluginModules,
|
||||
BuildContext context) {
|
||||
return Stream.concat(productLayout.getIncludedPluginModules(enabledPluginModules).stream(),
|
||||
productLayout.getIncludedPluginModules(enabledPluginModules).stream())
|
||||
.flatMap(new Function<String, Stream<? extends String>>() {
|
||||
@Override
|
||||
Stream<? extends String> apply(String moduleName) {
|
||||
return JpsJavaExtensionService.dependencies(context.findRequiredModule(moduleName))
|
||||
.productionOnly()
|
||||
.getModules()
|
||||
.stream()
|
||||
.map(new Function<JpsModule, String>() {
|
||||
@Override
|
||||
String apply(JpsModule module) {
|
||||
return module.name
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.filter(Predicate.isEqual("intellij.platform.coverage"))
|
||||
.findAny()
|
||||
.isPresent()
|
||||
private static boolean hasPlatformCoverage(ProductModulesLayout productLayout, Set<String> enabledPluginModules, BuildContext context) {
|
||||
Set<String> modules = new LinkedHashSet<>()
|
||||
modules.addAll(productLayout.getIncludedPluginModules(enabledPluginModules))
|
||||
modules.addAll(PlatformModules.PLATFORM_API_MODULES)
|
||||
modules.addAll(PlatformModules.PLATFORM_IMPLEMENTATION_MODULES)
|
||||
modules.addAll(productLayout.productApiModules)
|
||||
modules.addAll(productLayout.productImplementationModules)
|
||||
modules.addAll(productLayout.additionalPlatformJars.values())
|
||||
|
||||
String coverageModuleName = "intellij.platform.coverage"
|
||||
if (modules.contains(coverageModuleName)) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (String moduleName : modules) {
|
||||
boolean contains = false
|
||||
JpsJavaExtensionService.dependencies(context.findRequiredModule(moduleName))
|
||||
.productionOnly()
|
||||
.processModules(new com.intellij.util.Consumer<JpsModule>() {
|
||||
@Override
|
||||
void consume(JpsModule module) {
|
||||
if (!contains && module.name == coverageModuleName) {
|
||||
contains = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (contains) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private static Set<JpsLibrary> computeProjectLibsUsedByPlugins(BuildContext context, Set<String> enabledPluginModules) {
|
||||
context.messages.debug("Collecting project libraries used by plugins:")
|
||||
private static Set<ProjectLibraryData> computeProjectLibsUsedByPlugins(BuildContext context, Set<String> enabledPluginModules) {
|
||||
ObjectLinkedOpenHashSet<ProjectLibraryData> result = new ObjectLinkedOpenHashSet<>()
|
||||
|
||||
Collection<JpsLibrary> result = new LinkedHashSet<>()
|
||||
MultiMap<JpsLibrary, JpsModule> libraries = MultiMap.createLinked()
|
||||
for (PluginLayout plugin : getPluginsByModules(context, enabledPluginModules)) {
|
||||
libraries.clear()
|
||||
collectProjectLibrariesWhichShouldBeProvidedByPlatform(plugin, libraries, context)
|
||||
for (Map.Entry<JpsLibrary, Collection<JpsModule>> entry in libraries.entrySet()) {
|
||||
context.messages.debug("plugin '$plugin.mainModule', library '$entry.key.name': " +
|
||||
"used in ${String.join(", ", entry.value.collect { "'$it.name'" })}")
|
||||
Collection<String> libsToUnpack = plugin.projectLibrariesToUnpack.values()
|
||||
for (String moduleName in plugin.includedModuleNames) {
|
||||
JpsJavaDependenciesEnumerator dependencies = JpsJavaExtensionService.dependencies(context.findRequiredModule(moduleName))
|
||||
dependencies.includedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME).processLibraries(new com.intellij.util.Consumer<JpsLibrary>() {
|
||||
@Override
|
||||
void consume(JpsLibrary library) {
|
||||
if (!isProjectLibraryUsedByPlugin(library, plugin, libsToUnpack)) {
|
||||
return
|
||||
}
|
||||
|
||||
String name = library.name
|
||||
ProjectLibraryData.PackMode packMode = PlatformModules.CUSTOM_PACK_MODE.getOrDefault(name, ProjectLibraryData.PackMode.MERGED)
|
||||
result.addOrGet(new ProjectLibraryData(name, "", packMode))
|
||||
.dependentModules.computeIfAbsent(Objects.requireNonNull(plugin.directoryName), PlatformModules.LIST_PRODUCER).add(moduleName)
|
||||
}
|
||||
})
|
||||
}
|
||||
result.addAll(libraries.keySet())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static MultiMap<JpsLibrary, JpsModule> collectProjectLibrariesWhichShouldBeProvidedByPlatform(BaseLayout plugin,
|
||||
MultiMap<JpsLibrary, JpsModule> result,
|
||||
BuildContext buildContext) {
|
||||
private static boolean isProjectLibraryUsedByPlugin(JpsLibrary library, BaseLayout plugin, Collection<String> libsToUnpack) {
|
||||
return !(library.createReference().parentReference instanceof JpsModuleReference) &&
|
||||
!plugin.includedProjectLibraries.any {it.libraryName == library.name} &&
|
||||
!libsToUnpack.contains(library.name)
|
||||
}
|
||||
|
||||
static void collectProjectLibrariesWhichShouldBeProvidedByPlatform(BaseLayout plugin,
|
||||
MultiMap<JpsLibrary, JpsModule> result,
|
||||
BuildContext context) {
|
||||
Collection<String> libsToUnpack = plugin.projectLibrariesToUnpack.values()
|
||||
for (String moduleName in plugin.includedModuleNames) {
|
||||
JpsModule module = buildContext.findRequiredModule(moduleName)
|
||||
JpsModule module = context.findRequiredModule(moduleName)
|
||||
JpsJavaDependenciesEnumerator dependencies = JpsJavaExtensionService.dependencies(module)
|
||||
for (JpsLibrary library : dependencies.includedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME).libraries) {
|
||||
if (!(library.createReference().parentReference instanceof JpsModuleReference) && !plugin.includedProjectLibraries.any {
|
||||
it.libraryName == library.name
|
||||
} && !libsToUnpack.contains(library.name)) {
|
||||
if (isProjectLibraryUsedByPlugin(library, plugin, libsToUnpack)) {
|
||||
result.putValue(library, module)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private static @NotNull Set<PluginLayout> filterPluginsToPublish(@NotNull Set<PluginLayout> plugins, @NotNull BuildContext context) {
|
||||
plugins = plugins.stream().filter {
|
||||
if (plugins.isEmpty()) {
|
||||
return plugins
|
||||
}
|
||||
|
||||
Set<PluginLayout> result = plugins
|
||||
for (PluginLayout plugin : plugins) {
|
||||
// Kotlin Multiplatform Mobile plugin is excluded since:
|
||||
// * is compatible with Android Studio only;
|
||||
// * has release cycle of its
|
||||
// * shadows IntelliJ utility modules included via Kotlin Compiler;
|
||||
// * breaks searchable options index and jar order generation steps.
|
||||
it.mainModule != 'kotlin-ultimate.kmm-plugin'
|
||||
}.collect(Collectors.toSet())
|
||||
if (plugins.isEmpty()) {
|
||||
return plugins
|
||||
if (plugin.mainModule == "kotlin-ultimate.kmm-plugin") {
|
||||
if (result.is(plugins)) {
|
||||
result = new LinkedHashSet<>(plugins)
|
||||
}
|
||||
result.remove(plugin)
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptySet()
|
||||
}
|
||||
|
||||
Set<String> toInclude = new HashSet<>(context.options.nonBundledPluginDirectoriesToInclude)
|
||||
if (toInclude.isEmpty()) {
|
||||
return plugins
|
||||
return result
|
||||
}
|
||||
|
||||
if (toInclude.size() == 1 && toInclude.contains("none")) {
|
||||
return new LinkedHashSet<PluginLayout>()
|
||||
return Collections.emptySet()
|
||||
}
|
||||
return plugins.findAll { toInclude.contains(it.directoryName) }
|
||||
|
||||
Iterator<PluginLayout> iterator = result.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
PluginLayout plugin = iterator.next()
|
||||
if (!toInclude.contains(plugin.directoryName)) {
|
||||
if (result.is(plugins)) {
|
||||
result = new LinkedHashSet<>(plugins)
|
||||
}
|
||||
result.remove(plugin)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private static Set<String> getEnabledPluginModules(Set<PluginLayout> pluginsToPublish, ProductProperties productProperties) {
|
||||
Set<String> result = new LinkedHashSet<>()
|
||||
result.addAll(productProperties.productLayout.bundledPluginModules)
|
||||
pluginsToPublish.collect(result) { it.mainModule }
|
||||
for (PluginLayout plugin : pluginsToPublish) {
|
||||
result.add(plugin.mainModule)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -183,11 +229,6 @@ final class DistributionJARsBuilder {
|
||||
return (platform.includedModuleNames as List<String>) + toolModules
|
||||
}
|
||||
|
||||
static List<String> getIncludedPlatformModules(ProductModulesLayout modulesLayout) {
|
||||
return PlatformModules.PLATFORM_API_MODULES + PlatformModules.PLATFORM_IMPLEMENTATION_MODULES + modulesLayout.productApiModules +
|
||||
modulesLayout.productImplementationModules + modulesLayout.additionalPlatformJars.values()
|
||||
}
|
||||
|
||||
/**
|
||||
* @return module names which are required to run necessary tools from build scripts
|
||||
*/
|
||||
@@ -212,9 +253,7 @@ final class DistributionJARsBuilder {
|
||||
ForkJoinTask<?> brokenPluginsTask = createBuildBrokenPluginListTask(context)?.fork()
|
||||
|
||||
BuildHelper buildHelper = BuildHelper.getInstance(context)
|
||||
buildHelper.createSkippableTask(spanBuilder("build searchable options index"),
|
||||
BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP,
|
||||
context) {
|
||||
buildHelper.createSkippableTask(spanBuilder("build searchable options index"), BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP, context) {
|
||||
buildSearchableOptions(context, getModulesForPluginsToPublish())
|
||||
}?.fork()?.join()
|
||||
|
||||
@@ -262,7 +301,10 @@ final class DistributionJARsBuilder {
|
||||
buildPlatformTask,
|
||||
createBuildBundledPluginTask(pluginLayouts, buildPlatformTask, context),
|
||||
createBuildOsSpecificBundledPluginsTask(pluginLayouts, isUpdateFromSources, buildPlatformTask, context),
|
||||
createBuildNonBundledPluginsTask(!isUpdateFromSources, buildPlatformTask, context),
|
||||
createBuildNonBundledPluginsTask(pluginsToPublish,
|
||||
!isUpdateFromSources && context.options.compressNonBundledPluginArchive,
|
||||
buildPlatformTask,
|
||||
context),
|
||||
ForkJoinTask.adapt(new Callable<List<DistributionFileEntry>>() {
|
||||
@Override
|
||||
List<DistributionFileEntry> call() throws Exception {
|
||||
@@ -386,7 +428,7 @@ final class DistributionJARsBuilder {
|
||||
BuildHelper helper = BuildHelper.getInstance(context)
|
||||
return helper.createSkippableTask(
|
||||
spanBuilder("build broken plugin list")
|
||||
.setAttribute("buildString", buildString)
|
||||
.setAttribute("buildNumber", buildString)
|
||||
.setAttribute("path", targetFile.toString()),
|
||||
BuildOptions.BROKEN_PLUGINS_LIST_STEP,
|
||||
context,
|
||||
@@ -637,7 +679,7 @@ final class DistributionJARsBuilder {
|
||||
}
|
||||
Span.current().setAttribute("satisfiableCount", pluginsToBundle.size())
|
||||
return buildPlugins(new ModuleOutputPatcher(), pluginsToBundle,
|
||||
context.paths.distAllDir.resolve(PLUGINS_DIRECTORY), context, buildPlatformTask, null, false)
|
||||
context.paths.distAllDir.resolve(PLUGINS_DIRECTORY), context, buildPlatformTask, null)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -687,7 +729,7 @@ final class DistributionJARsBuilder {
|
||||
.setAttribute("outDir", outDir.toString()), new Supplier<List<DistributionFileEntry>>() {
|
||||
@Override
|
||||
List<DistributionFileEntry> get() {
|
||||
return buildPlugins(new ModuleOutputPatcher(), osSpecificPlugins, outDir, context, buildPlatformTask, null, true)
|
||||
return buildPlugins(new ModuleOutputPatcher(), osSpecificPlugins, outDir, context, buildPlatformTask, null)
|
||||
}
|
||||
})
|
||||
}).collectMany { it.rawResult }
|
||||
@@ -744,86 +786,103 @@ final class DistributionJARsBuilder {
|
||||
|
||||
// compressPluginArchive also means that blockmap for plugin archive will be built
|
||||
@Nullable
|
||||
ForkJoinTask<?> createBuildNonBundledPluginsTask(boolean compressPluginArchive,
|
||||
@Nullable ForkJoinTask<?> buildPlatformLibTask,
|
||||
@NotNull BuildContext context) {
|
||||
ForkJoinTask<List<DistributionFileEntry>> createBuildNonBundledPluginsTask(@NotNull Set<PluginLayout> pluginsToPublish,
|
||||
boolean compressPluginArchive,
|
||||
@Nullable ForkJoinTask<?> buildPlatformLibTask,
|
||||
@NotNull BuildContext context) {
|
||||
if (pluginsToPublish.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
return BuildHelper.getInstance(context).createSkippableTask(spanBuilder("build non-bundled plugins")
|
||||
.setAttribute("count", pluginsToPublish.size()),
|
||||
BuildOptions.NON_BUNDLED_PLUGINS_STEP,
|
||||
context, new Runnable() {
|
||||
@Override
|
||||
void run() {
|
||||
Path nonBundledPluginsArtifacts = context.paths.artifactDir.resolve(context.applicationInfo.productCode + "-plugins")
|
||||
Path autoUploadingDir = nonBundledPluginsArtifacts.resolve("auto-uploading")
|
||||
return BuildHelper.getInstance(context).createTask(
|
||||
spanBuilder("build non-bundled plugins").setAttribute("count", pluginsToPublish.size()),
|
||||
new Supplier<List<DistributionFileEntry>>() {
|
||||
@Override
|
||||
List<DistributionFileEntry> get() {
|
||||
if (context.options.buildStepsToSkip.contains(BuildOptions.NON_BUNDLED_PLUGINS_STEP)) {
|
||||
Span.current().addEvent("skip")
|
||||
return Collections.emptyList()
|
||||
}
|
||||
|
||||
ForkJoinTask<List<kotlin.Pair<Path, byte[]>>> buildKeymapPluginsTask = buildKeymapPlugins(autoUploadingDir, context).fork()
|
||||
Path nonBundledPluginsArtifacts = context.paths.artifactDir.resolve(context.applicationInfo.productCode + "-plugins")
|
||||
Path autoUploadingDir = nonBundledPluginsArtifacts.resolve("auto-uploading")
|
||||
|
||||
ModuleOutputPatcher moduleOutputPatcher = new ModuleOutputPatcher()
|
||||
Path stageDir = context.paths.tempDir.resolve("non-bundled-plugins-" + context.applicationInfo.productCode)
|
||||
ForkJoinTask<List<kotlin.Pair<Path, byte[]>>> buildKeymapPluginsTask = buildKeymapPlugins(autoUploadingDir, context).fork()
|
||||
|
||||
List<Map.Entry<String, Path>> dirToJar = new ArrayList<>()
|
||||
ModuleOutputPatcher moduleOutputPatcher = new ModuleOutputPatcher()
|
||||
Path stageDir = context.paths.tempDir.resolve("non-bundled-plugins-" + context.applicationInfo.productCode)
|
||||
|
||||
String defaultPluginVersion = context.buildNumber.endsWith(".SNAPSHOT")
|
||||
? context.buildNumber + ".${PluginXmlPatcher.pluginDateFormat.format(ZonedDateTime.now())}"
|
||||
: context.buildNumber
|
||||
List<Map.Entry<String, Path>> dirToJar = new ArrayList<>()
|
||||
|
||||
List<PluginRepositorySpec> pluginsToIncludeInCustomRepository = new ArrayList<PluginRepositorySpec>()
|
||||
Predicate<PluginLayout> autoPublishPluginChecker = loadPluginAutoPublishList(context)
|
||||
String defaultPluginVersion = context.buildNumber.endsWith(".SNAPSHOT")
|
||||
? context.buildNumber + ".${PluginXmlPatcher.pluginDateFormat.format(ZonedDateTime.now())}"
|
||||
: context.buildNumber
|
||||
|
||||
boolean prepareCustomPluginRepositoryForPublishedPlugins = context.productProperties.productLayout
|
||||
.prepareCustomPluginRepositoryForPublishedPlugins
|
||||
buildPlugins(moduleOutputPatcher, pluginsToPublish, stageDir, context, buildPlatformLibTask, new BiConsumer<PluginLayout, Path>() {
|
||||
@Override
|
||||
void accept(PluginLayout plugin, Path pluginDir) {
|
||||
Path targetDirectory = autoPublishPluginChecker.test(plugin) ? autoUploadingDir : nonBundledPluginsArtifacts
|
||||
String pluginDirName = pluginDir.getFileName().toString()
|
||||
List<PluginRepositorySpec> pluginsToIncludeInCustomRepository = new ArrayList<PluginRepositorySpec>()
|
||||
Predicate<PluginLayout> autoPublishPluginChecker = loadPluginAutoPublishList(context)
|
||||
|
||||
Path moduleOutput = context.getModuleOutputDir(context.findRequiredModule(plugin.mainModule))
|
||||
Path pluginXmlPath = moduleOutput.resolve("META-INF/plugin.xml")
|
||||
boolean prepareCustomPluginRepositoryForPublishedPlugins = context.productProperties.productLayout
|
||||
.prepareCustomPluginRepositoryForPublishedPlugins
|
||||
List<DistributionFileEntry> mappings = buildPlugins(
|
||||
moduleOutputPatcher, pluginsToPublish, stageDir, context, buildPlatformLibTask,
|
||||
new BiConsumer<PluginLayout, Path>() {
|
||||
@Override
|
||||
void accept(PluginLayout plugin, Path pluginDir) {
|
||||
Path targetDirectory =
|
||||
autoPublishPluginChecker.test(plugin) ? autoUploadingDir :
|
||||
nonBundledPluginsArtifacts
|
||||
String pluginDirName = pluginDir.getFileName().toString()
|
||||
|
||||
String pluginVersion = Files.exists(pluginXmlPath)
|
||||
? plugin.versionEvaluator.evaluate(pluginXmlPath, defaultPluginVersion, context)
|
||||
: defaultPluginVersion
|
||||
Path moduleOutput =
|
||||
context.getModuleOutputDir(context.findRequiredModule(plugin.mainModule))
|
||||
Path pluginXmlPath = moduleOutput.resolve("META-INF/plugin.xml")
|
||||
|
||||
Path destFile = targetDirectory.resolve("$pluginDirName-${pluginVersion}.zip")
|
||||
String pluginVersion = Files.exists(pluginXmlPath)
|
||||
? plugin.versionEvaluator.evaluate(pluginXmlPath, defaultPluginVersion,
|
||||
context)
|
||||
: defaultPluginVersion
|
||||
|
||||
Path destFile =
|
||||
targetDirectory.resolve("$pluginDirName-${pluginVersion}.zip")
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
byte[] pluginXml =
|
||||
moduleOutputPatcher.getPatchedPluginXml(plugin.mainModule)
|
||||
pluginsToIncludeInCustomRepository
|
||||
.add(new PluginRepositorySpec(destFile, pluginXml))
|
||||
}
|
||||
dirToJar.add(Map.entry(pluginDirName, destFile))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
BuildHelper buildHelper = BuildHelper.getInstance(context)
|
||||
buildHelper.bulkZipWithPrefix(stageDir, dirToJar, compressPluginArchive)
|
||||
|
||||
PluginLayout helpPlugin = BuiltInHelpPlugin.helpPlugin(context, defaultPluginVersion)
|
||||
if (helpPlugin != null) {
|
||||
PluginRepositorySpec spec = buildHelpPlugin(helpPlugin, stageDir, autoUploadingDir, moduleOutputPatcher, context)
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
byte[] pluginXml = moduleOutputPatcher.getPatchedPluginXml(plugin.mainModule)
|
||||
pluginsToIncludeInCustomRepository.add(new PluginRepositorySpec(destFile, pluginXml))
|
||||
pluginsToIncludeInCustomRepository.add(spec)
|
||||
}
|
||||
dirToJar.add(Map.entry(pluginDirName, destFile))
|
||||
}
|
||||
}, true)
|
||||
|
||||
BuildHelper buildHelper = BuildHelper.getInstance(context)
|
||||
buildHelper.bulkZipWithPrefix(stageDir, dirToJar, compressPluginArchive)
|
||||
|
||||
PluginLayout helpPlugin = BuiltInHelpPlugin.helpPlugin(context, defaultPluginVersion)
|
||||
if (helpPlugin != null) {
|
||||
PluginRepositorySpec spec = buildHelpPlugin(helpPlugin, stageDir, autoUploadingDir, moduleOutputPatcher, context)
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
pluginsToIncludeInCustomRepository.add(spec)
|
||||
PluginRepositoryXmlGenerator.generate(pluginsToIncludeInCustomRepository, nonBundledPluginsArtifacts, context)
|
||||
|
||||
List<PluginRepositorySpec> autoUploadingPlugins = pluginsToIncludeInCustomRepository
|
||||
.findAll { it.pluginZip.startsWith(autoUploadingDir) }
|
||||
PluginRepositoryXmlGenerator.generate(autoUploadingPlugins, autoUploadingDir, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
PluginRepositoryXmlGenerator.generate(pluginsToIncludeInCustomRepository, nonBundledPluginsArtifacts, context)
|
||||
|
||||
List<PluginRepositorySpec> autoUploadingPlugins = pluginsToIncludeInCustomRepository
|
||||
.findAll { it.pluginZip.startsWith(autoUploadingDir) }
|
||||
PluginRepositoryXmlGenerator.generate(autoUploadingPlugins, autoUploadingDir, context)
|
||||
}
|
||||
|
||||
for (kotlin.Pair<Path, byte[]> item in buildKeymapPluginsTask.join()) {
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
pluginsToIncludeInCustomRepository.add(new PluginRepositorySpec(item.first, item.second))
|
||||
for (kotlin.Pair<Path, byte[]> item in buildKeymapPluginsTask.join()) {
|
||||
if (prepareCustomPluginRepositoryForPublishedPlugins) {
|
||||
pluginsToIncludeInCustomRepository.add(new PluginRepositorySpec(item.first, item.second))
|
||||
}
|
||||
}
|
||||
return mappings
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
private static ForkJoinTask<List<kotlin.Pair<Path, byte[]>>> buildKeymapPlugins(Path targetDir, BuildContext context) {
|
||||
@@ -843,7 +902,7 @@ final class DistributionJARsBuilder {
|
||||
context.messages.block(spanBuilder("build help plugin").setAttribute("dir", directory), new Supplier<Void>() {
|
||||
@Override
|
||||
Void get() {
|
||||
buildPlugins(moduleOutputPatcher, List.of(helpPlugin), pluginsToPublishDir, context, null, null, true)
|
||||
buildPlugins(moduleOutputPatcher, List.of(helpPlugin), pluginsToPublishDir, context, null, null)
|
||||
BuildHelper.zipWithPrefix(context, destFile, List.of(pluginsToPublishDir.resolve(directory)), directory, true)
|
||||
return null
|
||||
}
|
||||
@@ -905,13 +964,13 @@ final class DistributionJARsBuilder {
|
||||
}
|
||||
|
||||
if (customLayouts == null) {
|
||||
if (!result.add(PluginLayout.simplePlugin(moduleName))) {
|
||||
if (moduleName != "kotlin-ultimate.kmm-plugin" && !result.add(PluginLayout.simplePlugin(moduleName))) {
|
||||
throw new IllegalStateException("Plugin layout for module $moduleName is already added (duplicated module name?)")
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PluginLayout layout : customLayouts) {
|
||||
if (!result.add(layout)) {
|
||||
if (layout.mainModule != "kotlin-ultimate.kmm-plugin" && !result.add(layout)) {
|
||||
throw new IllegalStateException("Plugin layout for module $moduleName is already added (duplicated module name?)")
|
||||
}
|
||||
}
|
||||
@@ -929,8 +988,7 @@ final class DistributionJARsBuilder {
|
||||
Path targetDirectory,
|
||||
BuildContext context,
|
||||
@Nullable ForkJoinTask<?> buildPlatformTask,
|
||||
@Nullable BiConsumer<PluginLayout, Path> pluginBuilt,
|
||||
boolean isParallel) {
|
||||
@Nullable BiConsumer<PluginLayout, Path> pluginBuilt) {
|
||||
ScrambleTool scrambleTool = context.proprietaryBuildTools.scrambleTool
|
||||
boolean isScramblingSkipped = context.options.buildStepsToSkip.contains(BuildOptions.SCRAMBLING_STEP)
|
||||
|
||||
@@ -951,48 +1009,43 @@ final class DistributionJARsBuilder {
|
||||
String directoryName = getActualPluginDirectoryName(plugin, context)
|
||||
Path pluginDir = targetDirectory.resolve(directoryName)
|
||||
|
||||
Supplier<List<DistributionFileEntry>> task = new Supplier<List<DistributionFileEntry>>() {
|
||||
@Override
|
||||
List<DistributionFileEntry> get() throws Exception {
|
||||
List<DistributionFileEntry> result = layout(plugin,
|
||||
pluginDir,
|
||||
true,
|
||||
moduleOutputPatcher,
|
||||
plugin.moduleJars,
|
||||
context)
|
||||
if (!plugin.pathsToScramble.isEmpty()) {
|
||||
Attributes attributes = Attributes.of(AttributeKey.stringKey("plugin"), directoryName)
|
||||
if (scrambleTool == null) {
|
||||
Span.current().addEvent("skip scrambling plugin because scrambleTool isn't defined, but plugin defines paths to be scrambled",
|
||||
attributes)
|
||||
}
|
||||
else if (isScramblingSkipped) {
|
||||
Span.current().addEvent("skip scrambling plugin because step is disabled", attributes)
|
||||
}
|
||||
else {
|
||||
ForkJoinTask<?> scrambleTask = scrambleTool.scramblePlugin(context, plugin, pluginDir, targetDirectory)
|
||||
if (scrambleTask != null) {
|
||||
// we can not start executing right now because the plugin can use other plugins in a scramble classpath
|
||||
scrambleTasks.add(scrambleTask)
|
||||
tasks.add(buildHelper.createTask(
|
||||
spanBuilder("plugin").setAttribute("path", context.paths.buildOutputDir.relativize(pluginDir).toString()),
|
||||
new Supplier<List<DistributionFileEntry>>() {
|
||||
@Override
|
||||
List<DistributionFileEntry> get() throws Exception {
|
||||
List<DistributionFileEntry> result = layout(plugin,
|
||||
pluginDir,
|
||||
true,
|
||||
moduleOutputPatcher,
|
||||
plugin.moduleJars,
|
||||
context)
|
||||
if (!plugin.pathsToScramble.isEmpty()) {
|
||||
Attributes attributes = Attributes.of(AttributeKey.stringKey("plugin"), directoryName)
|
||||
if (scrambleTool == null) {
|
||||
Span.current().addEvent(
|
||||
"skip scrambling plugin because scrambleTool isn't defined, but plugin defines paths to be scrambled",
|
||||
attributes)
|
||||
}
|
||||
else if (isScramblingSkipped) {
|
||||
Span.current().addEvent("skip scrambling plugin because step is disabled", attributes)
|
||||
}
|
||||
else {
|
||||
ForkJoinTask<?> scrambleTask = scrambleTool.scramblePlugin(context, plugin, pluginDir, targetDirectory)
|
||||
if (scrambleTask != null) {
|
||||
// we can not start executing right now because the plugin can use other plugins in a scramble classpath
|
||||
scrambleTasks.add(scrambleTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginBuilt != null) {
|
||||
pluginBuilt.accept(plugin, pluginDir)
|
||||
if (pluginBuilt != null) {
|
||||
pluginBuilt.accept(plugin, pluginDir)
|
||||
}
|
||||
return result
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
if (isParallel) {
|
||||
tasks.add(buildHelper.createTask(spanBuilder("plugin")
|
||||
.setAttribute("path", context.paths.buildOutputDir.relativize(targetDirectory).toString()),
|
||||
task))
|
||||
}
|
||||
else {
|
||||
task.get()
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
List<DistributionFileEntry> entries = new ArrayList<>(tasks.size() * 2)
|
||||
|
||||
+81
-72
@@ -55,7 +55,9 @@ final class JarPackager {
|
||||
pack(actualModuleJars, outputDir, new BaseLayout() {}, new ModuleOutputPatcher(), false, context)
|
||||
}
|
||||
|
||||
private static final Map<String, Predicate<String>> EXTRA_MERGE_RULES = new LinkedHashMap<>();
|
||||
private static final Map<String, Predicate<String>> EXTRA_MERGE_RULES = new LinkedHashMap<>()
|
||||
|
||||
private final Map<JpsLibrary, ProjectLibraryData> libToMetadata = new HashMap<>()
|
||||
|
||||
static {
|
||||
// kotlinx- and kotlin-reflect libs to one kotlinx.jar
|
||||
@@ -308,12 +310,13 @@ final class JarPackager {
|
||||
if (library == null) {
|
||||
context.messages.error("Project library '$libraryName' from $jarPath should be unpacked but it isn't found")
|
||||
}
|
||||
|
||||
for (File ioFile : library.getFiles(JpsOrderRootType.COMPILED)) {
|
||||
Path file = ioFile.toPath()
|
||||
sourceList.add(createZipSource.apply(file, new IntConsumer() {
|
||||
@Override
|
||||
void accept(int size) {
|
||||
projectStructureMapping.add(new ProjectLibraryEntry(jarFile, library.name, file, size))
|
||||
projectStructureMapping.add(new ProjectLibraryEntry(jarFile, library.name, file, null, "explicitUnpack", size))
|
||||
}
|
||||
}))
|
||||
}
|
||||
@@ -361,6 +364,8 @@ final class JarPackager {
|
||||
throw new IllegalArgumentException("Cannot find library ${libraryData.libraryName} in the project")
|
||||
}
|
||||
|
||||
libToMetadata.put(library, libraryData)
|
||||
|
||||
Path libOutputDir = outputDir
|
||||
String relativePath = libraryData.relativeOutputPath
|
||||
if (relativePath != null && !relativePath.isEmpty()) {
|
||||
@@ -399,7 +404,8 @@ final class JarPackager {
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : jarToModuleNames.entrySet()) {
|
||||
if (entry.key.contains("/")) {
|
||||
String targetFilename = entry.key
|
||||
if (targetFilename.contains("/")) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -414,68 +420,8 @@ final class JarPackager {
|
||||
continue
|
||||
}
|
||||
|
||||
JpsLibraryDependency libraryDependency = (JpsLibraryDependency)element
|
||||
JpsCompositeElement parent = libraryDependency.libraryReference?.parentReference?.resolve()
|
||||
if (!(parent instanceof JpsModule)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!(JpsJavaExtensionService.instance.getDependencyExtension(element)?.scope
|
||||
?.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME) ?: false)) {
|
||||
continue
|
||||
}
|
||||
|
||||
JpsLibrary library = libraryDependency.library
|
||||
String libraryName = LayoutBuilder.getLibraryName(library)
|
||||
if (!excluded.contains(libraryName) &&
|
||||
!layout.includedModuleLibraries.any { it.libraryName == libraryName }) {
|
||||
String libName = library.name
|
||||
List<Path> files = getLibraryFiles(library, copiedFiles, true)
|
||||
|
||||
if (libName == "async-profiler-windows") {
|
||||
// custom name, removeVersionFromJar doesn't support strings like `2.1-ea-4`
|
||||
addLibrary(library, outputDir.resolve("async-profiler-windows.jar"), files)
|
||||
continue
|
||||
}
|
||||
|
||||
boolean isJpsModule = moduleName.endsWith(".jps")
|
||||
for (int i = files.size() - 1; i >= 0; i--) {
|
||||
Path file = files.get(i)
|
||||
String fileName = file.fileName.toString()
|
||||
if (isJpsModule) {
|
||||
files.remove(i)
|
||||
addLibrary(library, outputDir.resolve(fileName), List.of(file))
|
||||
}
|
||||
else {
|
||||
//noinspection SpellCheckingInspection
|
||||
if (fileName.endsWith("-rt.jar") || fileName.startsWith("jps-") || fileName.contains("-agent") ||
|
||||
fileName == "yjp-controller-api-redist.jar") {
|
||||
files.remove(i)
|
||||
addLibrary(library, outputDir.resolve(removeVersionFromJar(fileName)), List.of(file))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
BiFunction<Path, IntConsumer, ?> createZipSource = buildHelper.createZipSource
|
||||
Path targetFile = outputDir.resolve(entry.key)
|
||||
|
||||
List sources = extraLibSources.computeIfAbsent(entry.key, new Function<String, List>() {
|
||||
@Override
|
||||
List apply(String s) {
|
||||
return new ArrayList()
|
||||
}
|
||||
})
|
||||
|
||||
for (Path file : files) {
|
||||
sources.add(createZipSource.apply(file, new IntConsumer() {
|
||||
@Override
|
||||
void accept(int size) {
|
||||
projectStructureMapping.add(new ModuleLibraryFileEntry(targetFile, moduleName, file, size))
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
packModuleLibs(moduleName, targetFilename, (JpsLibraryDependency)element, excluded, layout, outputDir, copiedFiles,
|
||||
extraLibSources)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -483,6 +429,68 @@ final class JarPackager {
|
||||
return toMerge
|
||||
}
|
||||
|
||||
private void packModuleLibs(String moduleName,
|
||||
String targetFilename,
|
||||
JpsLibraryDependency libraryDependency,
|
||||
Collection<String> excluded,
|
||||
BaseLayout layout,
|
||||
Path outputDir,
|
||||
Map<Path, JpsLibrary> copiedFiles,
|
||||
Map<String, List> extraLibSources) {
|
||||
JpsCompositeElement parent = libraryDependency.libraryReference?.parentReference?.resolve()
|
||||
if (!(parent instanceof JpsModule)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!(JpsJavaExtensionService.instance.getDependencyExtension(libraryDependency)?.scope
|
||||
?.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME) ?: false)) {
|
||||
return
|
||||
}
|
||||
|
||||
JpsLibrary library = libraryDependency.library
|
||||
String libraryName = LayoutBuilder.getLibraryName(library)
|
||||
if (!excluded.contains(libraryName) &&
|
||||
!layout.includedModuleLibraries.any { it.libraryName == libraryName }) {
|
||||
String libName = library.name
|
||||
List<Path> files = getLibraryFiles(library, copiedFiles, true)
|
||||
|
||||
if (libName == "async-profiler-windows") {
|
||||
// custom name, removeVersionFromJar doesn't support strings like `2.1-ea-4`
|
||||
addLibrary(library, outputDir.resolve("async-profiler-windows.jar"), files)
|
||||
return
|
||||
}
|
||||
|
||||
for (int i = files.size() - 1; i >= 0; i--) {
|
||||
Path file = files.get(i)
|
||||
String fileName = file.fileName.toString()
|
||||
//noinspection SpellCheckingInspection
|
||||
if (fileName.endsWith("-rt.jar") || fileName.contains("-agent") || fileName == "yjp-controller-api-redist.jar") {
|
||||
files.remove(i)
|
||||
addLibrary(library, outputDir.resolve(removeVersionFromJar(fileName)), List.of(file))
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
BiFunction<Path, IntConsumer, ?> createZipSource = buildHelper.createZipSource
|
||||
List sources = extraLibSources.computeIfAbsent(targetFilename, new Function<String, List>() {
|
||||
@Override
|
||||
List apply(String s) {
|
||||
return new ArrayList()
|
||||
}
|
||||
})
|
||||
|
||||
Path targetFile = outputDir.resolve(targetFilename)
|
||||
for (Path file : files) {
|
||||
sources.add(createZipSource.apply(file, new IntConsumer() {
|
||||
@Override
|
||||
void accept(int size) {
|
||||
projectStructureMapping.add(new ModuleLibraryFileEntry(targetFile, moduleName, file, size))
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String removeVersionFromJar(String fileName) {
|
||||
Matcher matcher = fileName =~ LayoutBuilder.JAR_NAME_WITH_VERSION_PATTERN
|
||||
if (matcher.matches()) {
|
||||
@@ -532,12 +540,12 @@ final class JarPackager {
|
||||
}
|
||||
}
|
||||
|
||||
private static IntConsumer createLibSizeConsumer(Path file,
|
||||
boolean isModuleLibrary,
|
||||
Collection<DistributionFileEntry> projectStructureMapping,
|
||||
Path targetFile,
|
||||
JpsLibrary library,
|
||||
JpsModuleReference moduleReference) {
|
||||
private IntConsumer createLibSizeConsumer(Path file,
|
||||
boolean isModuleLibrary,
|
||||
Collection<DistributionFileEntry> projectStructureMapping,
|
||||
Path targetFile,
|
||||
JpsLibrary library,
|
||||
JpsModuleReference moduleReference) {
|
||||
return new IntConsumer() {
|
||||
@Override
|
||||
void accept(int size) {
|
||||
@@ -545,7 +553,8 @@ final class JarPackager {
|
||||
projectStructureMapping.add(new ModuleLibraryFileEntry(targetFile, moduleReference.moduleName, file, size))
|
||||
}
|
||||
else {
|
||||
projectStructureMapping.add(new ProjectLibraryEntry(targetFile, library.name, file, size))
|
||||
ProjectLibraryData libMetadata = libToMetadata.get(library)
|
||||
projectStructureMapping.add(new ProjectLibraryEntry(targetFile, library.name, file, libMetadata, null, size))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ final class PlatformLayout extends BaseLayout {
|
||||
includedProjectLibraries.add(new ProjectLibraryData(libraryName, "", packMode))
|
||||
}
|
||||
|
||||
void withProjectLibrary(ProjectLibraryData data) {
|
||||
includedProjectLibraries.add(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude project library {@code libraryName} even if it's added to dependencies of some module or plugin included into the product
|
||||
*/
|
||||
|
||||
+33
-21
@@ -7,23 +7,33 @@ import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.ProductModulesLayout
|
||||
import org.jetbrains.jps.model.library.JpsLibrary
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.NodeList
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.Function
|
||||
|
||||
import static org.jetbrains.intellij.build.impl.ProjectLibraryData.PackMode
|
||||
|
||||
@CompileStatic
|
||||
final class PlatformModules {
|
||||
public static final Function<String, List<String>> LIST_PRODUCER = new Function<String, List<String>>() {
|
||||
@Override
|
||||
List<String> apply(String __) {
|
||||
return new ArrayList<String>()
|
||||
}
|
||||
}
|
||||
|
||||
public static final String PRODUCT_JAR = "product.jar"
|
||||
|
||||
/**
|
||||
* List of modules which are included into lib/openapi.jar in all IntelliJ based IDEs.
|
||||
*/
|
||||
static final List<String> PLATFORM_API_MODULES = List.of(
|
||||
public static final List<String> PLATFORM_API_MODULES = List.of(
|
||||
"intellij.platform.analysis",
|
||||
"intellij.platform.builtInServer",
|
||||
"intellij.platform.core",
|
||||
@@ -112,6 +122,13 @@ final class PlatformModules {
|
||||
|
||||
private static final String UTIL_JAR = "util.jar"
|
||||
|
||||
public static final Map<String, PackMode> CUSTOM_PACK_MODE = Map.of(
|
||||
// jna uses native lib
|
||||
"jna", PackMode.STANDALONE_MERGED,
|
||||
"jetbrains-annotations-java5", PackMode.STANDALONE_SEPARATE_WITHOUT_VERSION_NAME,
|
||||
"intellij-coverage", PackMode.STANDALONE_SEPARATE,
|
||||
)
|
||||
|
||||
static jar(String relativeJarPath,
|
||||
Collection<String> moduleNames,
|
||||
ProductModulesLayout productLayout,
|
||||
@@ -137,13 +154,13 @@ final class PlatformModules {
|
||||
|
||||
static PlatformLayout createPlatformLayout(ProductModulesLayout productLayout,
|
||||
boolean hasPlatformCoverage,
|
||||
Set<JpsLibrary> additionalProjectLevelLibraries,
|
||||
BuildContext buildContext) {
|
||||
Set<ProjectLibraryData> additionalProjectLevelLibraries,
|
||||
BuildContext context) {
|
||||
PlatformLayout layout = new PlatformLayout()
|
||||
// used only in modules that packed into Java
|
||||
layout.excludedProjectLibraries.add("jps-javac-extension")
|
||||
layout.excludedProjectLibraries.add("Eclipse")
|
||||
productLayout.platformLayoutCustomizer.accept(layout, buildContext)
|
||||
productLayout.platformLayoutCustomizer.accept(layout, context)
|
||||
|
||||
Set<String> alreadyPackedModules = new HashSet<>()
|
||||
for (Map.Entry<String, Collection<String>> entry in productLayout.additionalPlatformJars.entrySet()) {
|
||||
@@ -168,7 +185,7 @@ final class PlatformModules {
|
||||
if (isRelocated) {
|
||||
layout.withModule(module, BaseLayout.APP_JAR)
|
||||
}
|
||||
else if (!buildContext.productProperties.useProductJar || module.startsWith("intellij.platform.commercial")) {
|
||||
else if (!context.productProperties.useProductJar || module.startsWith("intellij.platform.commercial")) {
|
||||
layout.withModule(module, productLayout.mainJarName)
|
||||
}
|
||||
else {
|
||||
@@ -256,9 +273,9 @@ final class PlatformModules {
|
||||
layout.withProjectLibraryUnpackedIntoJar(libraryName, productLayout.mainJarName)
|
||||
}
|
||||
|
||||
String productPluginSourceModuleName = buildContext.productProperties.applicationInfoModule
|
||||
String productPluginSourceModuleName = context.productProperties.applicationInfoModule
|
||||
if (productPluginSourceModuleName != null) {
|
||||
List<String> modules = getProductPluginContentModules(buildContext, productPluginSourceModuleName)
|
||||
List<String> modules = getProductPluginContentModules(context, productPluginSourceModuleName)
|
||||
if (modules != null) {
|
||||
for (String name : modules) {
|
||||
layout.withModule(name, BaseLayout.APP_JAR)
|
||||
@@ -266,32 +283,27 @@ final class PlatformModules {
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, PackMode> customPackMode = Map.of(
|
||||
// jna uses native lib
|
||||
"jna", PackMode.STANDALONE_MERGED,
|
||||
"jetbrains-annotations-java5", PackMode.STANDALONE_SEPARATE_WITHOUT_VERSION_NAME,
|
||||
"intellij-coverage", PackMode.STANDALONE_SEPARATE,
|
||||
)
|
||||
|
||||
layout.projectLibrariesToUnpack.putValues(UTIL_JAR, List.of(
|
||||
"JDOM",
|
||||
"Trove4j",
|
||||
))
|
||||
|
||||
for (JpsLibrary library in additionalProjectLevelLibraries) {
|
||||
String name = library.name
|
||||
for (ProjectLibraryData item in additionalProjectLevelLibraries) {
|
||||
String name = item.libraryName
|
||||
if (!productLayout.projectLibrariesToUnpackIntoMainJar.contains(name) &&
|
||||
!layout.projectLibrariesToUnpack.values().contains(name) &&
|
||||
!layout.excludedProjectLibraries.contains(name)) {
|
||||
layout.withProjectLibrary(name, customPackMode.getOrDefault(name, PackMode.MERGED))
|
||||
layout.includedProjectLibraries.add(item)
|
||||
}
|
||||
}
|
||||
layout.collectProjectLibrariesFromIncludedModules(buildContext) { lib, module ->
|
||||
if (!additionalProjectLevelLibraries.contains(lib)) {
|
||||
layout.collectProjectLibrariesFromIncludedModules(context, new BiConsumer<JpsLibrary, JpsModule>() {
|
||||
@Override
|
||||
void accept(JpsLibrary lib, JpsModule module) {
|
||||
String name = lib.name
|
||||
layout.withProjectLibrary(name, customPackMode.getOrDefault(name, PackMode.MERGED))
|
||||
layout.includedProjectLibraries.addOrGet(new ProjectLibraryData(name, "", CUSTOM_PACK_MODE.getOrDefault(name, PackMode.MERGED)))
|
||||
.dependentModules.computeIfAbsent("core", LIST_PRODUCER).add(module.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
return layout
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -2,12 +2,15 @@
|
||||
package org.jetbrains.intellij.build.impl
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
@CompileStatic
|
||||
final class ProjectLibraryData {
|
||||
final String libraryName
|
||||
final String relativeOutputPath
|
||||
final PackMode packMode
|
||||
// plugin to list of modules that uses the library
|
||||
final Map<String, List<String>> dependentModules = new TreeMap<>()
|
||||
|
||||
enum PackMode {
|
||||
// merged into some uber jar
|
||||
@@ -20,7 +23,7 @@ final class ProjectLibraryData {
|
||||
STANDALONE_SEPARATE_WITHOUT_VERSION_NAME,
|
||||
}
|
||||
|
||||
ProjectLibraryData(String libraryName, String relativeOutputPath, PackMode packMode) {
|
||||
ProjectLibraryData(@NotNull String libraryName, String relativeOutputPath, @NotNull PackMode packMode) {
|
||||
this.libraryName = libraryName
|
||||
this.relativeOutputPath = relativeOutputPath
|
||||
this.packMode = packMode
|
||||
|
||||
+15
@@ -2,6 +2,8 @@
|
||||
package org.jetbrains.intellij.build.impl.projectStructureMapping
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.intellij.build.impl.ProjectLibraryData
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -13,12 +15,25 @@ final class ProjectLibraryEntry extends DistributionFileEntry implements Distrib
|
||||
final String libraryName
|
||||
final Path libraryFile
|
||||
final int size
|
||||
final @Nullable ProjectLibraryData data
|
||||
final @Nullable String reason
|
||||
|
||||
ProjectLibraryEntry(Path path, String libraryName, Path libraryFile, int size) {
|
||||
this(path, libraryName, libraryFile, null, null, size)
|
||||
}
|
||||
|
||||
ProjectLibraryEntry(Path path,
|
||||
String libraryName,
|
||||
Path libraryFile,
|
||||
@Nullable ProjectLibraryData data,
|
||||
@Nullable String reason,
|
||||
int size) {
|
||||
super(path, "project-library")
|
||||
|
||||
this.libraryName = libraryName
|
||||
this.libraryFile = libraryFile
|
||||
this.data = data
|
||||
this.reason = reason
|
||||
this.size = size
|
||||
}
|
||||
|
||||
|
||||
+42
-4
@@ -3,10 +3,13 @@ package org.jetbrains.intellij.build.impl.projectStructureMapping
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.core.util.DefaultIndenter
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.intellij.build.BuildPaths
|
||||
import org.jetbrains.intellij.build.impl.ProjectLibraryData
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
@@ -59,7 +62,7 @@ final class ProjectStructureMapping {
|
||||
allEntries.sort({ DistributionFileEntry a , DistributionFileEntry b -> a.path.compareTo(b.path) })
|
||||
|
||||
Files.newOutputStream(file).withCloseable { out ->
|
||||
JsonGenerator writer = new JsonFactory().createGenerator(out).useDefaultPrettyPrinter()
|
||||
JsonGenerator writer = new JsonFactory().createGenerator(out).setPrettyPrinter(new IntelliJDefaultPrettyPrinter())
|
||||
writer.writeStartArray()
|
||||
for (DistributionFileEntry entry : allEntries) {
|
||||
writer.writeStartObject()
|
||||
@@ -88,8 +91,23 @@ final class ProjectStructureMapping {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class IntelliJDefaultPrettyPrinter extends DefaultPrettyPrinter {
|
||||
private static final DefaultIndenter INDENTER = new DefaultIndenter(" ", "\n")
|
||||
|
||||
IntelliJDefaultPrettyPrinter() {
|
||||
_objectFieldValueSeparatorWithSpaces = ": "
|
||||
_objectIndenter = INDENTER
|
||||
_arrayIndenter = INDENTER
|
||||
}
|
||||
|
||||
@Override
|
||||
DefaultPrettyPrinter createInstance() {
|
||||
return new IntelliJDefaultPrettyPrinter()
|
||||
}
|
||||
}
|
||||
|
||||
static void buildJarContentReport(Collection<DistributionFileEntry> entries, OutputStream out, BuildPaths buildPaths) {
|
||||
JsonGenerator writer = new JsonFactory().createGenerator(out).useDefaultPrettyPrinter()
|
||||
JsonGenerator writer = new JsonFactory().createGenerator(out).setPrettyPrinter(new IntelliJDefaultPrettyPrinter())
|
||||
Map<Path, List<DistributionFileEntry>> fileToEntry = new TreeMap<>()
|
||||
for (DistributionFileEntry entry : entries) {
|
||||
fileToEntry.computeIfAbsent(entry.path, { new ArrayList<DistributionFileEntry>() }).add(entry)
|
||||
@@ -125,7 +143,7 @@ final class ProjectStructureMapping {
|
||||
throw new IllegalStateException("Unsupported entry: $entry")
|
||||
}
|
||||
|
||||
writer.writeNumberField("value", fileSize)
|
||||
writer.writeNumberField("size", fileSize)
|
||||
writer.writeEndObject()
|
||||
}
|
||||
writer.writeEndArray()
|
||||
@@ -154,7 +172,15 @@ final class ProjectStructureMapping {
|
||||
for (ProjectLibraryEntry fileEntry : entry.value) {
|
||||
writer.writeStartObject()
|
||||
writer.writeStringField("name", shortenPath(fileEntry.libraryFile, buildPaths, null))
|
||||
writer.writeNumberField("value", fileEntry.size as long)
|
||||
writer.writeNumberField("size", fileEntry.size as long)
|
||||
|
||||
ProjectLibraryData data = fileEntry.data
|
||||
if (fileEntry.reason != null) {
|
||||
writer.writeStringField("reason", fileEntry.reason)
|
||||
}
|
||||
if (data != null && !data.dependentModules.isEmpty()) {
|
||||
writeModuleDependents(writer, data)
|
||||
}
|
||||
writer.writeEndObject()
|
||||
}
|
||||
writer.writeEndArray()
|
||||
@@ -163,6 +189,18 @@ final class ProjectStructureMapping {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeModuleDependents(JsonGenerator writer, ProjectLibraryData data) {
|
||||
writer.writeObjectFieldStart("dependentModules")
|
||||
for (Map.Entry<String, List<String>> pluginAndModules : data.dependentModules.entrySet()) {
|
||||
writer.writeArrayFieldStart(pluginAndModules.key)
|
||||
for (String moduleName : pluginAndModules.value) {
|
||||
writer.writeString(moduleName)
|
||||
}
|
||||
writer.writeEndArray()
|
||||
}
|
||||
writer.writeEndObject()
|
||||
}
|
||||
|
||||
private static String shortenPath(Path file, BuildPaths buildPaths, @Nullable Path extraRoot) {
|
||||
if (file.startsWith(MAVEN_REPO)) {
|
||||
return "\$MAVEN_REPOSITORY\$" + File.separatorChar + MAVEN_REPO.relativize(file).toString()
|
||||
|
||||
+17
-13
@@ -1,14 +1,23 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.internal.statistics.utils
|
||||
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.internal.statistic.utils.PluginInfo
|
||||
import com.intellij.internal.statistic.utils.PluginType
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
private const val tbePluginId = "org.jetbrains.toolbox-enterprise-client"
|
||||
|
||||
class FusInjectionWhiteListTest {
|
||||
companion object {
|
||||
@BeforeAll
|
||||
@JvmStatic
|
||||
fun setUp() {
|
||||
PluginManagerCore.isUnitTestMode = true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun allowedPluginsTBE() {
|
||||
@@ -17,10 +26,10 @@ class FusInjectionWhiteListTest {
|
||||
.partition { it.isAllowedToInjectIntoFUS() }
|
||||
|
||||
allowed
|
||||
.forEach { assertTrue(it.isDevelopedByJetBrains()) }
|
||||
.forEach { assertThat(it.isDevelopedByJetBrains()).isTrue() }
|
||||
|
||||
notAllowed
|
||||
.forEach { assertFalse(it.isDevelopedByJetBrains()) }
|
||||
.forEach { assertThat(it.isDevelopedByJetBrains()).isFalse() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -29,11 +38,6 @@ class FusInjectionWhiteListTest {
|
||||
.map { PluginInfo(it, "some.plugin.id", "1.2.3") }
|
||||
.filter { it.isAllowedToInjectIntoFUS() }
|
||||
|
||||
assertEquals(1, allowed.size)
|
||||
assertEquals(PluginType.PLATFORM, allowed.first().type)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val tbePluginId = "org.jetbrains.toolbox-enterprise-client"
|
||||
assertThat(allowed.map { it.type }).containsExactlyInAnyOrder(PluginType.PLATFORM, PluginType.FROM_SOURCES)
|
||||
}
|
||||
}
|
||||
@@ -198,18 +198,18 @@ data class PluginInfo(val type: PluginType, val id: String?, val version: String
|
||||
fun isSafeToReport() = type.isSafeToReport()
|
||||
|
||||
fun isAllowedToInjectIntoFUS(): Boolean {
|
||||
return (isDevelopedByJetBrains() && id == tbePluginId) ||
|
||||
return (id == tbePluginId && type.isDevelopedByJetBrains()) ||
|
||||
(PluginManagerCore.isUnitTestMode && (type == PluginType.PLATFORM || type == PluginType.FROM_SOURCES))
|
||||
}
|
||||
}
|
||||
|
||||
val jvmCore: PluginInfo = PluginInfo(PluginType.JVM_CORE, null, null)
|
||||
private val jvmCore: PluginInfo = PluginInfo(PluginType.JVM_CORE, null, null)
|
||||
val platformPlugin: PluginInfo = PluginInfo(PluginType.PLATFORM, null, null)
|
||||
val unknownPlugin: PluginInfo = PluginInfo(PluginType.UNKNOWN, null, null)
|
||||
private val notListedPlugin = PluginInfo(PluginType.NOT_LISTED, null, null)
|
||||
|
||||
// Mock plugin info used when we can't detect plugin by class loader because IDE is built from sources
|
||||
val builtFromSources: PluginInfo = PluginInfo(PluginType.FROM_SOURCES, null, null)
|
||||
private val builtFromSources = PluginInfo(PluginType.FROM_SOURCES, null, null)
|
||||
|
||||
private val pluginIdsFromOfficialJbPluginRepo: Supplier<Set<PluginId>> = TimeoutCachedValue(1, TimeUnit.HOURS) {
|
||||
// before loading default repository plugins lets check it's not changed, and is really official JetBrains repository
|
||||
|
||||
Reference in New Issue
Block a user