Regression in 2.0 when using allprojects{} with the integrationTest sample


(Oliver Trosien) #1

Hi,

I’m testing gradle 2.0 with our multiproject build, and it gets stuck when applying the integrationTest pattern with the error “Could not find method integrationTestCompile”. The funny thing is, that with subprojects{} instead of allprojects{} it seems to work fine. Is this a bug or am I missing something?

Stacktrace: https://gist.github.com/anonymous/f44e7526861ef59402fd gradle build files: https://gist.github.com/anonymous/2f595507c284846b1f57

Regards, Oliver


#2

Thanks for the report. I can reproduce this problem, and have simplified it to:

settings.gradle:

include 'subproject'

build.gradle:

allprojects {
    apply plugin: 'java'
       sourceSets {
        integrationTest {
            java { srcDir file('src/integration-test/java') }
        }
    }
       task integrationTest {
        ext.ss = sourceSets.integrationTest
    }
}

With Gradle 1.12, running ‘gradle help’ works fine. With Gradle 2.0, the error message is:

* What went wrong:
A problem occurred evaluating root project 'mp'.
> Could not find property 'integrationTest' on SourceSet container.

Changing ‘allprojects’ to ‘subprojects’ works as well.

I think the issue is due to the task name and sourceSet name being the same. If you change the name of the ‘integrationTest’ task (or the sourceSet), the problem is resolved.


(t.enderling) #3

This reply was created from a merged topic originally titled Order of configure closure binding changed between Gradle 1.8 and 2.0. I’m trying to migrate from Gradle 1.8 to 2.0 and noticed an intricate change in behavior of the DSL.

The following snippet demonstrates the change:

<br /> class SimpleDomainObject <br /> { <br />
   String name <br /><br />
   public SimpleDomainObject(String name) <br />
   {
       <br />
       this&#46;name = name <br />
   } <br /><br />
   void methodInSimpleDomainObject() { <br />
       println &quot;methodInSimpleDomainObject called for object '$name'&quot; <br />
   } <br /> } <br /><br /> extensions&#46;add('container', project&#46;container(SimpleDomainObject)) <br /><br /> container { <br />
   repositories {
  <br />
       methodInSimpleDomainObject() <br />
   } <br /> } <br /><br /> println 'Objects in container: ' + container*&#46;name <br />



Executing this code in Gradle 1.8 prints:

<br /> methodInSimpleDomainObject called for object 'repositories' <br /> Objects in container: [repositories] <br />



Executing it in Gradle 2.0:

<br /> Build file 'build&#46;gradle' line: 19 <br /><br /> * What went wrong: <br /> A problem occurred evaluating root project 'closurebinding'&#46; <br /> &gt; Could not find method methodInSimpleDomainObject() for arguments [] on repository container&#46; <br />



This only occurs if the name of the domain object is a method in an enclosing closure delegate (like in this case the project). This is pretty suprising.

Digging through the changes, the culprit seems to be changes to ConfigureDelegate:
http://code-review.gradle.org/changel…

Even more surprising: If you omit the call to methodInSimpleDomainObject, both versions yield the same result. But then there is no object created in the container!

<br /> Objects in container: [] <br />



I see, why the new behavior in Gradle 2.0 is more reliable than the behavior in 1.8. I’m still not convinced however, why one would want to call a configure-method, i.e. a method call with a single closure parameter, onto an object in some outer scope instead of creating a new object in the directly surrounding container.

Maybe you can reconsider and give the delegate precedence over the owner for all closure-like methods. If not, you should at least document this as potential breaking change in Gradle 2.0, as it is very hard to find and investigate.


(Luke Daley) #4

This has been fixed for 2.1 and will be in the next nightly.


(t.enderling) #5

Great, thanks!