[KPM] Implement initial kpm/idea dependency resolution

^KT-51386 Verification Pending
This commit is contained in:
sebastian.sellmair
2022-03-07 11:12:22 +01:00
committed by Space
parent 8b84ed4978
commit 1a5fc84080
61 changed files with 2278 additions and 120 deletions
@@ -1,5 +1,6 @@
plugins {
kotlin("jvm")
`java-test-fixtures`
}
object BackwardsCompatibilityTestConfiguration {
@@ -18,9 +19,14 @@ dependencies {
testImplementation(gradleKotlinDsl())
testImplementation(project(":kotlin-gradle-plugin"))
testImplementation(project(":kotlin-test:kotlin-test-junit"))
testImplementation("org.reflections:reflections:0.10.2") {
because("Tests on the object graph are performed. This library will find implementations of interfaces at runtime")
}
testFixturesImplementation(gradleApi())
testFixturesImplementation(gradleKotlinDsl())
testFixturesImplementation(project(":kotlin-test:kotlin-test-junit"))
}
publish()
@@ -39,7 +45,13 @@ run {
val version = if (isSnapshotTest) properties["defaultSnapshotVersion"].toString()
else BackwardsCompatibilityTestConfiguration.minimalBackwardsCompatibleVersion
val minimalBackwardsCompatibleVersionTestClasspath by configurations.creating
val minimalBackwardsCompatibleVersionTestClasspath by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
}
}
dependencies {
minimalBackwardsCompatibleVersionTestClasspath("org.jetbrains.kotlin:kotlin-gradle-plugin-idea:$version")
@@ -51,9 +63,17 @@ run {
if (isSnapshotTest) logger.quiet("Running test against snapshot: $version")
else logger.quiet("Running test against $version")
val resolvedClasspath = minimalBackwardsCompatibleVersionTestClasspath.files
if (resolvedClasspath.none { "kotlin-gradle-plugin-idea-$version.jar" in it.path }) {
throw IllegalStateException(buildString {
appendLine("Bad backwardsCompatibilityClasspath: $resolvedClasspath")
appendLine("Dependencies:${minimalBackwardsCompatibleVersionTestClasspath.allDependencies.joinToString()}")
})
}
systemProperty(
"backwardsCompatibilityClasspath",
minimalBackwardsCompatibleVersionTestClasspath.files.joinToString(";") { it.absolutePath }
resolvedClasspath.joinToString(";") { it.absolutePath }
)
}
}
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.kpm.idea
import org.jetbrains.kotlin.gradle.kpm.KotlinExternalModelContainer
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinDependency.Companion.CLASSPATH_BINARY_TYPE
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinDependency.Companion.DOCUMENTATION_BINARY_TYPE
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinDependency.Companion.SOURCES_BINARY_TYPE
import java.io.File
import java.io.Serializable
sealed interface IdeaKotlinDependency : Serializable {
val external: KotlinExternalModelContainer
companion object {
const val CLASSPATH_BINARY_TYPE = "org.jetbrains.binary.type.classpath"
const val SOURCES_BINARY_TYPE = "org.jetbrains.binary.type.sources"
const val DOCUMENTATION_BINARY_TYPE = "org.jetbrains.binary.type.documentation"
}
}
sealed interface IdeaKotlinSourceDependency : IdeaKotlinDependency {
val buildId: String
val projectPath: String
val projectName: String
val kotlinModuleName: String
val kotlinModuleClassifier: String?
val kotlinFragmentName: String
}
sealed interface IdeaKotlinBinaryCoordinates : Serializable {
val group: String
val module: String
val version: String
val kotlinModuleName: String?
val kotlinFragmentName: String?
}
sealed interface IdeaKotlinBinaryDependency : IdeaKotlinDependency {
val coordinates: IdeaKotlinBinaryCoordinates?
}
sealed interface IdeaKotlinUnresolvedBinaryDependency : IdeaKotlinBinaryDependency {
val cause: String?
}
sealed interface IdeaKotlinResolvedBinaryDependency : IdeaKotlinBinaryDependency {
val binaryType: String
val binaryFile: File
}
val IdeaKotlinResolvedBinaryDependency.isSourcesType get() = binaryType == SOURCES_BINARY_TYPE
val IdeaKotlinResolvedBinaryDependency.isDocumentationType get() = binaryType == DOCUMENTATION_BINARY_TYPE
val IdeaKotlinResolvedBinaryDependency.isClasspathType get() = binaryType == CLASSPATH_BINARY_TYPE
@InternalKotlinGradlePluginApi
data class IdeaKotlinSourceDependencyImpl(
override val buildId: String,
override val projectPath: String,
override val projectName: String,
override val kotlinModuleName: String,
override val kotlinModuleClassifier: String?,
override val kotlinFragmentName: String,
override val external: KotlinExternalModelContainer = KotlinExternalModelContainer.Empty
) : IdeaKotlinSourceDependency {
override fun toString(): String {
return "project://$buildId:$projectPath:$kotlinModuleName:$kotlinFragmentName"
}
@InternalKotlinGradlePluginApi
companion object {
private const val serialVersionUID = 0L
}
}
@InternalKotlinGradlePluginApi
data class IdeaKotlinBinaryCoordinatesImpl(
override val group: String,
override val module: String,
override val version: String,
override val kotlinModuleName: String? = null,
override val kotlinFragmentName: String? = null
) : IdeaKotlinBinaryCoordinates {
override fun toString(): String {
return "$group:$module:$version" +
(if (kotlinModuleName != null) ":$kotlinModuleName" else "") +
(if (kotlinFragmentName != null) ":$kotlinFragmentName" else "")
}
companion object {
private const val serialVersionUID = 0L
}
}
@InternalKotlinGradlePluginApi
data class IdeaKotlinResolvedBinaryDependencyImpl(
override val coordinates: IdeaKotlinBinaryCoordinates?,
override val binaryType: String,
override val binaryFile: File,
override val external: KotlinExternalModelContainer = KotlinExternalModelContainer.Empty
) : IdeaKotlinResolvedBinaryDependency {
override fun toString(): String {
return "${binaryType.split(".").last()}://$coordinates/${binaryFile.name}"
}
@InternalKotlinGradlePluginApi
companion object {
private const val serialVersionUID = 0L
}
}
@InternalKotlinGradlePluginApi
data class IdeaKotlinUnresolvedBinaryDependencyImpl(
override val cause: String?,
override val coordinates: IdeaKotlinBinaryCoordinates?,
override val external: KotlinExternalModelContainer = KotlinExternalModelContainer.Empty
) : IdeaKotlinUnresolvedBinaryDependency {
@InternalKotlinGradlePluginApi
companion object {
private const val serialVersionUID = 0L
}
}
@@ -11,8 +11,9 @@ import java.io.Serializable
interface IdeaKotlinFragment : Serializable {
val name: String
val moduleIdentifier: IdeaKotlinModuleIdentifier
val platforms: Set<IdeaKotlinPlatform>
val languageSettings: IdeaKotlinLanguageSettings?
val dependencies: List<IdeaKotlinFragmentDependency>
val dependencies: List<IdeaKotlinDependency>
val directRefinesDependencies: List<IdeaKotlinFragment>
val sourceDirectories: List<IdeaKotlinSourceDirectory>
val resourceDirectories: List<IdeaKotlinResourceDirectory>
@@ -23,8 +24,9 @@ interface IdeaKotlinFragment : Serializable {
data class IdeaKotlinFragmentImpl(
override val name: String,
override val moduleIdentifier: IdeaKotlinModuleIdentifier,
override val platforms: Set<IdeaKotlinPlatform>,
override val languageSettings: IdeaKotlinLanguageSettings?,
override val dependencies: List<IdeaKotlinFragmentDependency>,
override val dependencies: List<IdeaKotlinDependency>,
override val directRefinesDependencies: List<IdeaKotlinFragment>,
override val sourceDirectories: List<IdeaKotlinSourceDirectory>,
override val resourceDirectories: List<IdeaKotlinResourceDirectory>,
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.kpm.idea
import java.io.Serializable
interface IdeaKotlinFragmentDependency : Serializable
@Suppress("unused")
@InternalKotlinGradlePluginApi
class IdeaKotlinFragmentDependencyImpl: IdeaKotlinFragmentDependency {
@InternalKotlinGradlePluginApi
companion object {
const val serialVersionUID = 0L
}
}
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.gradle.kpm.idea
import java.io.Serializable
interface IdeaKotlinModule : Serializable {
val name: String
val moduleIdentifier: IdeaKotlinModuleIdentifier
val fragments: List<IdeaKotlinFragment>
}
@InternalKotlinGradlePluginApi
data class IdeaKotlinModuleImpl(
override val name: String,
override val moduleIdentifier: IdeaKotlinModuleIdentifier,
override val fragments: List<IdeaKotlinFragment>
) : IdeaKotlinModule {
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("unused")
package org.jetbrains.kotlin.gradle.kpm.idea
import java.io.Serializable
sealed interface IdeaKotlinPlatform : Serializable {
val platformType: String
val platformDetails: IdeaKotlinPlatformDetails?
companion object {
val unknown: IdeaKotlinPlatform = IdeaKotlinPlatformImpl("unknown", null)
const val wasmPlatformType = "wasm"
const val nativePlatformType = "native"
const val jvmPlatformType = "jvm"
const val jsPlatformType = "js"
}
}
sealed interface IdeaKotlinPlatformDetails : Serializable
sealed interface IdeaKotlinWasmPlatformDetails : IdeaKotlinPlatformDetails
sealed interface IdeaKotlinNativePlatformDetails : IdeaKotlinPlatformDetails {
val konanTarget: String
}
sealed interface IdeaKotlinJvmPlatformDetails : IdeaKotlinPlatformDetails {
val jvmTarget: String
}
sealed interface IdeaKotlinJsPlatformDetails : IdeaKotlinPlatformDetails {
val isIr: Boolean
}
@InternalKotlinGradlePluginApi
fun IdeaKotlinPlatform.Companion.wasm(): IdeaKotlinPlatform {
return IdeaKotlinPlatformImpl(wasmPlatformType, IdeaKotlinWasmPlatformDetailsImpl)
}
@InternalKotlinGradlePluginApi
fun IdeaKotlinPlatform.Companion.native(konanTarget: String): IdeaKotlinPlatform {
return IdeaKotlinPlatformImpl(nativePlatformType, IdeaKotlinNativePlatformDetailsImpl(konanTarget))
}
@InternalKotlinGradlePluginApi
fun IdeaKotlinPlatform.Companion.jvm(jvmTarget: String): IdeaKotlinPlatform {
return IdeaKotlinPlatformImpl(jvmPlatformType, IdeaKotlinJvmPlatformDetailsImpl(jvmTarget))
}
@InternalKotlinGradlePluginApi
fun IdeaKotlinPlatform.Companion.js(isIr: Boolean): IdeaKotlinPlatform {
return IdeaKotlinPlatformImpl(jsPlatformType, IdeaKotlinJsPlatformDetailsImpl(isIr))
}
val IdeaKotlinPlatform.isWasm get() = platformType == IdeaKotlinPlatform.wasmPlatformType
val IdeaKotlinPlatform.isNative get() = platformType == IdeaKotlinPlatform.nativePlatformType
val IdeaKotlinPlatform.isJvm get() = platformType == IdeaKotlinPlatform.jvmPlatformType
val IdeaKotlinPlatform.isJs get() = platformType == IdeaKotlinPlatform.jsPlatformType
val IdeaKotlinPlatform.nativeOrNull get() = (platformDetails as? IdeaKotlinNativePlatformDetails)
val IdeaKotlinPlatform.jvmOrNull get() = (platformDetails as? IdeaKotlinJvmPlatformDetails)
val IdeaKotlinPlatform.jsOrNull get() = (platformDetails as? IdeaKotlinJsPlatformDetails)
private data class IdeaKotlinPlatformImpl(
override val platformType: String, override val platformDetails: IdeaKotlinPlatformDetails?
) : IdeaKotlinPlatform {
companion object {
const val serialVersionUID = 0L
}
}
private object IdeaKotlinWasmPlatformDetailsImpl : IdeaKotlinWasmPlatformDetails {
private const val serialVersionUID = 0L
}
private data class IdeaKotlinJvmPlatformDetailsImpl(override val jvmTarget: String) : IdeaKotlinJvmPlatformDetails {
private companion object {
const val serialVersionUID = 0L
}
}
private data class IdeaKotlinNativePlatformDetailsImpl(override val konanTarget: String) : IdeaKotlinNativePlatformDetails {
private companion object {
const val serialVersionUID = 0L
}
}
private data class IdeaKotlinJsPlatformDetailsImpl(override val isIr: Boolean) : IdeaKotlinJsPlatformDetails {
private companion object {
const val serialVersionUID = 0L
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.kpm.idea
import java.io.Serializable
interface IdeaKotlinVariant : IdeaKotlinFragment, Serializable {
val platform: IdeaKotlinPlatform
val variantAttributes: Map<String, String>
val compilationOutputs: IdeaKotlinCompilationOutput
}
@@ -15,6 +16,7 @@ interface IdeaKotlinVariant : IdeaKotlinFragment, Serializable {
@InternalKotlinGradlePluginApi
data class IdeaKotlinVariantImpl(
internal val fragment: IdeaKotlinFragment,
override val platform: IdeaKotlinPlatform,
override val variantAttributes: Map<String, String>,
override val compilationOutputs: IdeaKotlinCompilationOutput,
) : IdeaKotlinVariant, IdeaKotlinFragment by fragment {
@@ -1,4 +1,5 @@
import org.gradle.api.Project
import org.gradle.api.artifacts.verification.DependencyVerificationMode
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.configurationcache.extensions.serviceOf
import org.gradle.testfixtures.ProjectBuilder
@@ -20,5 +21,8 @@ fun Project.buildIdeaKotlinProjectModel(): IdeaKotlinProjectModel {
fun createKpmProject(): Pair<ProjectInternal, KotlinPm20ProjectExtension> {
val project = ProjectBuilder.builder().build() as ProjectInternal
project.plugins.apply(KotlinPm20PluginWrapper::class.java)
project.gradle.startParameter.dependencyVerificationMode = DependencyVerificationMode.OFF
project.repositories.mavenLocal()
project.repositories.maven { it.setUrl("https://cache-redirector.jetbrains.com/maven-central") }
return project to project.extensions.getByType(KotlinPm20ProjectExtension::class.java)
}
@@ -5,8 +5,8 @@
package org.jetbrains.kotlin.gradle.kpm
import deserialize
import serialize
import org.jetbrains.kotlin.gradle.kpm.idea.testFixtures.deserialize
import org.jetbrains.kotlin.gradle.kpm.idea.testFixtures.serialize
import java.io.Serializable
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -10,23 +10,20 @@ package org.jetbrains.kotlin.gradle.kpm.idea
import buildIdeaKotlinProjectModel
import createKpmProject
import createProxyInstance
import deserialize
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.configurationcache.extensions.serviceOf
import org.gradle.kotlin.dsl.create
import org.gradle.testfixtures.ProjectBuilder
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.gradle.kpm.KotlinExternalModelKey
import org.jetbrains.kotlin.gradle.kpm.KotlinExternalModelSerializer.Companion.serializable
import org.jetbrains.kotlin.gradle.kpm.external.ExternalVariantApi
import org.jetbrains.kotlin.gradle.kpm.external.external
import org.jetbrains.kotlin.gradle.kpm.idea.testFixtures.deserialize
import org.jetbrains.kotlin.gradle.kpm.idea.testFixtures.serialize
import org.jetbrains.kotlin.gradle.plugin.KotlinPm20PluginWrapper
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinIosX64Variant
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinLinuxX64Variant
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.jvm
import serialize
import unwrapProxyInstance
import java.io.File
import java.io.Serializable
@@ -0,0 +1,75 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.kpm.idea.testFixtures
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinBinaryCoordinates
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinBinaryDependency
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinResolvedBinaryDependency
import java.io.File
fun buildIdeaKotlinDependencyMatchers(any: Any?): List<IdeaKotlinDependencyMatcher> {
return when (any) {
null -> emptyList()
is IdeaKotlinDependencyMatcher -> listOf(any)
is String -> listOf(IdeaKotlinDependencyMatcher.Coordinates(parseIdeaKotlinBinaryCoordinates(any)))
is Regex -> listOf(IdeaKotlinDependencyMatcher.CoordinatesRegex(any))
is File -> listOf(IdeaKotlinDependencyMatcher.BinaryFile(any))
is Iterable<*> -> any.flatMap { child -> buildIdeaKotlinDependencyMatchers(child) }
else -> error("Can't build ${IdeaKotlinDependencyMatcher::class.simpleName} from $any")
}
}
interface IdeaKotlinDependencyMatcher {
val description: String
fun matches(dependency: IdeaKotlinDependency): Boolean
class Coordinates(
private val coordinates: IdeaKotlinBinaryCoordinates
) : IdeaKotlinDependencyMatcher {
override val description: String = coordinates.toString()
override fun matches(dependency: IdeaKotlinDependency): Boolean {
return dependency is IdeaKotlinBinaryDependency && coordinates == dependency.coordinates
}
}
class CoordinatesRegex(
private val regex: Regex
) : IdeaKotlinDependencyMatcher {
override val description: String = regex.pattern
override fun matches(dependency: IdeaKotlinDependency): Boolean {
return dependency is IdeaKotlinBinaryDependency && regex.matches(dependency.coordinates.toString())
}
}
class BinaryFile(
private val binaryFile: File
) : IdeaKotlinDependencyMatcher {
override val description: String = binaryFile.path
override fun matches(dependency: IdeaKotlinDependency): Boolean {
return dependency is IdeaKotlinResolvedBinaryDependency && dependency.binaryFile == binaryFile
}
}
class InDirectory(
private val parentFile: File
) : IdeaKotlinDependencyMatcher {
constructor(parentFilePath: String) : this(File(parentFilePath))
override val description: String = "$parentFile/**"
override fun matches(dependency: IdeaKotlinDependency): Boolean {
return dependency is IdeaKotlinResolvedBinaryDependency &&
dependency.binaryFile.absoluteFile.normalize().canonicalPath.startsWith(
parentFile.absoluteFile.normalize().canonicalPath
)
}
}
}
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.kpm.idea.testFixtures
import org.jetbrains.kotlin.gradle.kpm.idea.*
import kotlin.test.fail
fun IdeaKotlinProjectModel.assertIsNotEmpty(): IdeaKotlinProjectModel = apply {
if (this.modules.isEmpty()) fail("Expected at least one module in model")
}
fun IdeaKotlinProjectModel.assertContainsModule(name: String): IdeaKotlinModule {
return modules.find { it.name == name }
?: fail("Missing module with name '$name'. Found: ${modules.map { it.name }}")
}
fun IdeaKotlinModule.assertContainsFragment(name: String): IdeaKotlinFragment {
return fragments.find { it.name == name }
?: fail("Missing fragment with name '$name'. Found: ${fragments.map { it.name }}")
}
fun IdeaKotlinFragment.assertResolvedBinaryDependencies(
binaryType: String,
matchers: Set<IdeaKotlinDependencyMatcher>
): Set<IdeaKotlinResolvedBinaryDependency> {
val resolvedBinaryDependencies = dependencies
.mapNotNull { dependency ->
when (dependency) {
is IdeaKotlinResolvedBinaryDependencyImpl -> dependency
is IdeaKotlinUnresolvedBinaryDependencyImpl -> fail("Unexpected unresolved dependency: $dependency")
is IdeaKotlinSourceDependencyImpl -> null
}
}
.filter { it.binaryType == binaryType }
.toSet()
val unexpectedResolvedBinaryDependencies = resolvedBinaryDependencies
.filter { dependency -> matchers.none { matcher -> matcher.matches(dependency) } }
val missingDependencies = matchers.filter { matcher ->
resolvedBinaryDependencies.none { dependency -> matcher.matches(dependency) }
}
if (unexpectedResolvedBinaryDependencies.isEmpty() && missingDependencies.isEmpty()) {
return resolvedBinaryDependencies
}
fail(
buildString {
if (unexpectedResolvedBinaryDependencies.isNotEmpty()) {
appendLine("${name}: Unexpected dependencies found:")
unexpectedResolvedBinaryDependencies.forEach { unexpectedDependency ->
appendLine(unexpectedDependency)
}
appendLine()
appendLine("Unexpected dependency coordinates:")
unexpectedResolvedBinaryDependencies.forEach { unexpectedDependency ->
appendLine("\"${unexpectedDependency.coordinates}\",")
}
}
if (missingDependencies.isNotEmpty()) {
appendLine()
appendLine("Missing dependencies:")
missingDependencies.forEach { missingDependency ->
appendLine(missingDependency.description)
}
}
appendLine()
appendLine("Resolved Dependency Coordinates:")
resolvedBinaryDependencies.mapNotNull { it.coordinates }.forEach { coordinates ->
appendLine("\"$coordinates\",")
}
}
)
}
@JvmName("assertResolvedBinaryDependenciesByAnyMatcher")
fun IdeaKotlinFragment.assertResolvedBinaryDependencies(
binaryType: String, matchers: Set<Any?>,
) = assertResolvedBinaryDependencies(binaryType, matchers.flatMap { buildIdeaKotlinDependencyMatchers(it) }.toSet())
fun IdeaKotlinFragment.assertResolvedBinaryDependencies(
binaryType: String, vararg matchers: Any?
) = assertResolvedBinaryDependencies(binaryType, matchers.toSet())
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.kpm.idea.testFixtures
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinBinaryCoordinates
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinBinaryCoordinatesImpl
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinBinaryDependency
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKotlinFragment
fun parseIdeaKotlinBinaryCoordinates(coordinates: String): IdeaKotlinBinaryCoordinates {
val parts = coordinates.split(":")
if (parts.size == 3) {
return IdeaKotlinBinaryCoordinatesImpl(parts[0], parts[1], parts[2])
}
if (parts.size == 5) {
return IdeaKotlinBinaryCoordinatesImpl(parts[0], parts[1], parts[2], parts[3], parts[4])
}
throw IllegalArgumentException("Cannot parse $coordinates into ${IdeaKotlinBinaryCoordinates::class.java.simpleName}")
}
fun Iterable<IdeaKotlinBinaryCoordinates>.parsableString() =
joinToString("," + System.lineSeparator(), "", "") { "\"$it\"" }
@Suppress("unused") // Debugging API
fun IdeaKotlinFragment.parsableDependencyCoordinatesString(): String {
return dependencies.filterIsInstance<IdeaKotlinBinaryDependency>()
.mapNotNull { it.coordinates }.toSet()
.parsableString()
}
@@ -1,3 +1,5 @@
package org.jetbrains.kotlin.gradle.kpm.idea.testFixtures
import org.gradle.internal.io.ClassLoaderObjectInputStream
import java.io.*
@@ -6,20 +8,20 @@ import java.io.*
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
internal fun Any.serialize(): ByteArray {
fun Any.serialize(): ByteArray {
return ByteArrayOutputStream().use { byteArrayOutputStream ->
ObjectOutputStream(byteArrayOutputStream).writeObject(this)
byteArrayOutputStream.toByteArray()
}
}
internal inline fun <reified T : Serializable> ByteArray.deserialize(): T {
inline fun <reified T : Serializable> ByteArray.deserialize(): T {
val inputStream = ByteArrayInputStream(this)
val objectInputStream = ObjectInputStream(inputStream)
return objectInputStream.use { it.readObject() } as T
}
internal fun ByteArray.deserialize(classLoader: ClassLoader): Any {
fun ByteArray.deserialize(classLoader: ClassLoader): Any {
val inputStream = ByteArrayInputStream(this)
val objectInputStream = ClassLoaderObjectInputStream(inputStream, classLoader)
return objectInputStream.use { it.readObject() }