Fix: Add Native KLIBs as project-level libraries

Issue #KT-30966 Fixed
This commit is contained in:
Dmitriy Dolovov
2019-04-19 10:50:11 +07:00
parent cfa635b36a
commit e188c313e6
2 changed files with 53 additions and 11 deletions
@@ -356,7 +356,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
preprocessDependencies(substitutedDependencies), preprocessDependencies(substitutedDependencies),
ideProject ideProject
) )
KotlinNativeLibrariesNameFixer.applyTo(dataNode) KotlinNativeLibrariesFixer.applyTo(dataNode, ideProject)
for (sourceSet in compilation.sourceSets) { for (sourceSet in compilation.sourceSets) {
if (sourceSet.fullName() == compilation.fullName()) continue if (sourceSet.fullName() == compilation.fullName()) continue
val targetDataNode = getSiblingKotlinModuleData(sourceSet, gradleModule, ideModule, resolverCtx) ?: continue val targetDataNode = getSiblingKotlinModuleData(sourceSet, gradleModule, ideModule, resolverCtx) ?: continue
@@ -9,6 +9,8 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.ProjectKeys import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.LibraryData 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.model.project.ProjectData
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
import com.intellij.openapi.externalSystem.service.project.IdeUIModifiableModelsProvider 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.ExternalMultiLibraryDependency
import org.jetbrains.plugins.gradle.model.FileCollectionDependency import org.jetbrains.plugins.gradle.model.FileCollectionDependency
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData 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 org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import java.io.File 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: * Gradle IDE plugin creates [LibraryData] nodes with internal name consisting of two parts:
// - mandatory "Gradle: " prefix * - mandatory "Gradle: " prefix
// - and library name * - and library name
// Then internal name is propagated to IDE `Library` object, and is displayed in IDE as "Gradle: <LIBRARY_NAME>". * Then internal name is propagated to IDE [Library] object, and is displayed in IDE as "Gradle: <LIBRARY_NAME>".
// KotlinNativeLibrariesNameFixer removes "Gradle: " prefix from all `LibraryData` nodes representing KLIBs. * [KotlinNativeLibrariesFixer] removes "Gradle: " prefix from all [LibraryData] items representing KLIBs to make them
fun applyTo(ownerNode: DataNode<GradleSourceSetData>) { * look more friendly.
for (libraryDependency in ExternalSystemApiUtil.findAll(ownerNode, ProjectKeys.LIBRARY_DEPENDENCY)) { *
val libraryData = libraryDependency.data.target * 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<GradleSourceSetData>, ideProject: DataNode<ProjectData>) {
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")) { 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<ProjectData>) {
GradleProjectResolverUtil.linkProjectLibrary(ideProject, libraryData)
}
private fun fixLibraryDependencyLevel(oldDependencyNode: DataNode<LibraryDependencyData>) {
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 { private sealed class DependencySubstitute {