How to redefine a task method from gradle script?


(Davide Cavestro) #1

In order to temporarily workaround a limitation on the jacoco plugin (without patching it), I’d like to redefine a method this way

  task jacocoReport(type: JacocoReport) {

doFirst {

def oldMethod = it.metaClass.getClassDirs

it.metaClass.getClassDirs = { ->

oldMethod.filter {!it.name.endsWith (’.jar’)}

}

}

I’m afraid this kind of meta programming somewhat hurts some gradle internals, cause it seems that the original method is redefined with my closure, but then it fails complaining
  org.gradle.api.internal.MissingMethodException: Could not find method structure() for arguments [{name=TEST}, org.ajoberstar.gradle.jacoco.tasks.JacocoReport$_generate_closure1_closure8@13da177] on task ':TEST:jacocoReport'.

at org.gradle.api.internal.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:68)

at org.gradle.api.internal.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:56)

at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:172)

at org.ajoberstar.gradle.jacoco.tasks.JacocoReport_Decorated.invokeMethod(Unknown Source)

at org.ajoberstar.gradle.jacoco.tasks.JacocoReport$_generate_closure1.doCall(JacocoReport.groovy:62)

at org.ajoberstar.gradle.jacoco.tasks.JacocoReport$_generate_closure1.doCall(JacocoReport.groovy)

at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:86)

at org.gradle.api.internal.project.DefaultAntBuilder.super$3$invokeMethod(DefaultAntBuilder.groovy)

at org.gradle.api.internal.project.DefaultAntBuilder.invokeMethod(DefaultAntBuilder.groovy:37)

at org.ajoberstar.gradle.jacoco.tasks.JacocoReport.generate(JacocoReport.groovy:58)

at org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:216)

at org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:122)  

(Luke Daley) #2

The exception is saying that a different method is missing. I’m not seeing the relationship.


(Davide Cavestro) #3

The problem is that the issue arises if I use the instance metaClass in order to replace the original method with my closure. The missing method is actually an element available for jacoco report ant task. It’'s called at (https://github.com/ajoberstar/gradle-jacoco/blob/0.2.0/src/main/groovy/org/ajoberstar/gradle/jacoco/tasks/JacocoReport.groovy#L62 , and its body/closure should invoke my closure at https://github.com/ajoberstar/gradle-jacoco/blob/0.2.0/src/main/groovy/org/ajoberstar/gradle/jacoco/tasks/JacocoReport.groovy#L64. Moreover the method I have replaced is annotated as a task input… so I suspect my change somewhat breaks the gradle ANT builder (but maybe I’m wrong).

So I’d like to know if there’s a better way to replace a task method (provided that mine is clearly a workaround).

Cheers Davide


(Davide Cavestro) #4

I replied to you some days ago, but I missed leaving directly a comment… any idea on why the issue arises if I use the instance metaClass in order to replace the original method with my closure?


(Peter Niederwieser) #5

There is no supported way to replace a task method, and monkey patching is always risky business. You might be better off forking (or contributing to) the plugin.