mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[build scripts] don't rely on the runtime module repository when filtering modules compatible with the frontend (IJPL-201730)
Since the runtime module repository won't be produced during compilation after migration to Bazel, the build scripts cannot use it to filter out modules incompatible with the frontend when building the frontend distribution and to put such modules in separate JARs when building a monolith distribution. Since building the runtime module repository may take noticeable time when running 'dev build' from sources, the logic in 'ContentModuleFilterImpl' and 'FrontendModuleFilterImpl' was reimplemented to use the data from JpsModel instead. IJ-MR-174028 GitOrigin-RevId: d51e6e1cde9e559a5555388a6bda7468ed95dd9a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f83795eaff
commit
d6ea3c63d7
@@ -254,8 +254,8 @@ class BuildContextImpl internal constructor(
|
||||
val rootModule = productProperties.embeddedFrontendRootModule
|
||||
if (rootModule != null && options.enableEmbeddedFrontend) {
|
||||
val moduleRepository = getOriginalModuleRepository()
|
||||
val productModules = moduleRepository.loadProductModules(rootModule, ProductMode.FRONTEND)
|
||||
FrontendModuleFilterImpl(moduleRepository.repository, productModules)
|
||||
val productModules = moduleRepository.loadRawProductModules(rootModule, ProductMode.FRONTEND)
|
||||
FrontendModuleFilterImpl.create(project, productModules, jarPackagerDependencyHelper)
|
||||
}
|
||||
else {
|
||||
EmptyFrontendModuleFilter
|
||||
@@ -276,7 +276,7 @@ class BuildContextImpl internal constructor(
|
||||
|
||||
return asyncLazy("Content Modules Filter") {
|
||||
val bundledPluginModules = getBundledPluginModules()
|
||||
ContentModuleByProductModeFilter(getOriginalModuleRepository().repository, bundledPluginModules, productProperties.productMode)
|
||||
ContentModuleByProductModeFilter(project, bundledPluginModules, productProperties.productMode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-8
@@ -2,30 +2,29 @@
|
||||
package org.jetbrains.intellij.build.impl
|
||||
|
||||
import com.intellij.platform.runtime.product.ProductMode
|
||||
import com.intellij.platform.runtime.product.impl.ProductModeMatcher
|
||||
import com.intellij.platform.runtime.repository.RuntimeModuleId
|
||||
import com.intellij.platform.runtime.repository.RuntimeModuleRepository
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.ContentModuleFilter
|
||||
import org.jetbrains.intellij.build.impl.moduleBased.JpsProductModeMatcher
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
|
||||
/**
|
||||
* An instance of [ContentModuleFilter] which excludes modules not compatible with the given [ProductMode] from the platform part and bundled plugins.
|
||||
*/
|
||||
internal class ContentModuleByProductModeFilter(
|
||||
private val moduleRepository: RuntimeModuleRepository,
|
||||
bundledPluginModules: List<String>,
|
||||
private val project: JpsProject,
|
||||
bundledPluginModules: List<String>,
|
||||
private val productMode: ProductMode
|
||||
) : ContentModuleFilter {
|
||||
|
||||
private val productModeMatcher = ProductModeMatcher(productMode)
|
||||
private val productModeMatcher = JpsProductModeMatcher(productMode)
|
||||
private val bundledPluginMainModules = bundledPluginModules.toSet()
|
||||
|
||||
override fun isOptionalModuleIncluded(moduleName: String, pluginMainModuleName: String?): Boolean {
|
||||
if (pluginMainModuleName != null && pluginMainModuleName !in bundledPluginMainModules) {
|
||||
return true
|
||||
}
|
||||
val moduleDescriptor = moduleRepository.getModule(RuntimeModuleId.module(moduleName))
|
||||
return productModeMatcher.matches(moduleDescriptor)
|
||||
val module = project.findModuleByName(moduleName) ?: return true
|
||||
return productModeMatcher.matches(module)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
+67
-22
@@ -2,33 +2,84 @@
|
||||
package org.jetbrains.intellij.build.impl
|
||||
|
||||
import com.intellij.platform.runtime.product.ProductMode
|
||||
import com.intellij.platform.runtime.product.ProductModules
|
||||
import com.intellij.platform.runtime.product.impl.ProductModeMatcher
|
||||
import com.intellij.platform.runtime.repository.RuntimeModuleId
|
||||
import com.intellij.platform.runtime.repository.RuntimeModuleRepository
|
||||
import com.intellij.platform.runtime.product.serialization.RawProductModules
|
||||
import org.jetbrains.intellij.build.FrontendModuleFilter
|
||||
import org.jetbrains.intellij.build.JarPackagerDependencyHelper
|
||||
import org.jetbrains.intellij.build.impl.moduleBased.JpsProductModeMatcher
|
||||
import org.jetbrains.jps.model.JpsNamedElement
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.library.JpsLibrary
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.jetbrains.jps.model.module.JpsModuleReference
|
||||
|
||||
internal class FrontendModuleFilterImpl(private val moduleRepository: RuntimeModuleRepository, productModules: ProductModules): FrontendModuleFilter {
|
||||
private val includedModules: Set<RuntimeModuleId> = (sequenceOf(productModules.mainModuleGroup) + productModules.bundledPluginModuleGroups.asSequence())
|
||||
.flatMap { it.includedModules.asSequence() }
|
||||
.filter { included -> included.moduleDescriptor.moduleId !in MODULES_SCRAMBLED_WITH_FRONTEND }
|
||||
.mapTo(HashSet()) { it.moduleDescriptor.moduleId }
|
||||
private val frontendModeMatcher = ProductModeMatcher(ProductMode.FRONTEND)
|
||||
internal class FrontendModuleFilterImpl private constructor(
|
||||
private val project: JpsProject,
|
||||
private val frontendModeMatcher: JpsProductModeMatcher,
|
||||
private val includedModuleNames: Set<String>,
|
||||
private val includedProjectLibraryNames: Set<String>,
|
||||
): FrontendModuleFilter {
|
||||
companion object {
|
||||
suspend fun create(project: JpsProject, productModules: RawProductModules, jarPackagerDependencyHelper: JarPackagerDependencyHelper): FrontendModuleFilter {
|
||||
val frontendModeMatcher = JpsProductModeMatcher(ProductMode.FRONTEND)
|
||||
val includedModuleNames = LinkedHashSet<String>()
|
||||
val includedProjectLibraryNames = LinkedHashSet<String>()
|
||||
|
||||
for (rootModuleName in productModules.mainGroupModules) {
|
||||
val rootModule = project.findModuleByName(rootModuleName.moduleId.stringId) ?: continue
|
||||
collectTransitiveDependenciesCompatibleWithFrontend(rootModule, frontendModeMatcher, includedModuleNames, includedProjectLibraryNames)
|
||||
}
|
||||
|
||||
for (mainModuleId in productModules.bundledPluginMainModules) {
|
||||
val module = project.findModuleByName(mainModuleId.stringId) ?: continue
|
||||
if (frontendModeMatcher.matches(module)) {
|
||||
includedModuleNames.add(module.name)
|
||||
jarPackagerDependencyHelper.readPluginContentFromDescriptor(module, ModuleOutputPatcher())
|
||||
.mapNotNull { project.findModuleByName(it.first) }
|
||||
.filter { frontendModeMatcher.matches(it) }
|
||||
.mapTo(includedModuleNames) { it.name }
|
||||
}
|
||||
}
|
||||
|
||||
return FrontendModuleFilterImpl(project, frontendModeMatcher, includedModuleNames, includedProjectLibraryNames)
|
||||
}
|
||||
|
||||
private fun collectTransitiveDependenciesCompatibleWithFrontend(
|
||||
module: JpsModule,
|
||||
frontendModeMatcher: JpsProductModeMatcher,
|
||||
includedModuleNames: MutableSet<String>,
|
||||
includedProjectLibraryNames: MutableSet<String>,
|
||||
) {
|
||||
if (isScrambledWithFrontend(module) || !frontendModeMatcher.matches(module)) {
|
||||
return
|
||||
}
|
||||
if (!includedModuleNames.add(module.name)) {
|
||||
return
|
||||
}
|
||||
JpsJavaExtensionService.dependencies(module).productionOnly().runtimeOnly().processModuleAndLibraries(
|
||||
{ depModule ->
|
||||
collectTransitiveDependenciesCompatibleWithFrontend(depModule, frontendModeMatcher, includedModuleNames, includedProjectLibraryNames)
|
||||
},
|
||||
{ depLibrary ->
|
||||
if (!isScrambledWithFrontend(depLibrary) && depLibrary.createReference().parentReference !is JpsModuleReference) {
|
||||
includedProjectLibraryNames.add(depLibrary.name)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isModuleIncluded(moduleName: String): Boolean {
|
||||
return RuntimeModuleId.module(moduleName) in includedModules
|
||||
return moduleName in includedModuleNames
|
||||
}
|
||||
|
||||
override fun isProjectLibraryIncluded(libraryName: String): Boolean {
|
||||
return RuntimeModuleId.projectLibrary(libraryName) in includedModules
|
||||
return libraryName in includedProjectLibraryNames
|
||||
}
|
||||
|
||||
override fun isModuleCompatibleWithFrontend(moduleName: String): Boolean {
|
||||
val moduleDescriptor = moduleRepository.getModule(RuntimeModuleId.module(moduleName))
|
||||
return frontendModeMatcher.matches(moduleDescriptor)
|
||||
val module = project.findModuleByName(moduleName)
|
||||
return module != null && frontendModeMatcher.matches(module)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,15 +93,9 @@ val PROJECT_LIBRARIES_SCRAMBLED_WITH_FRONTEND: Set<String> = setOf(
|
||||
)
|
||||
|
||||
/**
|
||||
* Contains a set of runtime modules from the platform part which are also included in the frontend JARs and scrambled (differently) there.
|
||||
* It's important not to include JARs for these modules in the platform part to the classpath of the frontend process, because they may
|
||||
* cause clashes.
|
||||
* Returns `true` if the module or library [element] from the platform part which are also included in the frontend JARs and scrambled (differently) there.
|
||||
* It's important not to include JARs for these modules and libraries in the platform part to the classpath of the frontend process, because they may cause clashes.
|
||||
*/
|
||||
val MODULES_SCRAMBLED_WITH_FRONTEND: Set<RuntimeModuleId> by lazy {
|
||||
setOf(RuntimeModuleId.module(PLATFORM_MODULE_SCRAMBLED_WITH_FRONTEND)) +
|
||||
PROJECT_LIBRARIES_SCRAMBLED_WITH_FRONTEND.map { RuntimeModuleId.projectLibrary(it) }
|
||||
}
|
||||
|
||||
fun isScrambledWithFrontend(element: JpsNamedElement): Boolean = when (element) {
|
||||
is JpsModule -> element.name == PLATFORM_MODULE_SCRAMBLED_WITH_FRONTEND
|
||||
is JpsLibrary -> element.name in PROJECT_LIBRARIES_SCRAMBLED_WITH_FRONTEND
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// 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.moduleBased
|
||||
|
||||
import com.intellij.platform.runtime.product.ProductMode
|
||||
import com.intellij.platform.runtime.product.impl.ProductModes
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
|
||||
/**
|
||||
* This is an equivalent implementation of [com.intellij.platform.runtime.product.impl.ProductModeMatcher] based on JPS model instead of the runtime module repository.
|
||||
*/
|
||||
internal class JpsProductModeMatcher(productMode: ProductMode) {
|
||||
private val incompatibleRootModule = ProductModes.getIncompatibleRootModule(productMode).stringId
|
||||
private val cache: MutableMap<JpsModule, Boolean> = mutableMapOf()
|
||||
|
||||
fun matches(module: JpsModule): Boolean {
|
||||
val cached = cache[module]
|
||||
if (cached != null) return cached
|
||||
if (incompatibleRootModule == module.name) {
|
||||
cache[module] = false
|
||||
return false
|
||||
}
|
||||
|
||||
cache[module] = true //this is needed to prevent StackOverflowError in the case of circular dependencies
|
||||
var matches = true
|
||||
JpsJavaExtensionService.dependencies(module).productionOnly().runtimeOnly().processModules {
|
||||
matches = matches && matches(it)
|
||||
}
|
||||
cache[module] = matches
|
||||
return matches
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.intellij.platform.runtime.product.impl;
|
||||
|
||||
import com.intellij.platform.runtime.product.ProductMode;
|
||||
import com.intellij.platform.runtime.repository.RuntimeModuleId;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -10,7 +11,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
* Currently, this is determined by the presence of specific modules in dependencies. We can change this and require to specify modes
|
||||
* a module is compatible with explicitly in the future.
|
||||
*/
|
||||
final class ProductModes {
|
||||
@ApiStatus.Internal
|
||||
public final class ProductModes {
|
||||
private ProductModes() {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user