mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-10-07 23:49:08 +00:00
Prior to this commit, the Java 21 and Java 24 multi-release sources in spring-core could not be developed or tested within Eclipse, since an Eclipse project supports only a single Java compliance level. This commit configures Eclipse projects that use the multiReleaseJar plugin with the highest multi-release version as their Java baseline (Java 24 for spring-core) and includes the corresponding multi-release source folders. Types which are overridden by a multi-release source folder are excluded from lower source folders, and higher source folders are placed first so that the debugger's source lookup resolves overriding types. A lower baseline can be configured via the "eclipseJavaBaseline" project property: for example, -PeclipseJavaBaseline=17. See gh-37397
203 lines
7.6 KiB
Groovy
203 lines
7.6 KiB
Groovy
import org.gradle.plugins.ide.eclipse.model.Library
|
|
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
|
import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
|
|
|
apply plugin: 'eclipse'
|
|
|
|
eclipse.jdt {
|
|
sourceCompatibility = 17
|
|
targetCompatibility = 17
|
|
}
|
|
|
|
// Replace classpath entries with project dependencies (GRADLE-1116)
|
|
// https://issues.gradle.org/browse/GRADLE-1116
|
|
eclipse.classpath.file.whenMerged { classpath ->
|
|
def regexp = /.*?\/([^\/]+)\/build\/([^\/]+\/)+(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
|
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
|
projectOutputDependencies.each { entry ->
|
|
def matcher = (entry.path =~ regexp)
|
|
if (matcher) {
|
|
def projectName = matcher[0][1]
|
|
def path = "/${projectName}"
|
|
if (!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
|
def recursiveDependency = entry.path.matches('.+/' + projectName + '/build/([^/]+/)+(?:main|test)')
|
|
// Avoid recursive dependency on current project.
|
|
if (!recursiveDependency) {
|
|
classpath.entries.add(new ProjectDependency(path))
|
|
}
|
|
}
|
|
classpath.entries.remove(entry)
|
|
}
|
|
}
|
|
|
|
// Remove any remaining direct depencencies on JARs in the build/libs folder
|
|
// except the repack JARs.
|
|
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
|
}
|
|
|
|
// Use separate main/test outputs (prevents WTP from packaging test classes)
|
|
eclipse.classpath.defaultOutputDir = file(project.name + '/bin/eclipse')
|
|
eclipse.classpath.file.beforeMerged { classpath ->
|
|
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
|
if (it.output.startsWith('bin/')) {
|
|
it.output = null
|
|
}
|
|
}
|
|
}
|
|
eclipse.classpath.file.whenMerged {
|
|
entries.findAll{ it instanceof SourceFolder }.each {
|
|
it.output = 'bin/' + it.path.split('/')[1]
|
|
}
|
|
}
|
|
|
|
// Ensure project dependencies come after 3rd-party libs (SPR-11836)
|
|
// https://jira.spring.io/browse/SPR-11836
|
|
eclipse.classpath.file.whenMerged {
|
|
entries.findAll { it instanceof ProjectDependency }.each {
|
|
// delete from original position
|
|
entries.remove(it)
|
|
// append to end of classpath
|
|
entries.add(it)
|
|
}
|
|
}
|
|
|
|
// Remove recursive project dependencies
|
|
eclipse.classpath.file.whenMerged {
|
|
entries.findAll { it instanceof ProjectDependency && it.path == ('/' + project.name) }.each {
|
|
entries.remove(it)
|
|
}
|
|
}
|
|
|
|
// Since an Eclipse project supports only a single Java compliance level, projects
|
|
// that use the multiReleaseJar plugin are configured with a single Java baseline
|
|
// within Eclipse. By default, the highest multi-release version is used (such as
|
|
// Java 24 for spring-core), so that the corresponding sources can be developed
|
|
// and tested within Eclipse. A different baseline can be configured via the
|
|
// "eclipseJavaBaseline" project property: for example, -PeclipseJavaBaseline=17.
|
|
// Multi-release source folders for versions above the baseline are not configured
|
|
// as source folders in Eclipse (the sources themselves remain untouched), and types
|
|
// which are overridden by a multi-release source folder are excluded from lower
|
|
// source folders in Eclipse.
|
|
def javaBaseline = 17
|
|
|
|
def multiReleaseVersions = {
|
|
sourceSets.names.findAll { it ==~ /java\d+/ }.collect { (it - 'java') as int }
|
|
}
|
|
|
|
def eclipseJavaBaseline = {
|
|
def releaseVersions = multiReleaseVersions()
|
|
if (releaseVersions.isEmpty()) {
|
|
return javaBaseline
|
|
}
|
|
return (project.hasProperty('eclipseJavaBaseline') ?
|
|
(project.property('eclipseJavaBaseline') as int) : releaseVersions.max())
|
|
}
|
|
|
|
// Return the Java version of the supplied source folder: 0 for "src/main/java",
|
|
// 21 for "src/main/java21", or null if it is not a Java source folder.
|
|
def javaVersionOf = { SourceFolder folder ->
|
|
def matcher = (folder.path =~ /^src\/(main|test)\/java(\d*)$/)
|
|
if (!matcher.matches()) {
|
|
return null
|
|
}
|
|
return (matcher.group(2) ? (matcher.group(2) as int) : 0)
|
|
}
|
|
|
|
// Return the paths of all Java source files in the supplied directory, relative to
|
|
// that directory: for example, "org/springframework/core/task/VirtualThreadDelegate.java"
|
|
// for "src/main/java21/org/springframework/core/task/VirtualThreadDelegate.java".
|
|
def relativeJavaFiles = { String dir ->
|
|
def root = file(dir).toPath()
|
|
return fileTree(dir).matching { include '**/*.java' }.collect {
|
|
root.relativize(it.toPath()).toString().replace('\\', '/')
|
|
}
|
|
}
|
|
|
|
// Remove existing source folders, since their exclusion patterns depend on the
|
|
// configured baseline and would otherwise result in duplicate entries.
|
|
eclipse.classpath.file.beforeMerged { classpath ->
|
|
if (!multiReleaseVersions().isEmpty()) {
|
|
classpath.entries.removeAll { it instanceof SourceFolder }
|
|
}
|
|
}
|
|
|
|
eclipse.jdt.file.whenMerged { jdt ->
|
|
def baseline = JavaVersion.toVersion(eclipseJavaBaseline())
|
|
jdt.sourceCompatibility = baseline
|
|
jdt.targetCompatibility = baseline
|
|
}
|
|
|
|
eclipse.classpath.file.whenMerged { classpath ->
|
|
def baseline = eclipseJavaBaseline()
|
|
|
|
// Remove Gradle output for multi-release source sets, such as
|
|
// "build/classes/java/java21".
|
|
classpath.entries.removeAll { it.path =~ /build\/classes\/[^\/]+\/java\d+(Test)?$/ }
|
|
|
|
// Remove classpath entries for multi-release source folders above the baseline.
|
|
classpath.entries.removeAll {
|
|
it instanceof SourceFolder && (javaVersionOf(it) ?: 0) > baseline
|
|
}
|
|
|
|
// Mark multi-release test source folders (such as "src/test/java21") as test
|
|
// sources, since they share the output folder with "src/test/java".
|
|
classpath.entries.findAll { it instanceof SourceFolder && it.path ==~ /src\/test\/java\d+/ }.each {
|
|
it.entryAttributes['test'] = 'true'
|
|
}
|
|
|
|
// Exclude types from lower source folders which are overridden in higher ones.
|
|
['main', 'test'].each { scope ->
|
|
def sourceFolders = classpath.entries.findAll {
|
|
it instanceof SourceFolder && it.path.startsWith("src/${scope}/") &&
|
|
javaVersionOf(it) != null
|
|
}
|
|
sourceFolders.each { folder ->
|
|
def overriddenTypes = sourceFolders
|
|
.findAll { javaVersionOf(it) > javaVersionOf(folder) }
|
|
.collectMany { relativeJavaFiles(it.path) }
|
|
.findAll { file("${folder.path}/${it}").exists() }
|
|
if (!overriddenTypes.isEmpty()) {
|
|
folder.excludes = (folder.excludes + overriddenTypes).unique()
|
|
}
|
|
}
|
|
|
|
// Place higher source folders before lower ones, so that the debugger's source
|
|
// lookup finds overriding types before excluded ones.
|
|
def multiReleaseFolders = sourceFolders.findAll { javaVersionOf(it) > 0 }
|
|
.sort { -javaVersionOf(it) }
|
|
def baseFolder = sourceFolders.find { javaVersionOf(it) == 0 }
|
|
if (baseFolder != null && !multiReleaseFolders.isEmpty()) {
|
|
classpath.entries.removeAll(multiReleaseFolders)
|
|
classpath.entries.addAll(classpath.entries.indexOf(baseFolder), multiReleaseFolders)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove classpath entries for non-existent libraries added by the multiReleaseJar
|
|
// plugin, such as "spring-core/build/classes/kotlin/java21".
|
|
eclipse.classpath.file.whenMerged {
|
|
entries.findAll { it instanceof Library && !file(it.path).exists() }.each {
|
|
entries.remove(it)
|
|
}
|
|
}
|
|
|
|
// Include project specific settings
|
|
tasks.register('eclipseSettings', Copy) {
|
|
from rootProject.files(
|
|
'src/eclipse/org.eclipse.core.resources.prefs',
|
|
'src/eclipse/org.eclipse.jdt.core.prefs',
|
|
'src/eclipse/org.eclipse.jdt.ui.prefs')
|
|
into project.file('.settings/')
|
|
outputs.upToDateWhen { false }
|
|
}
|
|
|
|
tasks.register('cleanEclipseSettings', Delete) {
|
|
delete project.file('.settings/org.eclipse.core.resources.prefs')
|
|
delete project.file('.settings/org.eclipse.jdt.core.prefs')
|
|
delete project.file('.settings/org.eclipse.jdt.ui.prefs')
|
|
}
|
|
|
|
tasks['eclipse'].dependsOn(eclipseSettings)
|
|
tasks['eclipseJdt'].dependsOn(eclipseSettings)
|
|
tasks['cleanEclipse'].dependsOn(cleanEclipseSettings)
|