Gradle plugin for JVM projects written in Java, Kotlin, Groovy, or Scala; and Android projects written in Java or Kotlin. Provides advice for managing dependencies and other applied plugins
Apache License 2.0
1.66k
stars
116
forks
source link
Incomplete reason explanation on multi capabilities #1170
If there is more than one dependency per sourceSet to the same module, but with different capabilities (like default one vs testFixtures), the reason --id :module explanation is incomplete. It shows only a single explanation of possible routes to dependency instead of all.
Root cause analysis: problem with ComputeAdviceTask toStringCoordinates
The problem is in ComputeAdviceTask:206. The dependencyUsages object is valid before serialization, but the stored object is first wrapped via toStringCoordinates call and there is a problem:
internal fun Map<Coordinates, Set<Usage>>.toStringCoordinates(buildPath: String): Map<String, Set<Usage>> =
map { (key, value) ->
toCoordinatesKey(key, buildPath) to value
}.toMap()
Each calculated via toCoordinatesKey repeated key is simply lost in favor of the last one which just rewrites the map.
Root cause analysis: problem with ReasonTask getUsageFor
The fix of toStringCoordinates is not enough as there is the second place where the reason explanation blocks are squashed as well. There is a sorting method
private fun getUsageFor(id: String): Set<Usage> {
return dependencyUsages.entries.find(id::equalsKey)?.value?.toSortedSet(Usage.BY_VARIANT)
?: annotationProcessorUsages.entries.find(id::equalsKey)?.value?.toSortedSet(Usage.BY_VARIANT)
which calls toSortedSet and it uses TreeSet under the hood. The problem is that even if there are Usage elements which are non-equal via equals, they are squashed if compareTo()==0 from sorting comparator. So it should be addressed too.
Before and after
The sample difference of reason task explanations before the fix:
...
Source: main
------------
(no usages)
...
vs after
...
Source: main
------------
* Uses 17 classes, 5 of which are shown: com.acme.Class1, com.acme.Class2, com.acme.Class3, com.acme.Class4, com.acme.Class5 (implies implementation).
* Provides 1 service loader: com.acme.MetaService (implies runtimeOnly).
Source: main
------------
(no usages)
Further plan
Once we agree on how to approach the issue I'd like to implement a functional test covering it. Existing functional tests seem to be fine.
Also it makes sense to enhance the output reason task explanation in case if Source: x is repeated, e.g. Source: x (via module-dependency-test-fixtures) specifying the according capabilities.
If there is more than one dependency per sourceSet to the same module, but with different capabilities (like default one vs
testFixtures
), thereason --id :module
explanation is incomplete. It shows only a single explanation of possible routes to dependency instead of all.Root cause analysis: problem with ComputeAdviceTask toStringCoordinates
The problem is in
ComputeAdviceTask:206
. ThedependencyUsages
object is valid before serialization, but the stored object is first wrapped viatoStringCoordinates
call and there is a problem:Each calculated via
toCoordinatesKey
repeated key is simply lost in favor of the last one which just rewrites the map.Root cause analysis: problem with ReasonTask getUsageFor
The fix of
toStringCoordinates
is not enough as there is the second place where the reason explanation blocks are squashed as well. There is a sorting methodwhich calls
toSortedSet
and it usesTreeSet
under the hood. The problem is that even if there areUsage
elements which are non-equal viaequals
, they are squashed ifcompareTo()==0
from sorting comparator. So it should be addressed too.Before and after
The sample difference of
reason
task explanations before the fix:vs after
Further plan
Once we agree on how to approach the issue I'd like to implement a functional test covering it. Existing functional tests seem to be fine. Also it makes sense to enhance the output reason task explanation in case if
Source: x
is repeated, e.g.Source: x (via module-dependency-test-fixtures)
specifying the according capabilities.