https://kotlinlang.org logo
#gradle
Title
# gradle
c

Chachako

06/23/2022, 9:33 AM
Hello, everyone. I wonder if there is any way to observe the completion of
DomainObjectCollection
? Is this Kotlin code correct?
Copy code
val dependencies = channelFlow {
  project.configurations.configureEach {
    it.dependencies.forEach(::trySend)
  }
}

// On "configureEach" completion
println(dependencies)
s

Sam

06/23/2022, 9:38 AM
One thing to note about `channelFlow`:
The resulting flow completes as soon as the code in the block and all its children completes. Use awaitClose as the last statement to keep it running.
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/channel-flow.html
🤯 1
c

Chachako

06/23/2022, 9:44 AM
So I can’t do the listening to
DomainObjectCollection.configureEach
with a clumsy trick like
channelFlow
? and any correct guidance would be appreciated!
s

Sam

06/23/2022, 9:46 AM
You said "observe the completion" but what do you mean by completion? Depending on the type of collection I think it could theoretically be modified at any time during the build
You might do better by observing the lifecycle of the things that you think might modify the collection, e.g.
project.afterEvaluate
👎 2
👍 1
If it's specifically for dependencies, you could try installing a
resolutionStrategy
instead. That will be invoked at the point when the configuration is resolved, which sounds like what you want.
👀 1
c

Chachako

06/23/2022, 9:50 AM
For Gradle, should all configurations be evaluated and completed at some point? At that point,
project.configurations
shouldn’t have anything new added, so I want to do something while it’s at a point where nothing will be added.
project.afterEvaluate
is a practice, but I feel this may be a little late
s

Sam

06/23/2022, 10:02 AM
I'm not sure if you can also use
configuration.incoming.beforeResolve
to register some code to run just before the configuration is resolved
(Because I'm not 100% sure what the semantics of
configuration.incoming
are)
c

Chachako

06/23/2022, 10:04 AM
OK, I’ll try that, if none of them work, then
project.afterEvaluate
will be the last resort
v

Vampire

06/23/2022, 1:24 PM
project.afterEvaluate
is a practice
It is not only a practice, it is a bad practice. And you can never know whether the collection is already complete at that time, because
afterEvaluate
blocks are added t a queue and the ones later in the queue than your block might again change what you are evaluating.
afterEvaluate
is not a solution to anything, but a hack and one that will fail on you as soon as someone configures the thing you try to look at in an
afterEvaluate
block that is evaluated after your
afterEvaluate
block. The only thing
afterEvaluate
does, is doing symptom treatment, delaying a problem to arise later again, but that time even harder to debug. It always introduces nasty race conditions you cannot really avoid except by not using
afterEvaluate
.
As you most probably not want to just print all dependencies, please describe what your actual use-case is you are trying to solve, then maybe someone can advice a proper way to solve it. 🙂
c

Chachako

06/23/2022, 2:51 PM
As you most probably not want to just print all dependencies, please describe what your actual use-case is you are trying to solve, then maybe someone can advice a proper way to solve it. 🙂
I actually have a common version catalog file that is very large, so I need a way to get all Gradle in-use dependencies, and write the corresponding dependencies from the common file to
libraries.versions.toml
to avoid other unnecessary sight distractions. So in this case ,
afterEvaluate
should work