Fix runtime elements configuration resolved for compile classpath

The existing disambiguation rule for the Usage attribute lead to
runtime variants being resolved even for compile-scoped input
configurations, because Gradle runs disambiguation rules even if the
consumer value is present in the candidates list.

For example, an `app` project's `jvmCompileClasspath` configuration
would get its `project('lib')` dependency resolved to the
`jvmLibRuntimeElements` instead of `jvmLibApiElements`.

Fix this by:
1) running the part of the disambiguation rule only with Gradle 4.1+, so
  as to use the consumer value for proper disambiguation;
2) choosing the JAVA_API usage when the consumer is JAVA_API or
  KOTLIN_API, and choosing one of the JAVA_RUNTIME usages if the
  consumer is either KOTLIN_RUNTIME, one of the JAVA_RUNTIME usages, or
  does not specify its usage.

Issue #KT-27849 Fixed
This commit is contained in:
Sergey Igushkin
2018-10-29 16:28:00 +03:00
parent 43e79035e9
commit f995afd50d
2 changed files with 45 additions and 7 deletions
@@ -65,19 +65,33 @@ object KotlinUsages {
override fun execute(details: MultipleCandidatesDetails<Usage?>) = with(details) {
val candidateNames = candidateValues.map { it?.name }.toSet()
fun chooseCandidateByName(name: String?): Unit = closestMatch(candidateValues.single { it?.name == name }!!)
// if both API and runtime artifacts are chosen according to the compatibility rules, then
// the consumer requested nothing specific, so provide them with the runtime variant, which is more complete:
if (candidateNames.filterNotNull().toSet() == setOf(KOTLIN_RUNTIME, KOTLIN_API)) {
details.closestMatch(candidateValues.single { it?.name == KOTLIN_RUNTIME }!!)
chooseCandidateByName(KOTLIN_RUNTIME)
}
if (JAVA_API in candidateNames && JAVA_RUNTIME_JARS in candidateNames && values.none { it in candidateNames }) {
details.closestMatch(candidateValues.single { it?.name == JAVA_RUNTIME_JARS }!!)
}
if (JAVA_API in candidateNames && JAVA_RUNTIME in candidateNames && values.none { it in candidateNames }) {
details.closestMatch(candidateValues.single { it?.name == JAVA_RUNTIME }!!)
// The consumer value is available and can be used for disambiguation in Gradle 4.1+
if (isGradleVersionAtLeast(4, 1)) {
val javaRuntimeUsages = setOf(JAVA_RUNTIME_JARS, JAVA_RUNTIME)
if (JAVA_API in candidateNames &&
javaRuntimeUsages.any { it in candidateNames } &&
values.none { it in candidateNames }
) {
when (consumerValue?.name) {
KOTLIN_API, JAVA_API ->
chooseCandidateByName(JAVA_API)
null, KOTLIN_RUNTIME, in javaRuntimeUsages ->
chooseCandidateByName(javaRuntimeUsages.first { it in candidateNames })
}
}
}
if (JAVA_RUNTIME_CLASSES in candidateNames && JAVA_RUNTIME_RESOURCES in candidateNames && KOTLIN_RUNTIME in candidateNames) {
closestMatch(candidateValues.single { it?.name == KOTLIN_RUNTIME }!!)
chooseCandidateByName(KOTLIN_RUNTIME)
}
}
}