Skip to content

Commit

Permalink
Merge pull request #3209 from gradle/donat/ide/eclipse-cp-separation
Browse files Browse the repository at this point in the history
Allow Buildship to separate runtime classpath based on source set information
  • Loading branch information
donat committed Oct 19, 2017
2 parents 41cf77c + c052c18 commit 2db9545
Show file tree
Hide file tree
Showing 28 changed files with 857 additions and 96 deletions.
Expand Up @@ -22,7 +22,7 @@
</tr>
<tr>
<td>defaultOutputDir</td>
<td><filename><replaceable>${project.projectDir}</replaceable>/bin</filename></td>
<td><filename><replaceable>${project.projectDir}</replaceable>/bin/default</filename></td>
</tr>
<tr>
<td>downloadSources</td>
Expand Down Expand Up @@ -54,4 +54,4 @@
</tr>
</table>
</section>
</section>
</section>
9 changes: 9 additions & 0 deletions subprojects/docs/src/docs/release/notes.md
Expand Up @@ -36,6 +36,11 @@ As of Gradle 4.4, optional dependencies will participate in dependency resolutio
For example, if a transitive dependency on `foo:bar:1.1` is optional, but another path in the dependency graph brings `foo:bar:1.0` (not optional), then Gradle will resolve to `foo:bar:1.1`.
Previous releases would resolve to `foo:bar:1.0`. However, if no "hard" dependency is found on the optional module, then it will **not** be included, as previous Gradle versions did.

### Eclipse plugin separates output folders

The `eclipse` plugin now defines separate output directories for each source folder. This ensures that main and test classes are compiled to different directories.

The plugin also records which Eclipse classpath entries are needed for running classes from each source folder through the new `gradle_scope` and `gradle_used_by_scope` attributes. Future [Buildship](http://eclipse.org/buildship) versions will use this information to provide a more accurate classpath when launching applications and tests.

### Parametrized tooling model builders.

Expand Down Expand Up @@ -80,6 +85,10 @@ Since then Gradle optimized its up-to-date checking for project dependencies whi
Supporting optional dependencies means that depending on the shape of your dependency graph, you may now have a different dependency resolution result after upgrading to Gradle 4.4.
Should you see any problem, [build scans](https://scans.gradle.com) can help you debug those.

### Changes in the `eclipse` plugin

The default output location in [EclipseClasspath](dsl/org.gradle.plugins.ide.eclipse.model.EclipseClasspath.html#org.gradle.plugins.ide.eclipse.model.EclipseClasspath:defaultOutputDir) changed from `${project.projectDir}/bin` to `${project.projectDir}/bin/default`.

## External contributions

We would like to thank the following community members for making contributions to this release of Gradle.
Expand Down
Expand Up @@ -41,6 +41,7 @@ class ToolingApiEclipseModelOutputLocationCrossVersionSpec extends ToolingApiSpe
thrown UnsupportedMethodException
}

@TargetGradleVersion(">=3.0 <4.4")
def "Non-Java project has default output location"() {
when:
EclipseProject project = loadToolingModel(EclipseProject)
Expand All @@ -50,6 +51,7 @@ class ToolingApiEclipseModelOutputLocationCrossVersionSpec extends ToolingApiSpe
output.path == 'bin'
}

@TargetGradleVersion(">=3.0 <4.4")
def "Java project has default output location"() {
setup:
buildFile << "apply plugin: 'java'"
Expand Down
Expand Up @@ -43,6 +43,7 @@ class ToolingApiEclipseModelSourceDirectoryOutputCrossVersionSpec extends Toolin
thrown UnsupportedMethodException
}

@TargetGradleVersion(">=3.0 <4.4")
def "Source directory has no output specified"() {
setup:
settingsFile << 'rootProject.name = "root"'
Expand Down
Expand Up @@ -52,6 +52,7 @@ class ToolingApiEclipseModelSourceFolderClasspathAttributesCrossVersionSpec exte
thrown UnsupportedMethodException
}

@TargetGradleVersion(">=3.0 <4.4")
def "Source folder doesn't define classpath attributes"() {
setup:
settingsFile << 'rootProject.name = "root"'
Expand All @@ -65,6 +66,7 @@ class ToolingApiEclipseModelSourceFolderClasspathAttributesCrossVersionSpec exte
project.sourceDirectories.find {it.path == 'src/main/java' }.classpathAttributes.isEmpty()
}

@TargetGradleVersion(">=3.0 <4.4")
def "Source folder defines one classpath attribute"() {
settingsFile << 'rootProject.name = "root"'
buildFile <<
Expand Down Expand Up @@ -92,6 +94,7 @@ class ToolingApiEclipseModelSourceFolderClasspathAttributesCrossVersionSpec exte
project.sourceDirectories[0].classpathAttributes[0].value == 'customValue'
}

@TargetGradleVersion(">=3.0 <4.4")
def "Source folder defines multiple classpath attributes"() {
settingsFile << 'rootProject.name = "root"'
buildFile <<
Expand Down
@@ -0,0 +1,53 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.plugins.ide.tooling.r44

import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.eclipse.EclipseOutputLocation
import org.gradle.tooling.model.eclipse.EclipseProject

@ToolingApiVersion('>=4.4')
@TargetGradleVersion(">=4.4")
class ToolingApiEclipseModelOutputLocationCrossVersionSpec extends ToolingApiSpecification {

def setup() {
settingsFile << 'rootProject.name = "root"'
}

def "Non-Java project has default output location"() {
when:
EclipseProject project = loadToolingModel(EclipseProject)
EclipseOutputLocation output = project.getOutputLocation()

then:
output.path == 'bin/default'
}

def "Java project has default output location"() {
setup:
buildFile << "apply plugin: 'java'"
EclipseProject project = loadToolingModel(EclipseProject)

when:
EclipseOutputLocation output = project.getOutputLocation()

then:
output.path == 'bin/default'
}
}
@@ -0,0 +1,67 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.plugins.ide.tooling.r44

import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.eclipse.EclipseProject

@ToolingApiVersion('>=4.4')
@TargetGradleVersion(">=4.4")
class ToolingApiEclipseModelSourceDirectoryOutputCrossVersionSpec extends ToolingApiSpecification {

def "Source directories have default output"() {
setup:
settingsFile << 'rootProject.name = "root"'
buildFile << "apply plugin: 'java'"
file('src/main/java').mkdirs()

when:
EclipseProject project = loadToolingModel(EclipseProject)

then:
project.sourceDirectories.size() == 1
project.sourceDirectories[0].output == 'bin/main'
}

def "Source directory has custom output"() {
setup:
settingsFile << 'rootProject.name = "root"'
buildFile << """
apply plugin: 'java'
apply plugin: 'eclipse'
eclipse.classpath.file.whenMerged {
entries.find { entry -> entry.path == 'src/test/java' }.output = null
entries.find { entry -> entry.path == 'src/test/resources' }.output = 'out/test-resources'
}
"""

file('src/test/java').mkdirs()
file('src/test/resources').mkdirs()

when:
EclipseProject project = loadToolingModel(EclipseProject)

then:
project.sourceDirectories.size() == 2
project.sourceDirectories[0].output == null
project.sourceDirectories[1].output == 'out/test-resources'
}

}
@@ -0,0 +1,110 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.plugins.ide.tooling.r44

import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.eclipse.EclipseProject

@ToolingApiVersion('>=4.4')
@TargetGradleVersion(">=4.4")
class ToolingApiEclipseModelSourceFolderClasspathAttributesCrossVersionSpec extends ToolingApiSpecification {

def "Source folder contains source set information in classpath attributes"() {
setup:
buildFile << "apply plugin: 'java'"
file('src/main/java').mkdirs()
file('src/test/java').mkdirs()

when:
EclipseProject project = loadToolingModel(EclipseProject)
def mainDirAttributes = project.sourceDirectories.find { it.path == 'src/main/java' }.classpathAttributes
def testDirAttributes = project.sourceDirectories.find { it.path == 'src/test/java' }.classpathAttributes

then:
mainDirAttributes.size() == 2
mainDirAttributes[0].name == 'gradle_scope'
mainDirAttributes[0].value == 'main'
mainDirAttributes[1].name == 'gradle_used_by_scope'
mainDirAttributes[1].value == 'main,test'

testDirAttributes.size() == 2
testDirAttributes[0].name == 'gradle_scope'
testDirAttributes[0].value == 'test'
testDirAttributes[1].name == 'gradle_used_by_scope'
testDirAttributes[1].value == 'test'
}

def "Source folder defines additional classpath attributes"() {
buildFile <<
"""apply plugin: 'java'
apply plugin: 'eclipse'
eclipse {
classpath {
file {
whenMerged { classpath ->
classpath.entries.find { it.kind == 'src' && it.path == 'src/main/java' }.entryAttributes.key1 = 'value1'
classpath.entries.find { it.kind == 'src' && it.path == 'src/main/java' }.entryAttributes.key2 = 'value2'
}
}
}
}
"""
file('src/main/java').mkdirs()

when:
EclipseProject project = loadToolingModel(EclipseProject)

then:
project.sourceDirectories.size() == 1
project.sourceDirectories[0].classpathAttributes.size() == 4
project.sourceDirectories[0].classpathAttributes.find { it.name == 'gradle_scope' && it.value == 'main'}
project.sourceDirectories[0].classpathAttributes.find { it.name == 'gradle_used_by_scope' && it.value == 'main,test'}
project.sourceDirectories[0].classpathAttributes.find { it.name == 'key1' && it.value == 'value1'}
project.sourceDirectories[0].classpathAttributes.find { it.name == 'key2' && it.value == 'value2'}
}


def "Source dir information can be modified in whenMerged block"() {
buildFile <<
"""apply plugin: 'java'
apply plugin: 'eclipse'
eclipse {
classpath {
file {
whenMerged { classpath ->
def entry = classpath.entries.find { it.kind == 'src' && it.path == 'src/main/java' }
entry.entryAttributes['gradle_scope'] = 'foo'
entry.entryAttributes['gradle_used_by_scope'] = 'foo,bar'
}
}
}
}
"""
file('src/main/java').mkdirs()

when:
EclipseProject project = loadToolingModel(EclipseProject)

then:
project.sourceDirectories.size() == 1
project.sourceDirectories[0].classpathAttributes.size() == 2
project.sourceDirectories[0].classpathAttributes.find { it.name == 'gradle_scope' && it.value == 'foo'}
project.sourceDirectories[0].classpathAttributes.find { it.name == 'gradle_used_by_scope' && it.value == 'foo,bar'}
}
}

0 comments on commit 2db9545

Please sign in to comment.