[Gradle] Ide Dependency Resolution: Provide attributes for binary coordinates

^KT-60053 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-07-12 16:35:43 +02:00
committed by Space Team
parent 6140854fa6
commit 3032d02ce9
23 changed files with 1478 additions and 63 deletions
@@ -298,34 +298,45 @@ public final class org/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinStringEx
public fun serialize (Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinSerializationContext;Ljava/lang/String;)[B
}
public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability : java/io/Serializable {
public static final field serialVersionUID J
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability;
public abstract interface class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes : java/io/Serializable, java/util/Map, kotlin/jvm/internal/markers/KMappedMarker {
}
public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributesKt {
public static final fun IdeaKotlinBinaryAttributes ()Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;
public static final fun IdeaKotlinBinaryAttributes (Ljava/util/Map;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;
}
public abstract interface class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability : java/io/Serializable {
public abstract fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability;
public abstract fun getGroup ()Ljava/lang/String;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getVersion ()Ljava/lang/String;
}
public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability$DefaultImpls {
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability;
public fun equals (Ljava/lang/Object;)Z
public final fun getGroup ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
public final fun getVersion ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapabilityKt {
public static final fun IdeaKotlinBinaryCapability (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCapability;
}
public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates : org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependencyCoordinates {
public static final field serialVersionUID J
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryCoordinates;
public fun equals (Ljava/lang/Object;)Z
public final fun getAttributes ()Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinBinaryAttributes;
public final fun getCapabilities ()Ljava/util/Set;
public final fun getDisplayString ()Ljava/lang/String;
public final fun getGroup ()Ljava/lang/String;
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2023 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.idea.tcs
import org.jetbrains.kotlin.gradle.idea.utils.stringInterner
import org.jetbrains.kotlin.tooling.core.WeakInterner
import java.io.Serializable
fun IdeaKotlinBinaryAttributes(attributes: Map<String, String>): IdeaKotlinBinaryAttributes {
return IdeaKotlinBinaryAttributesImpl.createAndIntern(attributes)
}
fun IdeaKotlinBinaryAttributes(): IdeaKotlinBinaryAttributes {
return IdeaKotlinBinaryAttributesImpl.createAndIntern(emptyMap())
}
/**
* Representing the 'Gradle attributes' associated with a given binary.
* This can be used to identify binaries further than just their maven coordinates.
*/
@IdeaKotlinModel
sealed interface IdeaKotlinBinaryAttributes : Map<String, String>, Serializable
private class IdeaKotlinBinaryAttributesImpl private constructor(
private val attributes: Map<String, String>,
) : IdeaKotlinBinaryAttributes, Map<String, String> by attributes {
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is IdeaKotlinBinaryAttributesImpl) return false
return this.attributes == other.attributes
}
override fun hashCode(): Int {
return attributes.hashCode()
}
override fun toString(): String {
return attributes.toString()
}
companion object {
const val serialVersionUID = 0L
private val interner = WeakInterner()
internal fun createAndIntern(attributes: Map<String, String>): IdeaKotlinBinaryAttributes {
val internedMap = attributes.map { (key, value) -> stringInterner.getOrPut(key) to stringInterner.getOrPut(value) }.toMap()
return interner.getOrPut(IdeaKotlinBinaryAttributesImpl(internedMap))
}
}
}
@@ -5,8 +5,17 @@
package org.jetbrains.kotlin.gradle.idea.tcs
import org.jetbrains.kotlin.gradle.idea.utils.stringInterner
import java.io.Serializable
fun IdeaKotlinBinaryCapability(group: String, name: String, version: String?): IdeaKotlinBinaryCapability {
return IdeaKotlinBinaryCapabilityImpl(
group = stringInterner.getOrPut(group),
name = stringInterner.getOrPut(name),
version = if (version != null) stringInterner.getOrPut(version) else null
)
}
/**
* Several variants can be published under a given set of maven coordinates (group, module, version),
* Capabilities can classify those variants in a way that e.g. two variants with the same maven coordinates
@@ -21,12 +30,24 @@ import java.io.Serializable
* @since 1.9.20
*/
@IdeaKotlinModel
class IdeaKotlinBinaryCapability(
val group: String,
val name: String,
val version: String?,
) : Serializable {
internal companion object {
sealed interface IdeaKotlinBinaryCapability : Serializable {
val group: String
val name: String
val version: String?
fun copy(
group: String = this.group,
name: String = this.name,
version: String? = this.version,
): IdeaKotlinBinaryCapability
}
private class IdeaKotlinBinaryCapabilityImpl(
override val group: String,
override val name: String,
override val version: String?,
) : IdeaKotlinBinaryCapability {
companion object {
const val serialVersionUID = 0L
}
@@ -37,10 +58,10 @@ class IdeaKotlinBinaryCapability(
}
}
fun copy(
group: String = this.group,
name: String = this.name,
version: String? = this.version,
override fun copy(
group: String,
name: String,
version: String?,
): IdeaKotlinBinaryCapability {
return IdeaKotlinBinaryCapability(group = group, name = name, version = version)
}
@@ -23,6 +23,12 @@ class IdeaKotlinBinaryCoordinates(
* @since 1.9.20
*/
val capabilities: Set<IdeaKotlinBinaryCapability> = emptySet(),
/**
* @see IdeaKotlinBinaryAttributes
* @since 1.9.20
*/
val attributes: IdeaKotlinBinaryAttributes = IdeaKotlinBinaryAttributes(),
) : IdeaKotlinDependencyCoordinates {
constructor(
@@ -55,6 +61,9 @@ class IdeaKotlinBinaryCoordinates(
if (capabilities.isNotEmpty()) {
append(capabilities.joinToString(", ", "(", ")"))
}
if (attributes.isNotEmpty()) {
append("+attributes(${attributes.hashCode()})")
}
}
/**
@@ -119,7 +128,7 @@ class IdeaKotlinBinaryCoordinates(
if (version != other.version) return false
if (sourceSetName != other.sourceSetName) return false
if (capabilities != other.capabilities) return false
if (attributes != other.attributes) return false
return true
}
@@ -129,6 +138,7 @@ class IdeaKotlinBinaryCoordinates(
result = 31 * result + (version?.hashCode() ?: 0)
result = 31 * result + (sourceSetName?.hashCode() ?: 0)
result = 31 * result + capabilities.hashCode()
result = 31 * result + attributes.hashCode()
return result
}
@@ -146,7 +156,8 @@ class IdeaKotlinBinaryCoordinates(
module = module,
version = version,
sourceSetName = sourceSetName,
capabilities = capabilities
capabilities = capabilities,
attributes = attributes,
)
}
@@ -156,13 +167,15 @@ class IdeaKotlinBinaryCoordinates(
version: String? = this.version,
sourceSetName: String? = this.sourceSetName,
capabilities: Set<IdeaKotlinBinaryCapability> = this.capabilities,
attributes: IdeaKotlinBinaryAttributes = this.attributes,
): IdeaKotlinBinaryCoordinates {
return IdeaKotlinBinaryCoordinates(
group = group,
module = module,
version = version,
sourceSetName = sourceSetName,
capabilities = capabilities
capabilities = capabilities,
attributes = attributes
)
}
@@ -184,10 +197,14 @@ class IdeaKotlinBinaryCoordinates(
* will be 'null'. In this case we use the 'copy' function to provide an instance that will have an emptySet instead.
*/
private fun readResolve(): Any {
@Suppress("SENSELESS_COMPARISON")
if (capabilities == null) {
return copy(capabilities = emptySet())
@Suppress("SENSELESS_COMPARISON", "USELESS_ELVIS")
if (capabilities == null || attributes == null) {
return copy(
capabilities = capabilities ?: emptySet(),
attributes = attributes ?: IdeaKotlinBinaryAttributes()
)
}
return this
}
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2023 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.idea.utils
import org.jetbrains.kotlin.tooling.core.WeakInterner
/**
* Can be used for all entities in this module to intern strings
*/
internal val stringInterner = WeakInterner()
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2023 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.idea.test.tcs
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryAttributes
import kotlin.test.*
class IdeaKotlinBinaryAttributesTest {
@Test
fun `test - empty instance is same`() {
val instance1 = IdeaKotlinBinaryAttributes()
val instance2 = IdeaKotlinBinaryAttributes()
assertSame(instance1, instance2)
}
@Test
fun `test - equal instances are same`() {
val instance1 = IdeaKotlinBinaryAttributes(
mapOf("a" to "valueA", "b" to "valueB")
)
val instance2 = IdeaKotlinBinaryAttributes(
mapOf("a" to "valueA", "b" to "valueB")
)
assertSame(instance1, instance2)
}
@Test
fun `test - instances string values are same`() {
val instance1 = IdeaKotlinBinaryAttributes(
mapOf("a" to "valueA", "b" to "valueB", "c" to "xxx")
)
val instance2 = IdeaKotlinBinaryAttributes(
mapOf("a" to "valueA", "b" to "valueB", "c" to "yyy")
)
assertNotSame(instance1, instance2)
assertNotEquals(instance1, instance2)
instance1.keys.toList().forEachIndexed { index, key ->
assertSame(key, instance2.keys.toList()[index])
}
assertSame(instance1["a"], instance2["a"])
assertSame(instance1["b"], instance2["b"])
assertEquals("valueA", instance1["a"])
assertEquals("valueB", instance1["b"])
assertEquals("xxx", instance1["c"])
assertEquals("yyy", instance2["c"])
}
}
@@ -5,10 +5,13 @@
package org.jetbrains.kotlin.gradle.idea.test.tcs
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryAttributes
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCapability
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotSame
class IdeaKotlinBinaryCoordinatesTest {
@@ -108,7 +111,7 @@ class IdeaKotlinBinaryCoordinatesTest {
assertEquals("myGroup:myModule-foo:1.0.0:commonMain", coordinates.displayString)
assertEquals(
"myGroup:myModule:1.0.0:commonMain(myGroup:myModule-foo:1.0.0, notMyGroup:myModule-foo:1.0.0, notMyGroupEither:myModule-foo)",
"myGroup:myModule:commonMain:1.0.0(myGroup:myModule-foo:1.0.0, notMyGroup:myModule-foo:1.0.0, notMyGroupEither:myModule-foo)",
coordinates.identityString
)
}
@@ -123,11 +126,48 @@ class IdeaKotlinBinaryCoordinatesTest {
IdeaKotlinBinaryCapability("notMyGroup", "myModule-foo", null),
)
)
assertEquals("myGroup:myModule-(foo, bar):1.0.0:commonMain", coordinates.displayString)
assertEquals("myGroup:myModule-(foo, bar):commonMain:1.0.0", coordinates.displayString)
assertEquals(
"myGroup:myModule:1.0.0:commonMain(myGroup:myModule-foo:1.0.0, myGroup:myModule-bar:1.0.0, notMyGroup:myModule-foo)",
"myGroup:myModule:commonMain:1.0.0(myGroup:myModule-foo:1.0.0, myGroup:myModule-bar:1.0.0, notMyGroup:myModule-foo)",
coordinates.identityString
)
}
@Test
fun `test - displayString & identityString - sample 9`() {
val coordinates = IdeaKotlinBinaryCoordinates(
"myGroup", "myModule", "1.0.0", "commonMain",
capabilities = setOf(
IdeaKotlinBinaryCapability("myGroup", "myModule-foo", "1.0.0"),
IdeaKotlinBinaryCapability("myGroup", "myModule-bar", "1.0.0"),
IdeaKotlinBinaryCapability("notMyGroup", "myModule-foo", null),
),
attributes = IdeaKotlinBinaryAttributes(
mapOf("a" to "valueA")
)
)
assertEquals("myGroup:myModule-(foo, bar):commonMain:1.0.0", coordinates.displayString)
assertEquals(
"myGroup:myModule:commonMain:1.0.0(myGroup:myModule-foo:1.0.0, myGroup:myModule-bar:1.0.0, notMyGroup:myModule-foo)+attributes(-823812975)",
coordinates.identityString
)
}
@Test
fun `test - equals`() {
val baseline = IdeaKotlinBinaryCoordinates(
"a", "b", "c", "d",
capabilities = setOf(IdeaKotlinBinaryCapability("x", "y", "z")),
attributes = IdeaKotlinBinaryAttributes(mapOf("a" to "valueA"))
)
assertNotSame(baseline, baseline.copy())
assertEquals(baseline, baseline.copy())
assertEquals(baseline.hashCode(), baseline.copy().hashCode())
assertEquals(baseline.identityString, baseline.copy().identityString)
assertNotEquals(baseline, baseline.copy(sourceSetName = null))
assertNotEquals(baseline, baseline.copy(capabilities = emptySet()))
assertNotEquals(baseline, baseline.copy(attributes = IdeaKotlinBinaryAttributes()))
}
}