mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-10-08 16:19:48 +00:00
Support multi-release sources in Eclipse
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
This commit is contained in:
+101
-5
@@ -68,13 +68,109 @@ eclipse.classpath.file.whenMerged {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove classpath entries for multi-release source sets (such as "src/main/java21")
|
// Since an Eclipse project supports only a single Java compliance level, projects
|
||||||
// and their Gradle output (such as "build/classes/java/java21"), since an Eclipse
|
// that use the multiReleaseJar plugin are configured with a single Java baseline
|
||||||
// project supports only a single Java compliance level. Consequently, features
|
// within Eclipse. By default, the highest multi-release version is used (such as
|
||||||
// managed via the multiReleaseJar plugin cannot be built or tested within Eclipse.
|
// 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 ->
|
eclipse.classpath.file.whenMerged { classpath ->
|
||||||
classpath.entries.removeAll { it.path =~ /src\/(main|test)\/java\d+/ }
|
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)?$/ }
|
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
|
// Remove classpath entries for non-existent libraries added by the multiReleaseJar
|
||||||
|
|||||||
@@ -53,11 +53,15 @@ within your locally cloned `spring-framework` working directory._
|
|||||||
compile `spring-core` and generate JAXB types for `spring-oxm`.
|
compile `spring-core` and generate JAXB types for `spring-oxm`.
|
||||||
1. `spring-aspects` does not compile due to references to aspect types unknown to Eclipse.
|
1. `spring-aspects` does not compile due to references to aspect types unknown to Eclipse.
|
||||||
- If you installed _AJDT_ into Eclipse it should work.
|
- If you installed _AJDT_ into Eclipse it should work.
|
||||||
1. The Java 21 and Java 24 multi-release sources in `spring-core` (`src/main/java21`,
|
1. Since an Eclipse project supports only a single Java compliance level, `spring-core`
|
||||||
`src/main/java24`, and `src/test/java21`) are not configured as source folders in
|
is configured with a Java 24 baseline in Eclipse, which includes the Java 21 and
|
||||||
Eclipse, since an Eclipse project supports only a single Java compliance level.
|
Java 24 multi-release sources (`src/main/java21`, `src/main/java24`, and
|
||||||
- Use `./gradlew :spring-core:java21Test` or `./gradlew :spring-core:java24Test` to
|
`src/test/java21`). Types overridden by those sources are excluded from
|
||||||
build and test those sources from the command line.
|
`src/main/java`. Eclipse does not report usage of Java features newer than the
|
||||||
|
project-wide Java 17 baseline; however, such usage will be caught by the Gradle build.
|
||||||
|
- To work on the Java 17 or Java 21 variants instead, run
|
||||||
|
`./gradlew eclipse -PeclipseJavaBaseline=17` (or `21`) and refresh the projects in
|
||||||
|
Eclipse (or close and reopen them if the compiler settings are not updated).
|
||||||
1. While JUnit tests pass from the command line with Gradle, some may fail when run from
|
1. While JUnit tests pass from the command line with Gradle, some may fail when run from
|
||||||
the IDE.
|
the IDE.
|
||||||
- Resolving this is a work in progress.
|
- Resolving this is a work in progress.
|
||||||
|
|||||||
Reference in New Issue
Block a user