Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Eclipse 4.8 test source sets in the classpath file #4802

Closed
danielkaneider opened this issue Mar 22, 2018 · 8 comments
Closed
Assignees
Labels
a:feature A new functionality

Comments

@danielkaneider
Copy link

Eclipse 4.8 M5 added support for test sources (https://www.eclipse.org/eclipse/news/4.8/M5/#JDT). It would be nice if gradle eclipse generation could mark the corresponding entries in the .classpath files as such. This could be done among others for source folders, output folders and referenced libraries.

@danielkaneider danielkaneider changed the title Add support for Eclipse test source sets in the classpath file Add support for Eclipse 4.8 test source sets in the classpath file Mar 22, 2018
@howlger
Copy link

howlger commented Jun 11, 2018

The following build.gradle snippet works for me as a workaround for this issue in Eclipse Photon RC2:

apply plugin: 'eclipse'
eclipse.classpath.file.whenMerged {

	// separate output folders required to set the 'test' attribute
	entries.find { it.path == 'src/main/java' }.output = 'bin/main'
	def testSrc = entries.find { it.path == 'src/test/java' }
	testSrc.output = 'bin/test'
	testSrc.entryAttributes['test'] = 'true'

	// libraries visible for test sources only?
	entries.forEach { entry ->
		def entryIn = { it.find { file(entry.path).equals(it) } }
		if (entry.kind == 'lib') {
			entry.entryAttributes['test'] =
				entryIn(configurations.testRuntimeClasspath) &&
				!entryIn(configurations.runtimeClasspath)
		}
	}

}

@eric-milles
Copy link

Current gradle/eclipse plug-in is separating output paths and so I was able to accomplish the same with:

eclipse.classpath.file.whenMerged {
  entries.findAll { entry ->
    entry.class.name in [
      'org.gradle.plugins.ide.eclipse.model.Library',
      'org.gradle.plugins.ide.eclipse.model.SourceFolder'
    ]
  }.each { entry ->
    if (entry.entryAttributes['gradle_used_by_scope'] == 'test') {
      entry.entryAttributes['test'] = 'true'
    }
  }
}

@liblit
Copy link

liblit commented Jul 25, 2018

@eric-milles, which specific Gradle version, Eclipse version, and Eclipse Buildship plug-in version are you using?

I tried your suggestion with Gradle 4.9, Eclipse 4.8.0 (Photon), and Buildship 2.2.1.v20180125-1441. I am working with a complex Gradle-based project that includes many subprojects, so I wrapped your entire Gradle fragment inside an allprojects { ... } block to include those many subprojects:

allprojects {
  eclipse.classpath.file.whenMerged {
    entries.findAll { entry ->
      entry.class.name in [
        'org.gradle.plugins.ide.eclipse.model.Library',
        'org.gradle.plugins.ide.eclipse.model.SourceFolder'
      ]
    }.each { entry ->
      if (entry.entryAttributes['gradle_used_by_scope'] == 'test') {
        entry.entryAttributes['test'] = 'true'
      }
    }
  }
}

Unfortunately, this did not do anything useful. Every entry considered by entries.findAll had dynamic type org.gradle.plugins.ide.eclipse.model.Output. There were no Library or SourceFolder entries, which therefore left nothing for the .each { ... } stage to operate on, so nothing was marked as being test code.

@eric-milles
Copy link

@liblit I also have Gradle 4.9, Eclipse 4.8.0, Buildship 2.2.1. My project is very simple and the .classpath looks like this:

<classpath>
	<classpathentry kind="src" output="bin/main" path="src/main/groovy">
		<attributes>
			<attribute name="gradle_scope" value="main"/>
			<attribute name="gradle_used_by_scope" value="main,test"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="bin/main" path="src/main/java">
		<attributes>
			<attribute name="gradle_scope" value="main"/>
			<attribute name="gradle_used_by_scope" value="main,test"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="bin/test" path="src/test/java">
		<attributes>
			<attribute name="gradle_scope" value="test"/>
			<attribute name="gradle_used_by_scope" value="test"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
	<classpathentry kind="output" path="bin/default"/>
</classpath>

@liblit
Copy link

liblit commented Jul 25, 2018

Here is my version of @eric-millesʼs approach that works with subprojects as well:

allprojects {
  apply plugin: 'eclipse'

  eclipse.classpath.file.whenMerged {
    entries.each {
      if (it in org.gradle.plugins.ide.eclipse.model.AbstractClasspathEntry && it.entryAttributes['gradle_used_by_scope'] == 'test')
        it.entryAttributes['test'] = true
    }
  }
}

@eric-milles
Copy link

I used explicit checks for Library and SourceFolder because I was unsure if Container, Variable and ProjectDependency should have this applied.

liblit added a commit to liblit/WALA that referenced this issue Jul 25, 2018
This leverages new Eclipse 4.8 (Photon) features that distinguish main
code from test code:
<https://www.eclipse.org/photon/noteworthy/index.php#test-sources>.
An eventual fix to <gradle/gradle#4802>
might mean that Buildship starts doing this automatically, but for now
we can do it ourselves.

If using an older Eclipse release, this change does nothing useful,
but neither does it cause any harm.
msridhar pushed a commit to wala/WALA that referenced this issue Jul 30, 2018
This leverages new Eclipse 4.8 (Photon) features that distinguish main
code from test code:
<https://www.eclipse.org/photon/noteworthy/index.php#test-sources>.
An eventual fix to <gradle/gradle#4802>
might mean that Buildship starts doing this automatically, but for now
we can do it ourselves.

If using an older Eclipse release, this change does nothing useful,
but neither does it cause any harm.
@twwwt
Copy link

twwwt commented Jan 2, 2019

I've tried the workaround proposed by @liblit. It works unless a project defines an additional configuration. I have a Java project that contains the following:

configurations
{
	providedCompile { description = 'Same as with `war` plugin.'; extendsFrom compile }
}

sourceSets.main.compileClasspath += configurations.providedCompile

dependencies
{
	providedCompile 'javax.enterprise:cdi-api:2.0'
	testRuntime 'javax.enterprise:cdi-api:2.0' // Needed as there are unit tests for classes that compile-time depend on cdi-api.
}

eclipse.classpath
{
	plusConfigurations += [ configurations.providedCompile ]
}

The resulting entry in .classpath file is (paths shortened):

<classpathentry kind="lib" path="javax.enterprise/cdi-api/2.0/cdi-api-2.0.jar" sourcepath="javax.enterprise/cdi-api/2.0/cdi-api-2.0-sources.jar">
	<attributes>
		<attribute name="gradle_used_by_scope" value="test"/>
		<attribute name="test" value="true"/>
	</attributes>
</classpathentry>

Due to gradle_used_by_scope having the value test it is marked as a test classpath entry only, which is not what is expected. It should rather have the value main, test and thus become a standard runtime classpath entry. Am I missing something here?

@donat
Copy link
Member

donat commented Jan 6, 2020

This has been fixed in #9484 and available since Gradle 5.6.

@donat donat closed this as completed Jan 6, 2020
valfirst added a commit to vividus-framework/vividus that referenced this issue Jan 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:feature A new functionality
Projects
None yet
Development

No branches or pull requests

7 participants