This message was deleted.
# configuration-cache
s
This message was deleted.
a
The task performs the required function just fine, only fails if I enable CC. I would like it to work properly with CC.
a
Looks like this part:
Copy code
onlyIf {
    this.getXmlReport().get().asFile.exists()
}
maybe this could fix it:
Copy code
def xmlReport = this.getXmlReport() 
onlyIf {
    xmlReport.get().asFile.exists()
}
a
Sure, why not, seems like a plausible fix
Wow! I would not have thought about this simple context switch making a difference.
That is it. Thank you!
🙌 1
a
Also this thing works:
Copy code
onlyIf { task ->
    task.xmlReport.get().asFile.exists()
}
v
I'm curious, why do you anyway have an own task for that? Judging by the name, you should just use a normal
JacocoReport
task that you give all execution data files for what you want a combined report conceptually like the JaCoCo report aggregation plugin does. You just need some extra configuration if you want a report over different test types, but that is what I do to get an overall JaCoCo report.
r
@Alexander Volanis Is he right? Can we just delegate summary report creation to a
JacocoReport
task?
v
Why shouldn't you? Or what is the task doing?
r
It's generating another XML file in a particular format that is read by another system that enforces code coverage requirements at code review time
v
Oh, ok, then of course not. That's why I asked. :-)
r
@Anze Sodja Can you explain how you spotted that so easily? It seems like there's a lot of Groovy-specific stuff going on here, because it's not obvious to me why
onlyIf
can close over
xmlReport
but not
this
v
It's a quirk related to how Groovy closures are serialized to and deserialized from the configuration cache. This for example would also have worked as no closure is involved:
Copy code
onlyIf new Spec() {
   @Override
   boolean isSatisfiedBy(Object o) {
      this.getXmlReport().get().asFile.exists()
   }
}
Maybe
@CompileStatic
would also have worked.
a
No, that was the first thing I tried. It was refusing to compile static actually and I could not fully understand the reasons why. The error message was this:
Copy code
JacocoCoverageSummaryReportTask.groovy: 50: [Static type checking] - Cannot statically compile constructor implicitly including non-static elements from fields, properties or initializers
 @ line 50, column 5.
       @CompileStatic
       ^
I tried to make sure all references to fields are qualified but nothing worked.
FYI making the onlyIf this way also worked and makes sense now.
Copy code
onlyIf { JacocoCoverageSummaryReportTask task ->
    task.xmlReport.get().asFile.exists()
}
r
This is further justification for my “use Java or you’ll die” philosophy
👍 2
ABI details matter!
a
As to the question of delegating the summary to JacocoReport we cannot do that because this is a root project task that creates a summary/average of all subprojects at the root project. Each subproject has its own summary report task creating the summary file and the root project task aggregates all into a package level summary file. That would be too much logic to attach onto a
doLast
in my opinion. But perhaps worth refactoring into such? Basically the entire @TaskAction of this task could become an attached doLast action for each JacocoReport task. The one at the root project does the aggregation. To do this right we would need to adjust the task outputs of the JacocoReport but that is probably just as easy.
r
Configuration caching means we are called upon to understand in some detail how our object graphs are serialized. You can only do that by understanding how language features are translated to bytecode
a
I am coming to your camp with the Java or die approach. Conveniently IntelliJ has support to convert Groovy to Java within limits.
r
Yeah, it’s not that great. I started out using it and ended up doing the conversion fully by hand
But our presets plugin uses Groovy dynamism, so it’s not clear how to migrate it to Java. Maybe if we kick out the Android stuff, or keep it in Groovy somehow
a
I want to kick the Android out so we can then make the Android stuff properly using Java and no dynamic behaviors.
I think much of what the plugin does can be direct to Java and it would benefit from it. I have started making many of my own plugins into Java for the same reasons
a
Anze Sodja Can you explain how you spotted that so easily? It seems like there's a lot of Groovy-specific stuff going on here, because it's not obvious to me why onlyIf can close over xmlReport but not this
It's far from obvious. We should have less of such traps. First hint for me was, using `onlyIf`:
onlyIf
runs at the execution time, always even on cc hit and because of that closure is serialized. So
onlyIf
is very similar to
doFirst/doLast
in that regard. And then
org.gradle.api.specs.internal.ClosureSpec.isSatisfiedBy(ClosureSpec.java:33)
,
isSatisfiedBy
was a good hint that this is in fact
onlyIf
closure. And then using
this.
that have a reference to a larger scope (whole task in that case). Although it was not obvious to me that this causes an issue. It seems that similar code works in Kotlin, so it's really a quirk in Closure serialization.
a
Using
this
was an attempt to clear up the issue. I was not using
this
before I ran into the problem. But your explanation makes sense now and solved the immediate issue. Long term I am converting this to use Java instead of Groovy eliminating Closure serialization for good.