From e188c313e60a8db8fc25a4ecc28b6a751f95f702 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Fri, 19 Apr 2019 10:50:11 +0700 Subject: [PATCH] Fix: Add Native KLIBs as project-level libraries Issue #KT-30966 Fixed --- .../KotlinMPPGradleProjectResolver.kt | 2 +- .../idea/configuration/nativeLibrariesUtil.kt | 62 ++++++++++++++++--- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt index 5a62f51969f..bf923b43bc3 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt @@ -356,7 +356,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() { preprocessDependencies(substitutedDependencies), ideProject ) - KotlinNativeLibrariesNameFixer.applyTo(dataNode) + KotlinNativeLibrariesFixer.applyTo(dataNode, ideProject) for (sourceSet in compilation.sourceSets) { if (sourceSet.fullName() == compilation.fullName()) continue val targetDataNode = getSiblingKotlinModuleData(sourceSet, gradleModule, ideModule, resolverCtx) ?: continue diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/nativeLibrariesUtil.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/nativeLibrariesUtil.kt index 018d5e6277d..3511e29c3f8 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/nativeLibrariesUtil.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/nativeLibrariesUtil.kt @@ -9,6 +9,8 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.ProjectKeys import com.intellij.openapi.externalSystem.model.project.LibraryData +import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData +import com.intellij.openapi.externalSystem.model.project.LibraryLevel import com.intellij.openapi.externalSystem.model.project.ProjectData import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider import com.intellij.openapi.externalSystem.service.project.IdeUIModifiableModelsProvider @@ -35,6 +37,7 @@ import org.jetbrains.plugins.gradle.model.ExternalLibraryDependency import org.jetbrains.plugins.gradle.model.ExternalMultiLibraryDependency import org.jetbrains.plugins.gradle.model.FileCollectionDependency import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData +import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext import java.io.File @@ -177,20 +180,59 @@ internal class KotlinNativeLibrariesDependencySubstitutor( } } -internal object KotlinNativeLibrariesNameFixer { - // Gradle IDE plugin creates `LibraryData` nodes with internal name consisting of two parts: - // - mandatory "Gradle: " prefix - // - and library name - // Then internal name is propagated to IDE `Library` object, and is displayed in IDE as "Gradle: ". - // KotlinNativeLibrariesNameFixer removes "Gradle: " prefix from all `LibraryData` nodes representing KLIBs. - fun applyTo(ownerNode: DataNode) { - for (libraryDependency in ExternalSystemApiUtil.findAll(ownerNode, ProjectKeys.LIBRARY_DEPENDENCY)) { - val libraryData = libraryDependency.data.target +/** + * Gradle IDE plugin creates [LibraryData] nodes with internal name consisting of two parts: + * - mandatory "Gradle: " prefix + * - and library name + * Then internal name is propagated to IDE [Library] object, and is displayed in IDE as "Gradle: ". + * [KotlinNativeLibrariesFixer] removes "Gradle: " prefix from all [LibraryData] items representing KLIBs to make them + * look more friendly. + * + * Also, [KotlinNativeLibrariesFixer] makes sure that all KLIBs from Kotlin/Native distribution are added to IDE project model + * as project-level libraries. This is necessary until the appropriate fix in IDEA will be implemented (for details see IDEA-211451). + */ +internal object KotlinNativeLibrariesFixer { + fun applyTo(ownerNode: DataNode, ideProject: DataNode) { + for (libraryDependencyNode in ExternalSystemApiUtil.findAll(ownerNode, ProjectKeys.LIBRARY_DEPENDENCY)) { + val libraryData = libraryDependencyNode.data.target + + // Only KLIBs from Kotlin/Native distribution can have such prefix: if (libraryData.internalName.startsWith("$GRADLE_LIBRARY_PREFIX$KOTLIN_NATIVE_LIBRARY_PREFIX")) { - libraryData.internalName = libraryData.internalName.substringAfter(GRADLE_LIBRARY_PREFIX) + fixLibraryName(libraryData) + addLibraryToProjectModel(libraryData, ideProject) + fixLibraryDependencyLevel(libraryDependencyNode) } } } + + private fun fixLibraryName(libraryData: LibraryData) { + libraryData.internalName = libraryData.internalName.substringAfter(GRADLE_LIBRARY_PREFIX) + } + + private fun addLibraryToProjectModel(libraryData: LibraryData, ideProject: DataNode) { + GradleProjectResolverUtil.linkProjectLibrary(ideProject, libraryData) + } + + private fun fixLibraryDependencyLevel(oldDependencyNode: DataNode) { + val oldDependency = oldDependencyNode.data + if (oldDependency.level == LibraryLevel.PROJECT) return // nothing to do + + val newDependency = LibraryDependencyData(oldDependency.ownerModule, oldDependency.target, LibraryLevel.PROJECT).apply { + scope = oldDependency.scope + order = oldDependency.order + isExported = oldDependency.isExported + } + + val parentNode = oldDependencyNode.parent ?: return + val childNodes = oldDependencyNode.children + + val newDependencyNode = parentNode.createChild(oldDependencyNode.key, newDependency) + for (child in childNodes) { + newDependencyNode.addChild(child) + } + + oldDependencyNode.clear(true) + } } private sealed class DependencySubstitute {