Optimize memory usage during import of MPP projects
#KT-30767 Fixed
This commit is contained in:
+1
-1
@@ -196,7 +196,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
|
|||||||
if (LOG.isDebugEnabled) {
|
if (LOG.isDebugEnabled) {
|
||||||
LOG.debug("Start populate module dependencies. Gradle module: [$gradleModule], Ide module: [$ideModule], Ide project: [$ideProject]")
|
LOG.debug("Start populate module dependencies. Gradle module: [$gradleModule], Ide module: [$ideModule], Ide project: [$ideProject]")
|
||||||
}
|
}
|
||||||
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) }
|
val mppModel = resolverCtx.getMppModel(gradleModule)
|
||||||
if (mppModel != null) {
|
if (mppModel != null) {
|
||||||
mppModel.targets.forEach { target ->
|
mppModel.targets.forEach { target ->
|
||||||
KotlinStatisticsTrigger.trigger(
|
KotlinStatisticsTrigger.trigger(
|
||||||
|
|||||||
+21
-8
@@ -45,6 +45,7 @@ import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.ge
|
|||||||
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
|
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Order(ExternalSystemConstants.UNORDERED + 1)
|
@Order(ExternalSystemConstants.UNORDERED + 1)
|
||||||
open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
||||||
@@ -83,7 +84,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
super.populateModuleCompileOutputSettings(gradleModule, ideModule)
|
super.populateModuleCompileOutputSettings(gradleModule, ideModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
|
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
|
||||||
val ideaOutDir = File(ideModule.data.linkedExternalProjectPath, "out")
|
val ideaOutDir = File(ideModule.data.linkedExternalProjectPath, "out")
|
||||||
val projectDataNode = ideModule.getDataNode(ProjectKeys.PROJECT)!!
|
val projectDataNode = ideModule.getDataNode(ProjectKeys.PROJECT)!!
|
||||||
val moduleOutputsMap = projectDataNode.getUserData(MODULES_OUTPUTS)!!
|
val moduleOutputsMap = projectDataNode.getUserData(MODULES_OUTPUTS)!!
|
||||||
@@ -153,6 +154,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val proxyObjectCloningCache = WeakHashMap<Any, Any>()
|
||||||
|
|
||||||
fun initializeModuleData(
|
fun initializeModuleData(
|
||||||
gradleModule: IdeaModule,
|
gradleModule: IdeaModule,
|
||||||
mainModuleNode: DataNode<ModuleData>,
|
mainModuleNode: DataNode<ModuleData>,
|
||||||
@@ -164,7 +167,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
val mainModuleFileDirectoryPath = mainModuleData.moduleFileDirectoryPath
|
val mainModuleFileDirectoryPath = mainModuleData.moduleFileDirectoryPath
|
||||||
|
|
||||||
val externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java)
|
val externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java)
|
||||||
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) }
|
val mppModel = resolverCtx.getMppModel(gradleModule)
|
||||||
if (mppModel == null || externalProject == null) return
|
if (mppModel == null || externalProject == null) return
|
||||||
|
|
||||||
val jdkName = gradleModule.jdkNameIfAny
|
val jdkName = gradleModule.jdkNameIfAny
|
||||||
@@ -311,8 +314,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
ideModule: DataNode<ModuleData>,
|
ideModule: DataNode<ModuleData>,
|
||||||
resolverCtx: ProjectResolverContext
|
resolverCtx: ProjectResolverContext
|
||||||
) {
|
) {
|
||||||
val mppModel =
|
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
|
||||||
resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
|
|
||||||
if (resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java) == null) return
|
if (resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java) == null) return
|
||||||
processSourceSets(gradleModule, mppModel, ideModule, resolverCtx) { dataNode, sourceSet ->
|
processSourceSets(gradleModule, mppModel, ideModule, resolverCtx) { dataNode, sourceSet ->
|
||||||
if (dataNode == null || sourceSet.platform == KotlinPlatform.ANDROID) return@processSourceSets
|
if (dataNode == null || sourceSet.platform == KotlinPlatform.ANDROID) return@processSourceSets
|
||||||
@@ -339,8 +341,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
ideModule: DataNode<ModuleData>,
|
ideModule: DataNode<ModuleData>,
|
||||||
resolverCtx: ProjectResolverContext
|
resolverCtx: ProjectResolverContext
|
||||||
) {
|
) {
|
||||||
val mppModel =
|
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
|
||||||
resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
|
|
||||||
val sourceSetMap = ideProject.getUserData(GradleProjectResolver.RESOLVED_SOURCE_SETS) ?: return
|
val sourceSetMap = ideProject.getUserData(GradleProjectResolver.RESOLVED_SOURCE_SETS) ?: return
|
||||||
val artifactsMap = ideProject.getUserData(CONFIGURATION_ARTIFACTS) ?: return
|
val artifactsMap = ideProject.getUserData(CONFIGURATION_ARTIFACTS) ?: return
|
||||||
val substitutor = KotlinNativeLibrariesDependencySubstitutor(mppModel, gradleModule, resolverCtx)
|
val substitutor = KotlinNativeLibrariesDependencySubstitutor(mppModel, gradleModule, resolverCtx)
|
||||||
@@ -615,7 +616,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
resolverCtx: ProjectResolverContext
|
resolverCtx: ProjectResolverContext
|
||||||
): KotlinSourceSetInfo? {
|
): KotlinSourceSetInfo? {
|
||||||
if (sourceSet.platform.isNotSupported()) return null
|
if (sourceSet.platform.isNotSupported()) return null
|
||||||
return KotlinSourceSetInfo(KotlinSourceSetImpl(sourceSet)).also { info ->
|
return KotlinSourceSetInfo(sourceSet).also { info ->
|
||||||
val languageSettings = sourceSet.languageSettings
|
val languageSettings = sourceSet.languageSettings
|
||||||
info.moduleId = getKotlinModuleId(gradleModule, sourceSet, resolverCtx)
|
info.moduleId = getKotlinModuleId(gradleModule, sourceSet, resolverCtx)
|
||||||
info.gradleModuleId = getModuleId(resolverCtx, gradleModule)
|
info.gradleModuleId = getModuleId(resolverCtx, gradleModule)
|
||||||
@@ -645,7 +646,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
resolverCtx: ProjectResolverContext
|
resolverCtx: ProjectResolverContext
|
||||||
): KotlinSourceSetInfo? {
|
): KotlinSourceSetInfo? {
|
||||||
if (compilation.platform.isNotSupported()) return null
|
if (compilation.platform.isNotSupported()) return null
|
||||||
return KotlinSourceSetInfo(KotlinCompilationImpl(compilation)).also { sourceSetInfo ->
|
return KotlinSourceSetInfo(compilation).also { sourceSetInfo ->
|
||||||
sourceSetInfo.moduleId = getKotlinModuleId(gradleModule, compilation, resolverCtx)
|
sourceSetInfo.moduleId = getKotlinModuleId(gradleModule, compilation, resolverCtx)
|
||||||
sourceSetInfo.gradleModuleId = getModuleId(resolverCtx, gradleModule)
|
sourceSetInfo.gradleModuleId = getModuleId(resolverCtx, gradleModule)
|
||||||
sourceSetInfo.platform = compilation.platform
|
sourceSetInfo.platform = compilation.platform
|
||||||
@@ -697,3 +698,15 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
|
|||||||
) ?: false
|
) ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ProjectResolverContext.getMppModel(gradleModule: IdeaModule): KotlinMPPGradleModel? =
|
||||||
|
this.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)
|
||||||
|
?.let { kotlinMppModel ->
|
||||||
|
KotlinMPPGradleProjectResolver.proxyObjectCloningCache[kotlinMppModel] as? KotlinMPPGradleModelImpl ?: KotlinMPPGradleModelImpl(
|
||||||
|
kotlinMppModel,
|
||||||
|
KotlinMPPGradleProjectResolver.proxyObjectCloningCache
|
||||||
|
).also {
|
||||||
|
KotlinMPPGradleProjectResolver.proxyObjectCloningCache[kotlinMppModel] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,20 @@ import org.jetbrains.plugins.gradle.model.ExternalDependency
|
|||||||
import org.jetbrains.plugins.gradle.model.ModelFactory
|
import org.jetbrains.plugins.gradle.model.ModelFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
typealias KotlinDependency = ExternalDependency
|
typealias KotlinDependency = ExternalDependency
|
||||||
|
|
||||||
fun KotlinDependency.deepCopy(): KotlinDependency = ModelFactory.createCopy(this)
|
fun KotlinDependency.deepCopy(cache: MutableMap<Any, Any>): KotlinDependency {
|
||||||
|
val cachedValue = cache[this] as? KotlinDependency
|
||||||
|
if (cachedValue != null) {
|
||||||
|
return cachedValue
|
||||||
|
} else {
|
||||||
|
val result = ModelFactory.createCopy(this)
|
||||||
|
cache[this] = result
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface KotlinModule : Serializable {
|
interface KotlinModule : Serializable {
|
||||||
val name: String
|
val name: String
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
data class KotlinSourceSetImpl(
|
data class KotlinSourceSetImpl(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
@@ -18,12 +19,12 @@ data class KotlinSourceSetImpl(
|
|||||||
val defaultIsTestModule: Boolean = false
|
val defaultIsTestModule: Boolean = false
|
||||||
) : KotlinSourceSet {
|
) : KotlinSourceSet {
|
||||||
|
|
||||||
constructor(kotlinSourceSet: KotlinSourceSet) : this(
|
constructor(kotlinSourceSet: KotlinSourceSet, cloningCache: MutableMap<Any, Any>) : this(
|
||||||
kotlinSourceSet.name,
|
kotlinSourceSet.name,
|
||||||
KotlinLanguageSettingsImpl(kotlinSourceSet.languageSettings),
|
KotlinLanguageSettingsImpl(kotlinSourceSet.languageSettings),
|
||||||
HashSet(kotlinSourceSet.sourceDirs),
|
HashSet(kotlinSourceSet.sourceDirs),
|
||||||
HashSet(kotlinSourceSet.resourceDirs),
|
HashSet(kotlinSourceSet.resourceDirs),
|
||||||
kotlinSourceSet.dependencies.map { it.deepCopy() }.toSet(),
|
kotlinSourceSet.dependencies.map { it.deepCopy(cloningCache) }.toSet(),
|
||||||
HashSet(kotlinSourceSet.dependsOnSourceSets),
|
HashSet(kotlinSourceSet.dependsOnSourceSets),
|
||||||
kotlinSourceSet.platform,
|
kotlinSourceSet.platform,
|
||||||
kotlinSourceSet.isTestModule
|
kotlinSourceSet.isTestModule
|
||||||
@@ -87,10 +88,14 @@ data class KotlinCompilationImpl(
|
|||||||
) : KotlinCompilation {
|
) : KotlinCompilation {
|
||||||
|
|
||||||
// create deep copy
|
// create deep copy
|
||||||
constructor(kotlinCompilation: KotlinCompilation) : this(
|
constructor(kotlinCompilation: KotlinCompilation, cloningCache: MutableMap<Any, Any>) : this(
|
||||||
kotlinCompilation.name,
|
kotlinCompilation.name,
|
||||||
kotlinCompilation.sourceSets.map { KotlinSourceSetImpl(it) }.toList(),
|
kotlinCompilation.sourceSets.map { initialSourceSet ->
|
||||||
kotlinCompilation.dependencies.map { it.deepCopy() }.toSet(),
|
(cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(initialSourceSet, cloningCache).also {
|
||||||
|
cloningCache[initialSourceSet] = it
|
||||||
|
}
|
||||||
|
}.toList(),
|
||||||
|
kotlinCompilation.dependencies.map { it.deepCopy(cloningCache) }.toSet(),
|
||||||
KotlinCompilationOutputImpl(kotlinCompilation.output),
|
KotlinCompilationOutputImpl(kotlinCompilation.output),
|
||||||
KotlinCompilationArgumentsImpl(kotlinCompilation.arguments),
|
KotlinCompilationArgumentsImpl(kotlinCompilation.arguments),
|
||||||
ArrayList(kotlinCompilation.dependencyClasspath)
|
ArrayList(kotlinCompilation.dependencyClasspath)
|
||||||
@@ -126,12 +131,16 @@ data class KotlinTargetImpl(
|
|||||||
) : KotlinTarget {
|
) : KotlinTarget {
|
||||||
override fun toString() = name
|
override fun toString() = name
|
||||||
|
|
||||||
constructor(target: KotlinTarget) : this(
|
constructor(target: KotlinTarget, cloningCache: MutableMap<Any, Any>) : this(
|
||||||
target.name,
|
target.name,
|
||||||
target.presetName,
|
target.presetName,
|
||||||
target.disambiguationClassifier,
|
target.disambiguationClassifier,
|
||||||
KotlinPlatform.byId(target.platform.id) ?: KotlinPlatform.COMMON,
|
KotlinPlatform.byId(target.platform.id) ?: KotlinPlatform.COMMON,
|
||||||
target.compilations.map { KotlinCompilationImpl(it) }.toList(),
|
target.compilations.map { initialCompilation ->
|
||||||
|
(cloningCache[initialCompilation] as? KotlinCompilation) ?: KotlinCompilationImpl(initialCompilation, cloningCache).also {
|
||||||
|
cloningCache[initialCompilation] = it
|
||||||
|
}
|
||||||
|
}.toList(),
|
||||||
KotlinTargetJarImpl(target.jar?.archiveFile)
|
KotlinTargetJarImpl(target.jar?.archiveFile)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -147,9 +156,18 @@ data class KotlinMPPGradleModelImpl(
|
|||||||
override val kotlinNativeHome: String
|
override val kotlinNativeHome: String
|
||||||
) : KotlinMPPGradleModel {
|
) : KotlinMPPGradleModel {
|
||||||
|
|
||||||
constructor(mppModel: KotlinMPPGradleModel) : this(
|
constructor(mppModel: KotlinMPPGradleModel, cloningCache: MutableMap<Any, Any>) : this(
|
||||||
mppModel.sourceSets.mapValues { KotlinSourceSetImpl(it.value) },
|
mppModel.sourceSets.mapValues { initialSourceSet ->
|
||||||
mppModel.targets.map { KotlinTargetImpl(it) }.toList(),
|
(cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(
|
||||||
|
initialSourceSet.value,
|
||||||
|
cloningCache
|
||||||
|
).also { cloningCache[initialSourceSet] = it }
|
||||||
|
},
|
||||||
|
mppModel.targets.map { initialTarget ->
|
||||||
|
(cloningCache[initialTarget] as? KotlinTarget) ?: KotlinTargetImpl(initialTarget, cloningCache).also {
|
||||||
|
cloningCache[initialTarget] = it
|
||||||
|
}
|
||||||
|
}.toList(),
|
||||||
ExtraFeaturesImpl(mppModel.extraFeatures.coroutinesState),
|
ExtraFeaturesImpl(mppModel.extraFeatures.coroutinesState),
|
||||||
mppModel.kotlinNativeHome
|
mppModel.kotlinNativeHome
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user