diff --git a/.github/actions/.bats/bats b/.github/actions/.bats/bats
new file mode 160000
index 00000000..902578da
--- /dev/null
+++ b/.github/actions/.bats/bats
@@ -0,0 +1 @@
+Subproject commit 902578da790fbcb035747d2964747f192f6e1603
diff --git a/.github/actions/.bats/test_helper/bats-assert b/.github/actions/.bats/test_helper/bats-assert
new file mode 160000
index 00000000..e2d855bc
--- /dev/null
+++ b/.github/actions/.bats/test_helper/bats-assert
@@ -0,0 +1 @@
+Subproject commit e2d855bc78619ee15b0c702b5c30fb074101159f
diff --git a/.github/actions/.bats/test_helper/bats-support b/.github/actions/.bats/test_helper/bats-support
new file mode 160000
index 00000000..9bf10e87
--- /dev/null
+++ b/.github/actions/.bats/test_helper/bats-support
@@ -0,0 +1 @@
+Subproject commit 9bf10e876dd6b624fe44423f0b35e064225f7556
diff --git a/.github/actions/create-github-release/action.yml b/.github/actions/create-github-release/action.yml
new file mode 100644
index 00000000..1d72cd3a
--- /dev/null
+++ b/.github/actions/create-github-release/action.yml
@@ -0,0 +1,21 @@
+name: Create GitHub Release
+description: Create the release on GitHub with a changelog
+inputs:
+ milestone:
+ required: true
+ token:
+ required: true
+runs:
+ using: composite
+ steps:
+ - name: Generate Changelog
+ uses: spring-io/github-changelog-generator@v0.0.10
+ with:
+ milestone: ${{ inputs.milestone }}
+ token: ${{ inputs.token }}
+ config-file: .github/actions/create-github-release/changelog-generator.yml
+ - name: Create GitHub Release
+ env:
+ GITHUB_TOKEN: ${{ inputs.token }}
+ shell: bash
+ run: gh release create ${{ format('v{0}', inputs.milestone) }} --notes-file changelog.md
diff --git a/.github/actions/create-github-release/changelog-generator.yml b/.github/actions/create-github-release/changelog-generator.yml
new file mode 100644
index 00000000..2ce74a09
--- /dev/null
+++ b/.github/actions/create-github-release/changelog-generator.yml
@@ -0,0 +1,2 @@
+changelog:
+ repository: spring-io/spring-javaformat
diff --git a/.github/actions/deduce-versions/action.yml b/.github/actions/deduce-versions/action.yml
new file mode 100644
index 00000000..b8e197c4
--- /dev/null
+++ b/.github/actions/deduce-versions/action.yml
@@ -0,0 +1,22 @@
+name: 'Deduce Versions'
+description: 'Deduce the version to stage and the next SNAPSHOT version'
+inputs:
+ current-version:
+ required: true
+ release-type:
+ required: true
+outputs:
+ release-version:
+ value: ${{ steps.deduce-versions.outputs.release-version }}
+ next-version:
+ value: ${{ steps.deduce-versions.outputs.next-version }}
+runs:
+ using: composite
+ steps:
+ - name: Deduce Versions
+ id: deduce-versions
+ shell: bash
+ run: . ${{ github.action_path }}/deduce-versions.sh; deduce_versions
+ env:
+ CURRENT_VERSION: "${{ inputs.current-version }}"
+ RELEASE_TYPE: "${{ inputs.release-type }}"
diff --git a/.github/actions/deduce-versions/deduce-versions.sh b/.github/actions/deduce-versions/deduce-versions.sh
new file mode 100755
index 00000000..6a3d14e0
--- /dev/null
+++ b/.github/actions/deduce-versions/deduce-versions.sh
@@ -0,0 +1,116 @@
+#!/usr/bin/env bash
+
+# Get the next milestone release for the given number by inspecting current tags
+get_next_milestone_release() {
+ [[ -n $1 ]] || { echo "missing get_next_milestone_release() version argument" >&2; return 1; }
+ get_next_tag_based_release "$1" "M"
+}
+
+# Get the next RC release for the given number by inspecting current tags
+get_next_rc_release() {
+ [[ -n $1 ]] || { echo "missing get_next_rc_release() version argument" >&2; return 1; }
+ get_next_tag_based_release "$1" "RC"
+}
+
+# Get the next release for the given number
+get_next_release() {
+ [[ -n $1 ]] || { echo "missing get_next_release() version argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ local join="."
+ else
+ local join="-"
+ fi
+ local version
+ local result
+ version=$( strip_snapshot_suffix "$1" )
+ if [[ -n $2 ]]; then
+ result="${version}${join}${2}"
+ else
+ result="${version}"
+ fi
+ echo $result
+}
+
+# Get the next milestone or RC release for the given number by inspecting current tags
+get_next_tag_based_release() {
+ [[ -n $1 ]] || { echo "missing get_next_tag_based_release() version argument" >&2; return 1; }
+ [[ -n $2 ]] || { echo "missing get_next_tag_based_release() tag type argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ local join="."
+ else
+ local join="-"
+ fi
+ local version
+ local last
+ version=$( strip_snapshot_suffix "$1" )
+ git fetch --tags --all > /dev/null
+ last=$( git tag --list "v${version}${join}${2}*" | sed -E "s/^.*${2}([0-9]+)$/\1/g" | sort -rn | head -n1 )
+ if [[ -z $last ]]; then
+ last="0"
+ fi
+ last="${version}${join}${2}${last}"
+ bump_version_number "$last"
+}
+
+# Remove any "-SNAPSHOT" or ".BUILD-SNAPSHOT" suffix
+strip_snapshot_suffix() {
+ [[ -n $1 ]] || { echo "missing get_relase_version() argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ echo "${BASH_REMATCH[1]}"
+ elif [[ $1 =~ ^(.*)-SNAPSHOT$ ]]; then
+ echo "${BASH_REMATCH[1]}"
+ else
+ echo "$1"
+ fi
+}
+
+# Bump version number by incrementing the last numeric, RC or M token
+bump_version_number() {
+ local version=$1
+ [[ -n $version ]] || { echo "missing bump_version_number() argument" >&2; return 1; }
+ if [[ $version =~ ^(.*(\.|-)([A-Za-z]+))([0-9]+)$ ]]; then
+ local prefix=${BASH_REMATCH[1]}
+ local suffix=${BASH_REMATCH[4]}
+ (( suffix++ ))
+ echo "${prefix}${suffix}"
+ return 0;
+ fi
+ local suffix
+ if [[ $version =~ ^(.*)(\-SNAPSHOT)$ ]]; then
+ version=${BASH_REMATCH[1]}
+ suffix="-SNAPSHOT"
+ fi
+ tokens=(${version//\./ })
+ local bumpIndex
+ for i in "${!tokens[@]}"; do
+ if [[ "${tokens[$i]}" =~ ^[0-9]+$ ]] ; then
+ bumpIndex=$i
+ fi
+ done
+ [[ -n $bumpIndex ]] || { echo "unsupported version number" >&2; return 1; }
+ (( tokens[bumpIndex]++ ))
+ local bumpedVersion
+ IFS=. eval 'bumpedVersion="${tokens[*]}"'
+ echo "${bumpedVersion}${suffix}"
+}
+
+# Deduce versions
+deduce_versions() {
+ [[ -n ${GITHUB_OUTPUT} ]] || { echo "missing GITHUB_OUTPUT environment variable" >&2; return 1; }
+ [[ -n ${CURRENT_VERSION} ]] || { echo "missing CURRENT_VERSION environment variable" >&2; return 1; }
+ [[ -n ${RELEASE_TYPE} ]] || { echo "missing RELEASE_TYPE environment variable" >&2; return 1; }
+ if [[ ${RELEASE_TYPE,,} = "milestone" ]]; then
+ releaseVersion=$( get_next_milestone_release ${CURRENT_VERSION})
+ nextVersion=${CURRENT_VERSION}
+ elif [[ ${RELEASE_TYPE,,} = "release-candidate" ]]; then
+ releaseVersion=$( get_next_rc_release ${CURRENT_VERSION})
+ nextVersion=${CURRENT_VERSION}
+ elif [[ ${RELEASE_TYPE,,} = "release" ]]; then
+ releaseVersion=$( get_next_release ${CURRENT_VERSION})
+ nextVersion=$( bump_version_number ${CURRENT_VERSION})
+ else
+ echo "Unknown release type '${RELEASE_TYPE}'" >&2; exit 1;
+ fi
+ echo "release-version=${releaseVersion}" >> "$GITHUB_OUTPUT"
+ echo "next-version=${nextVersion}" >> "$GITHUB_OUTPUT"
+}
diff --git a/.github/actions/deduce-versions/test.sh b/.github/actions/deduce-versions/test.sh
new file mode 100755
index 00000000..0a8e4130
--- /dev/null
+++ b/.github/actions/deduce-versions/test.sh
@@ -0,0 +1 @@
+../.bats/bats/bin/bats test/*.bats
\ No newline at end of file
diff --git a/.github/actions/deduce-versions/test/bump_version.bats b/.github/actions/deduce-versions/test/bump_version.bats
new file mode 100644
index 00000000..5efd9f0b
--- /dev/null
+++ b/.github/actions/deduce-versions/test/bump_version.bats
@@ -0,0 +1,58 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "bump_version_number() should bump '.M'" {
+ run bump_version_number "1.2.0.M2"
+ assert_output "1.2.0.M3"
+}
+
+@test "bump_version_number() should bump '.RC'" {
+ run bump_version_number "1.2.0.RC3"
+ assert_output "1.2.0.RC4"
+}
+
+@test "bump_version_number() should bump '-M'" {
+ run bump_version_number "1.2.0-M2"
+ assert_output "1.2.0-M3"
+}
+
+@test "bump_version_number() should bump '-RC'" {
+ run bump_version_number "1.2.0-RC3"
+ assert_output "1.2.0-RC4"
+}
+
+@test "bump_version_number() should bump without suffix" {
+ run bump_version_number "1.2.0"
+ assert_output "1.2.1"
+}
+
+@test "bump_version_number() should bump '.RELEASE'" {
+ run bump_version_number "1.2.0.RELEASE"
+ assert_output "1.2.1.RELEASE"
+}
+
+@test "bump_version_number() should bump '-SNAPSHOT'" {
+ run bump_version_number "1.2.0-SNAPSHOT"
+ assert_output "1.2.1-SNAPSHOT"
+}
+
+@test "bump_version_number() should bump '.BUILD-SNAPSHOT'" {
+ run bump_version_number "1.2.0.BUILD-SNAPSHOT"
+ assert_output "1.2.1.BUILD-SNAPSHOT"
+}
+
+@test "bump_version_number() when missing argument should fail" {
+ run bump_version_number
+ assert_output "missing bump_version_number() argument"
+ assert [ "$status" -eq 1 ]
+}
+
+@test "bump_version_number() when bad argument should fail" {
+ run bump_version_number "foo.bar.baz"
+ assert_output "unsupported version number"
+ assert [ "$status" -eq 1 ]
+}
diff --git a/.github/actions/deduce-versions/test/deduce_versions.bats b/.github/actions/deduce-versions/test/deduce_versions.bats
new file mode 100644
index 00000000..2ffbf599
--- /dev/null
+++ b/.github/actions/deduce-versions/test/deduce_versions.bats
@@ -0,0 +1,96 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+teardown() {
+ rm .githuboutput | true
+}
+
+@test "deduce_versions() when 'milestone' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="milestone"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3-M2" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.3-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when 'release-candidate' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" "v1.2.3-M2" "v1.2.3-RC1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release-candidate"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3-RC2" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.3-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when 'release' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" "v1.2.3-M2" "v1.2.3-RC1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.4-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when no GITHUB_OUTPUT should fail" {
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing GITHUB_OUTPUT environment variable"
+}
+
+@test "deduce_versions() when no CURRENT_VERSION should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing CURRENT_VERSION environment variable"
+}
+
+@test "deduce_versions() when no RELEASE_TYPE should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing RELEASE_TYPE environment variable"
+}
+
+@test "deduce_versions() when wrong RELEASE_TYPE should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="nope"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "Unknown release type 'nope'"
+}
+
+mock_git_repo() {
+ local tmpdir=$(mktemp -d $BATS_TMPDIR/gitrepo.XXXXXX) >&2
+ mkdir -p "$tmpdir" >&2
+ cd "$tmpdir" >&2
+ git init >&2
+ echo "foo" > foo.txt
+ git add foo.txt >&2
+ git commit -m'Initial commit' >&2
+ for tag in "$@"; do
+ git tag "$tag" >&2
+ done
+ echo "$tmpdir"
+}
\ No newline at end of file
diff --git a/.github/actions/deduce-versions/test/get_next_release.bats b/.github/actions/deduce-versions/test/get_next_release.bats
new file mode 100644
index 00000000..b9be5c0e
--- /dev/null
+++ b/.github/actions/deduce-versions/test/get_next_release.bats
@@ -0,0 +1,119 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "get_next_milestone_release() when has no version should fail" {
+ run get_next_milestone_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_milestone_release() version argument"
+}
+
+@test "get_next_rc_release() when has no version should fail" {
+ run get_next_rc_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_rc_release() version argument"
+}
+
+@test "get_next_tag_based_release() when has no version should fail" {
+ run get_next_tag_based_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_tag_based_release() version argument"
+}
+
+@test "get_next_tag_based_release() when has no tag type should fail" {
+ run get_next_tag_based_release "1.2.3"
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_tag_based_release() tag type argument"
+}
+
+@test "get_next_milestone_release() when has no tag should return M1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_milestone_release "1.2.3-SNAPSHOT"
+ assert_output "1.2.3-M1"
+}
+
+@test "get_next_rc_release() when has no tag should return RC1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_rc_release "1.2.3-SNAPSHOT"
+ assert_output "1.2.3-RC1"
+}
+
+@test "get_next_tag_based_release() when has no tag and dash SNAPSHOT suffix should return dashed X1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3-SNAPSHOT" "X"
+ assert_output "1.2.3-X1"
+}
+
+@test "get_next_tag_based_release() when has no tag and dash BUILD-SNAPSHOT suffix should return dashed X1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3.BUILD-SNAPSHOT" "X"
+ assert_output "1.2.3.X1"
+}
+
+@test "get_next_tag_based_release() when has tags and dashed should return dashed X tag+1" {
+ repo=$( mock_git_repo "v1.2.3-X1" "v1.2.3-X3" "v1.2.3-X2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3-SNAPSHOT" "X"
+ assert_output "1.2.3-X4"
+}
+
+@test "get_next_tag_based_release() when has tags and dashed should return dot X tag+1" {
+ repo=$( mock_git_repo "v1.2.3.X1" "v1.2.3.X3" "v1.2.3.X2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3.BUILD-SNAPSHOT" "X"
+ assert_output "1.2.3.X4"
+}
+
+@test "get_next_tag_based_release() when has multiple tags should return version match tag+1" {
+ repo=$( mock_git_repo "v1.5.0.A1" "v1.5.0.A2" "v1.5.0.B1" "v2.0.0.A1" "v2.0.0.B1" "v2.0.0.B2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.5.0.BUILD-SNAPSHOT" "A"
+ assert_output "1.5.0.A3"
+ run get_next_tag_based_release "1.5.0.BUILD-SNAPSHOT" "B"
+ assert_output "1.5.0.B2"
+ run get_next_tag_based_release "2.0.0.BUILD-SNAPSHOT" "A"
+ assert_output "2.0.0.A2"
+ run get_next_tag_based_release "2.0.0.BUILD-SNAPSHOT" "B"
+ assert_output "2.0.0.B3"
+}
+
+@test "get_next_release() should return next release version with release suffix" {
+ run get_next_release "1.5.0.BUILD-SNAPSHOT" "RELEASE"
+ assert_output "1.5.0.RELEASE"
+ run get_next_release "1.5.0-SNAPSHOT" "RELEASE"
+ assert_output "1.5.0-RELEASE"
+}
+
+@test "get_next_release() should return next release version" {
+ run get_next_release "1.5.0.BUILD-SNAPSHOT"
+ assert_output "1.5.0"
+ run get_next_release "1.5.0-SNAPSHOT"
+ assert_output "1.5.0"
+}
+
+@test "get_next_release() when has no version should fail" {
+ run get_next_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_release() version argument"
+}
+
+mock_git_repo() {
+ local tmpdir=$(mktemp -d $BATS_TMPDIR/gitrepo.XXXXXX) >&2
+ mkdir -p "$tmpdir" >&2
+ cd "$tmpdir" >&2
+ git init >&2
+ echo "foo" > foo.txt
+ git add foo.txt >&2
+ git commit -m'Initial commit' >&2
+ for tag in "$@"; do
+ git tag "$tag" >&2
+ done
+ echo "$tmpdir"
+}
diff --git a/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats b/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats
new file mode 100644
index 00000000..bef64867
--- /dev/null
+++ b/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats
@@ -0,0 +1,21 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "strip_snapshot_suffix() should strip '-SNAPSHOT" {
+ run strip_snapshot_suffix "1.2.0-SNAPSHOT"
+ assert_output "1.2.0"
+}
+
+@test "strip_snapshot_suffix() should strip '.BUILD-SNAPSHOT" {
+ run strip_snapshot_suffix "1.2.0.BUILD-SNAPSHOT"
+ assert_output "1.2.0"
+}
+
+@test "strip_snapshot_suffix() when no suffix should return unchanged" {
+ run strip_snapshot_suffix "1.2.0"
+ assert_output "1.2.0"
+}
diff --git a/.github/actions/publish-eclipse-update-site/action.yml b/.github/actions/publish-eclipse-update-site/action.yml
new file mode 100644
index 00000000..4235c9e8
--- /dev/null
+++ b/.github/actions/publish-eclipse-update-site/action.yml
@@ -0,0 +1,22 @@
+name: 'Publish Eclipse Update Site '
+inputs:
+ version:
+ required: true
+ build-number:
+ required: true
+ artifactory-username:
+ required: true
+ artifactory-password:
+ required: true
+runs:
+ using: composite
+ steps:
+ - name: Stage
+ id: stage
+ shell: bash
+ run: . ${{ github.action_path }}/publish-eclipse-update-site.sh;
+ env:
+ VERSION: "${{ inputs.version }}"
+ BUILD_NUMBER: "${{ inputs.build-number }}"
+ ARTIFACTORY_USERNAME: "${{ inputs.artifactory-username }}"
+ ARTIFACTORY_PASSWORD: "${{ inputs.artifactory-password }}"
diff --git a/ci/scripts/publish-eclipse-update-site-pom-template.xml b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site-pom-template.xml
similarity index 100%
rename from ci/scripts/publish-eclipse-update-site-pom-template.xml
rename to .github/actions/publish-eclipse-update-site/publish-eclipse-update-site-pom-template.xml
diff --git a/ci/scripts/publish-eclipse-update-site.sh b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh
old mode 100755
new mode 100644
similarity index 59%
rename from ci/scripts/publish-eclipse-update-site.sh
rename to .github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh
index 761f74c3..9ddcee29
--- a/ci/scripts/publish-eclipse-update-site.sh
+++ b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh
@@ -1,14 +1,11 @@
-#!/bin/bash
-set -e
+buildInfo=$( jfrog rt curl api/build/spring-javaformat-${VERSION}/${BUILD_NUMBER} )
+groupId=$( echo ${buildInfo} | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' )
+version=$( echo ${buildInfo} | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
-source $(dirname $0)/common.sh
+echo "Publishing ${buildName}/${buildNumber} (${groupId}:${version}) to Eclipse Update Site"
-buildName=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.name' )
-buildNumber=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.number' )
-groupId=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' )
-version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
+jfrog rt dl --build spring-javaformat-${VERSION}/${BUILD_NUMBER} '**/io.spring.javaformat.eclipse.site*.zip'
-echo "Publishing ${buildName}/${buildNumber} to Eclipse Update Site"
curl \
-s \
--connect-timeout 240 \
@@ -17,7 +14,7 @@ curl \
-f \
-H "X-Explode-Archive: true" \
-X PUT \
- -T "artifactory-repo/io/spring/javaformat/io.spring.javaformat.eclipse.site/${version}/io.spring.javaformat.eclipse.site-${version}.zip" \
+ -T "io/spring/javaformat/io.spring.javaformat.eclipse.site/${version}/io.spring.javaformat.eclipse.site-${version}.zip" \
"https://repo.spring.io/javaformat-eclipse-update-site/${version}/" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
releasedVersions=$( curl -s -f -X GET https://repo.spring.io/api/storage/javaformat-eclipse-update-site | jq -r '.children[] | .uri' | cut -c 2- | grep '[0-9].*' | sort -V )
@@ -28,9 +25,8 @@ while read -r releasedVersion; do
repositories="${repositories}https://repo.spring.io/javaformat-eclipse-update-site/${releasedVersion}p2"
done <<< "${releasedVersions}"
-pushd git-repo > /dev/null
-sed "s|##repositories##|${repositories}|" ci/scripts/publish-eclipse-update-site-pom-template.xml > publish-eclipse-update-site-pom.xml
-run_maven -f publish-eclipse-update-site-pom.xml clean package || { echo "Failed to publish" >&2; exit 1; }
+sed "s|##repositories##|${repositories}|" ${GITHUB_ACTION_PATH}/publish-eclipse-update-site-pom-template.xml > publish-eclipse-update-site-pom.xml
+./mvnw -f publish-eclipse-update-site-pom.xml clean package || { echo "Failed to publish" >&2; exit 1; }
curl \
-s \
@@ -52,6 +48,4 @@ curl \
-T "target/repository/artifacts.jar" \
"https://repo.spring.io/javaformat-eclipse-update-site/" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
-popd > /dev/null
-
echo "Publish complete"
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
new file mode 100644
index 00000000..c1d38d98
--- /dev/null
+++ b/.github/actions/setup/action.yml
@@ -0,0 +1,16 @@
+name: 'Setup'
+runs:
+ using: composite
+ steps:
+ - name: Set Up Utilities
+ shell: bash
+ run: sudo apt-get update && sudo apt-get -y install libxml2-utils
+ - name: Set Up Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'liberica'
+ java-version: '17'
+ cache: maven
+ - name: Disable Java Problem Matcher
+ shell: bash
+ run: echo "::remove-matcher owner=java::"
diff --git a/.github/actions/stage-code/action.yml b/.github/actions/stage-code/action.yml
new file mode 100644
index 00000000..1fc1f060
--- /dev/null
+++ b/.github/actions/stage-code/action.yml
@@ -0,0 +1,22 @@
+name: 'Stage '
+inputs:
+ current-version:
+ required: true
+ release-version:
+ required: true
+ next-version:
+ required: true
+outputs:
+ distribution-repository:
+ value: ${{ steps.stage.outputs.distribution-repository }}
+runs:
+ using: composite
+ steps:
+ - name: Stage
+ id: stage
+ shell: bash
+ run: . ${{ github.action_path }}/stage.sh;
+ env:
+ CURRENT_VERSION: "${{ inputs.current-version }}"
+ RELEASE_VERSION: "${{ inputs.release-version }}"
+ NEXT_VERSION: "${{ inputs.next-version }}"
diff --git a/.github/actions/stage-code/stage.sh b/.github/actions/stage-code/stage.sh
new file mode 100644
index 00000000..6ac9c2f0
--- /dev/null
+++ b/.github/actions/stage-code/stage.sh
@@ -0,0 +1,32 @@
+repository=${GITHUB_WORKSPACE}/distribution-repository
+
+echo "Staging ${RELEASE_VERSION} to ${repository} (next version will be ${NEXT_VERSION})"
+
+./mvnw versions:set --batch-mode --no-transfer-progress -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false
+./mvnw org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata --batch-mode --no-transfer-progress
+./mvnw --projects io.spring.javaformat:spring-javaformat-vscode-extension --batch-mode --no-transfer-progress -P '!formatter-dependencies' antrun:run@update-version frontend:install-node-and-npm frontend:npm@update-package-lock
+
+git config user.name "Spring Builds" > /dev/null
+git config user.email "spring-builds@users.noreply.github.com" > /dev/null
+git add pom.xml > /dev/null
+git commit -m"Release v${RELEASE_VERSION}" > /dev/null
+git tag -a "v${RELEASE_VERSION}" -m"Release v${RELEASE_VERSION}" > /dev/null
+
+./mvnw clean deploy --batch-mode --no-transfer-progress -U -Dfull -DaltDeploymentRepository=distribution::file://${repository}
+
+git reset --hard HEAD^ > /dev/null
+if [[ ${NEXT_VERSION} != ${CURRENT_VERSION} ]]; then
+ echo "Setting next development version (v${NEXT_VERSION})"
+ ./mvnw versions:set --batch-mode --no-transfer-progress -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false
+ ./mvnw org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata --batch-mode --no-transfer-progress
+ ./mvnw --projects io.spring.javaformat:spring-javaformat-vscode-extension --batch-mode --no-transfer-progress -P '!formatter-dependencies' antrun:run@update-version frontend:npm@update-package-lock
+ sed -i "s/:release-version:.*/:release-version: ${RELEASE_VERSION}/g" README.adoc
+ sed -i "s/spring-javaformat-gradle-plugin:.*/spring-javaformat-gradle-plugin:${NEXT_VERSION}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
+ sed -i "s/spring-javaformat-checkstyle:.*/spring-javaformat-checkstyle:${NEXT_VERSION}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
+ sed -i "s|.*|${NEXT_VERSION}|" samples/spring-javaformat-maven-sample/pom.xml
+ git add -u . > /dev/null
+ git commit -m"Next development version (v${NEXT_VERSION})" > /dev/null
+fi;
+
+echo "Staged the following files:"
+find ${repository}
diff --git a/.github/artifacts.spec b/.github/artifacts.spec
new file mode 100644
index 00000000..0f6c3aac
--- /dev/null
+++ b/.github/artifacts.spec
@@ -0,0 +1,23 @@
+{
+ "files": [
+ {
+ "aql": {
+ "items.find": {
+ "$and": [
+ {
+ "@build.name": "${buildName}",
+ "@build.number": "${buildNumber}",
+ "name": {
+ "$nmatch": "*.zip"
+ },
+ "name": {
+ "$nmatch": "*.zip.asc"
+ }
+ }
+ ]
+ }
+ },
+ "target": "nexus/"
+ }
+ ]
+}
diff --git a/.github/dco.yml b/.github/dco.yml
new file mode 100644
index 00000000..0c4b142e
--- /dev/null
+++ b/.github/dco.yml
@@ -0,0 +1,2 @@
+require:
+ members: false
diff --git a/.github/workflows/build-and-deploy-snapshot.yml b/.github/workflows/build-and-deploy-snapshot.yml
new file mode 100644
index 00000000..d269a903
--- /dev/null
+++ b/.github/workflows/build-and-deploy-snapshot.yml
@@ -0,0 +1,30 @@
+name: Build and Deploy Snapshot
+on:
+ push:
+ branches:
+ - main
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+jobs:
+ build-and-deploy-snapshot:
+ name: Build and Deploy Snapshot
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'spring-io/spring-javaformat' }}
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Build
+ run: ./mvnw clean deploy --batch-mode --no-transfer-progress --update-snapshots -DaltDeploymentRepository=distribution::file://$(pwd)/distribution-repository
+ - name: Deploy
+ uses: spring-io/artifactory-deploy-action@v0.0.1
+ with:
+ folder: 'distribution-repository'
+ uri: 'https://repo.spring.io'
+ repository: 'libs-snapshot-local'
+ build-name: spring-javaformat
+ username: ${{ secrets.ARTIFACTORY_USERNAME }}
+ password: ${{ secrets.ARTIFACTORY_PASSWORD }}
+ signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
+ signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml
new file mode 100644
index 00000000..9e085b69
--- /dev/null
+++ b/.github/workflows/build-pull-request.yml
@@ -0,0 +1,16 @@
+name: Build Pull Request
+on: pull_request
+permissions:
+ contents: read
+jobs:
+ build:
+ name: Build Pull Request
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'spring-io/spring-javaformat' }}
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Build
+ run: ./mvnw clean install --batch-mode --no-transfer-progress --update-snapshots
diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml
new file mode 100644
index 00000000..e1faac58
--- /dev/null
+++ b/.github/workflows/promote.yml
@@ -0,0 +1,92 @@
+name: Promote
+run-name: >-
+ Promote of version ${{ inputs.version }} (build number ${{ inputs.build-number}}) by ${{ github.actor }} to '${{ inputs.environment }}' environment'
+on:
+ workflow_call:
+ inputs:
+ environment:
+ type: string
+ required: true
+ version:
+ type: string
+ required: true
+ build-number:
+ type: string
+ required: true
+ workflow_dispatch:
+ inputs:
+ environment:
+ description: Environment
+ type: environment
+ required: true
+ version:
+ description: The version number to promote
+ type: string
+ required: true
+ build-number:
+ description: The build number to promote
+ type: string
+ required: true
+jobs:
+ promote:
+ environment: ${{ inputs.environment }}
+ name: Promote
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up JFrog CLI
+ uses: jfrog/setup-jfrog-cli@ff5cb544114ffc152db9cea1cd3d5978d5074946 # v4.5.11
+ env:
+ JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
+ - name: Check Maven Central Sync Status
+ id: check-sync-status
+ run: |
+ url=${{ format('https://repo.maven.apache.org/maven2/io/spring/javaformat/spring-javaformat/{0}/spring-javaformat-{0}.pom', inputs.version) }}
+ status_code=$( curl --write-out '%{http_code}' --head --silent --output /dev/null ${url} )
+ if [ "${status_code}" != 200 ] && [ "${status_code}" != 404 ]; then
+ echo "Unexpected status code ${status_code}"
+ exit 1
+ fi
+ echo "status-code=${status_code}" >> $GITHUB_OUTPUT
+ - name: Download Release Artifacts
+ if: ${{ steps.check-sync-status.outputs.status-code == '404' }}
+ run: jf rt download --spec ./.github/artifacts.spec --spec-vars 'buildName=${{ format('spring-javaformat-{0}', inputs.version) }};buildNumber=${{ inputs.build-number }}'
+ - name: Sync to Maven Central
+ if: ${{ steps.check-sync-status.outputs.status-code == '404' }}
+ uses: spring-io/nexus-sync-action@v0.0.1
+ with:
+ username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
+ password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
+ staging-profile-name: ${{ secrets.OSSRH_S01_STAGING_PROFILE }}
+ create: true
+ upload: true
+ close: true
+ release: true
+ generate-checksums: true
+ - name: Await Maven Central Sync
+ if: ${{ steps.check-sync-status.outputs.status-code == '404' }}
+ run: |
+ url=${{ format('https://repo.maven.apache.org/maven2/io/spring/javaformat/spring-javaformat/{0}/spring-javaformat-{0}.pom', inputs.version) }}
+ echo "Waiting for $url"
+ until curl --fail --head --silent $url > /dev/null
+ do
+ echo "."
+ sleep 60
+ done
+ echo "$url is available"
+ - name: Promote Build
+ if: ${{ steps.check-sync-status.outputs.status-code == '404' }}
+ run: jfrog rt build-promote ${{ format('spring-javaformat-{0}', inputs.version)}} ${{ inputs.build-number }} libs-release-local
+ - name: Publish Eclipse Update Site
+ uses: ./.github/actions/publish-eclipse-update-site
+ with:
+ version: ${{ inputs.version }}
+ build-number: ${{ inputs.build-number }}
+ artifactory-username: ${{ secrets.ARTIFACTORY_USERNAME }}
+ artifactory-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
+ - name: Create GitHub Release
+ uses: ./.github/actions/create-github-release
+ with:
+ milestone: ${{ inputs.version }}
+ token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..c80a4091
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,59 @@
+name: Release
+run-name: >-
+ Release of '${{ github.ref_name }}' branch to '${{ inputs.environment }}' environment by ${{ github.actor }}
+on:
+ workflow_dispatch:
+ inputs:
+ environment:
+ description: Environment
+ type: environment
+ required: true
+jobs:
+ stage:
+ name: Stage
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Get Current Version
+ id: get-version
+ run: echo "current-version=$(xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml)" >> $GITHUB_OUTPUT
+ - name: Deduce Versions
+ id: deduce-versions
+ uses: ./.github/actions/deduce-versions
+ with:
+ current-version: ${{ steps.get-version.outputs.current-version }}
+ release-type: ${{ inputs.environment }}
+ - name: Stage Code
+ id: stage-code
+ uses: ./.github/actions/stage-code
+ with:
+ current-version: ${{ steps.get-version.outputs.current-version }}
+ release-version: ${{ steps.deduce-versions.outputs.release-version }}
+ next-version: ${{ steps.deduce-versions.outputs.next-version }}
+ - name: Deploy to Staging
+ uses: spring-io/artifactory-deploy-action@v0.0.1
+ with:
+ folder: distribution-repository
+ uri: 'https://repo.spring.io'
+ repository: 'libs-staging-local'
+ build-name: ${{ format('spring-javaformat-{0}', steps.deduce-versions.outputs.release-version)}}
+ username: ${{ secrets.ARTIFACTORY_USERNAME }}
+ password: ${{ secrets.ARTIFACTORY_PASSWORD }}
+ signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
+ signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ - name: Push
+ run: git push origin HEAD --tags
+ outputs:
+ release-version: ${{ steps.deduce-versions.outputs.release-version }}
+ release-build-number: ${{ github.run_number }}
+ promote:
+ name: Promote
+ needs: stage
+ uses: ./.github/workflows/promote.yml
+ with:
+ environment: ${{ inputs.environment }}
+ version: ${{needs.stage.outputs.release-version}}
+ build-number: ${{ needs.stage.outputs.release-build-number }}
diff --git a/.github/workflows/rollback.yml b/.github/workflows/rollback.yml
new file mode 100644
index 00000000..43e04a4d
--- /dev/null
+++ b/.github/workflows/rollback.yml
@@ -0,0 +1,41 @@
+name: Rollback
+run-name: >-
+ Rollback of version ${{ inputs.version }} (build number ${{ inputs.build-number}}) by ${{ github.actor }}
+on:
+ workflow_dispatch:
+ inputs:
+ environment:
+ description: Environment
+ type: environment
+ required: true
+ version:
+ description: The version number to roll back
+ type: string
+ required: true
+ build-number:
+ description: The build number to roll back
+ type: string
+ required: true
+jobs:
+ rollback:
+ environment: ${{ inputs.environment }}
+ name: Roll Back
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up JFrog CLI
+ uses: jfrog/setup-jfrog-cli@7c95feb32008765e1b4e626b078dfd897c4340ad # v4.1.2
+ env:
+ JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
+ - name: Delete Staged Artifacts
+ run: |
+ url=${{ format('libs-staging-local/io/spring/javaformat/spring-javaformat/{0}/spring-javaformat-{0}.pom', inputs.version) }}
+ artifact_count=$( jf rt s ${url} --count )
+ if [ "${artifact_count}" != 1 ]; then
+ echo "Unexpected aretifact count ${artifact_count}"
+ exit 1
+ fi
+ build_name=${{ format('spring-javaformat-{0}', inputs.version)}}
+ build_number=${{ inputs.build-number }}
+ jf rt delete --build ${build_name}/${build_number}
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..64d1aa9d
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule ".github/actions/.bats/bats"]
+ path = .github/actions/.bats/bats
+ url = https://github.com/bats-core/bats-core.git
+ tag = v1.11.0
+[submodule ".github/actions/.bats/test_helper/bats-support"]
+ path = .github/actions/.bats/test_helper/bats-support
+ url = https://github.com/bats-core/bats-support.git
+ tag = v0.3.0
+[submodule ".github/actions/.bats/test_helper/bats-assert"]
+ path = .github/actions/.bats/test_helper/bats-assert
+ url = https://github.com/bats-core/bats-assert.git
+ tag = v2.1.0
diff --git a/.sdkmanrc b/.sdkmanrc
index 14fdc133..83ec5a0a 100644
--- a/.sdkmanrc
+++ b/.sdkmanrc
@@ -1,3 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
-java=17.0.6-librca
+java=17.0.14-librca
diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc
index a5c92957..a7e07f62 100644
--- a/CONTRIBUTING.adoc
+++ b/CONTRIBUTING.adoc
@@ -12,10 +12,9 @@ Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
-== Sign the Contributor License Agreement
-Before we accept a non-trivial patch or pull request we will need you to https://cla.pivotal.io/sign/spring[sign the Contributor License Agreement].
-Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do.
-Active contributors might be asked to join the core team, and given the ability to merge pull requests.
+== Include a Signed-off-by Trailer
+All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin[Developer Certificate of Origin (DCO)].
+For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
@@ -29,7 +28,7 @@ should also work without issue.
=== Building From Source
-To build the source you will need to install JDK 11.
+To build the source you will need to install JDK 17.
@@ -206,9 +205,9 @@ Under `spring-javaformat` the following projects are defined:
* `spring-javaformat-formatter-shader` - Shader support classes
* `spring-javaformat-formatter-shaded` - A shaded version of the formatter with all dependencies included
* `spring-javaformat-formatter-eclipse-jdk8` - The eclipse JDK 8 formatter (repackaged and slightly adapted)
-* `spring-javaformat-formatter-eclipse-jdk11` - The eclipse JDK 11 formatter (repackaged and slightly adapted)
+* `spring-javaformat-formatter-eclipse-jdk17` - The eclipse JDK 17 formatter (repackaged and slightly adapted)
* `spring-javaformat-formatter-eclipse-jdt-jdk8` - The eclipse JDT import for JDK 8
-* `spring-javaformat-formatter-eclipse-jdt-jdk11` - The eclipse JDT import for JDK 8
+* `spring-javaformat-formatter-eclipse-jdt-jdk17` - The eclipse JDT import for JDK 17
* `spring-javaformat-formatter-eclipse-rewriter` - Internal utility used to modify eclipse code
* `spring-javaformat-formatter-eclipse-runtime` - Eclipse runtime JAR for use when running outside of Eclipse
diff --git a/README.adoc b/README.adoc
index ffca7a09..bf0a6e1c 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,4 +1,4 @@
-:release-version: 0.0.39
+:release-version: 0.0.46
:checkstyle-version: 9.3
== Spring Java Format
@@ -192,7 +192,7 @@ Your `checkstyle.xml` file should look then like this:
=== Java 8 Support
-By default, the formatter requires Java 11.
+By default, the formatter requires Java 17.
If you are working on an older project, you can use a variation of the formatter based off Eclipse 2021-03 (the latest Eclipse JDT version built with Java 8).
To use the Java 8 version, add a file called `.springjavaformatconfig` to the root of your project with the following content:
@@ -391,7 +391,7 @@ For example:
[source,java,indent=0,subs="normal"]
----
-class Name {
+public class Name {
private final String first;
diff --git a/ci/README.adoc b/ci/README.adoc
deleted file mode 100644
index bdf75bd5..00000000
--- a/ci/README.adoc
+++ /dev/null
@@ -1,18 +0,0 @@
-== Concourse pipeline
-
-Ensure that you've setup the target and can login
-
-[source]
-----
-$ fly -t spring-javaformat login -n spring-javaformat -c https://ci.spring.io
-----
-
-The pipeline can be deployed using the following command:
-
-[source]
-----
-$ fly -t spring-javaformat set-pipeline -p spring-javaformat -c ci/pipeline.yml -l ci/parameters.yml
-----
-
-NOTE: This assumes that you have credhub integration configured with the appropriate
-secrets.
diff --git a/ci/config/release-scripts.yml b/ci/config/release-scripts.yml
deleted file mode 100644
index d31f8cba..00000000
--- a/ci/config/release-scripts.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-logging:
- level:
- io.spring.concourse: DEBUG
-spring:
- main:
- banner-mode: off
-sonatype:
- exclude:
- - 'build-info\.json'
- - '.*\.zip'
diff --git a/ci/images/README.adoc b/ci/images/README.adoc
deleted file mode 100644
index 84eae160..00000000
--- a/ci/images/README.adoc
+++ /dev/null
@@ -1,21 +0,0 @@
-== CI Images
-
-These images are used by CI to run the actual builds.
-
-To build the image locally run the following from this directory:
-
-----
-$ docker build --no-cache -f /Dockerfile .
-----
-
-For example
-
-----
-$ docker build --no-cache -f spring-boot-ci-image/Dockerfile .
-----
-
-To test run:
-
-----
-$ docker run -it --entrypoint /bin/bash ✈
-----
diff --git a/ci/images/ci-image/Dockerfile b/ci/images/ci-image/Dockerfile
deleted file mode 100644
index fbdbb4c0..00000000
--- a/ci/images/ci-image/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-FROM ubuntu:focal-20210401
-
-ADD setup.sh /setup.sh
-ADD get-docker-url.sh /get-docker-url.sh
-RUN ./setup.sh
-
-ENV JAVA_HOME /opt/openjdk
-ENV PATH $JAVA_HOME/bin:$PATH
-ADD docker-lib.sh /docker-lib.sh
-
-ENTRYPOINT [ "switch", "shell=/bin/bash", "--", "codep", "/bin/docker daemon" ]
diff --git a/ci/images/docker-lib.sh b/ci/images/docker-lib.sh
deleted file mode 100755
index 4c7b1d58..00000000
--- a/ci/images/docker-lib.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-# Based on: https://github.com/concourse/docker-image-resource/blob/master/assets/common.sh
-
-DOCKER_LOG_FILE=${DOCKER_LOG_FILE:-/tmp/docker.log}
-SKIP_PRIVILEGED=${SKIP_PRIVILEGED:-false}
-STARTUP_TIMEOUT=${STARTUP_TIMEOUT:-120}
-
-sanitize_cgroups() {
- mkdir -p /sys/fs/cgroup
- mountpoint -q /sys/fs/cgroup || \
- mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
-
- mount -o remount,rw /sys/fs/cgroup
-
- sed -e 1d /proc/cgroups | while read sys hierarchy num enabled; do
- if [ "$enabled" != "1" ]; then
- # subsystem disabled; skip
- continue
- fi
-
- grouping="$(cat /proc/self/cgroup | cut -d: -f2 | grep "\\<$sys\\>")" || true
- if [ -z "$grouping" ]; then
- # subsystem not mounted anywhere; mount it on its own
- grouping="$sys"
- fi
-
- mountpoint="/sys/fs/cgroup/$grouping"
-
- mkdir -p "$mountpoint"
-
- # clear out existing mount to make sure new one is read-write
- if mountpoint -q "$mountpoint"; then
- umount "$mountpoint"
- fi
-
- mount -n -t cgroup -o "$grouping" cgroup "$mountpoint"
-
- if [ "$grouping" != "$sys" ]; then
- if [ -L "/sys/fs/cgroup/$sys" ]; then
- rm "/sys/fs/cgroup/$sys"
- fi
-
- ln -s "$mountpoint" "/sys/fs/cgroup/$sys"
- fi
- done
-
- if ! test -e /sys/fs/cgroup/systemd ; then
- mkdir /sys/fs/cgroup/systemd
- mount -t cgroup -o none,name=systemd none /sys/fs/cgroup/systemd
- fi
-}
-
-start_docker() {
- mkdir -p /var/log
- mkdir -p /var/run
-
- if [ "$SKIP_PRIVILEGED" = "false" ]; then
- sanitize_cgroups
-
- # check for /proc/sys being mounted readonly, as systemd does
- if grep '/proc/sys\s\+\w\+\s\+ro,' /proc/mounts >/dev/null; then
- mount -o remount,rw /proc/sys
- fi
- fi
-
- local mtu=$(cat /sys/class/net/$(ip route get 8.8.8.8|awk '{ print $5 }')/mtu)
- local server_args="--mtu ${mtu}"
- local registry=""
-
- server_args="${server_args}"
-
- for registry in $3; do
- server_args="${server_args} --insecure-registry ${registry}"
- done
-
- if [ -n "$4" ]; then
- server_args="${server_args} --registry-mirror $4"
- fi
-
- try_start() {
- dockerd --data-root /scratch/docker ${server_args} >$DOCKER_LOG_FILE 2>&1 &
- echo $! > /tmp/docker.pid
-
- sleep 1
-
- echo waiting for docker to come up...
- until docker info >/dev/null 2>&1; do
- sleep 1
- if ! kill -0 "$(cat /tmp/docker.pid)" 2>/dev/null; then
- return 1
- fi
- done
- }
-
- export server_args DOCKER_LOG_FILE
- declare -fx try_start
- trap stop_docker EXIT
-
- if ! timeout ${STARTUP_TIMEOUT} bash -ce 'while true; do try_start && break; done'; then
- echo Docker failed to start within ${STARTUP_TIMEOUT} seconds.
- return 1
- fi
-}
-
-stop_docker() {
- local pid=$(cat /tmp/docker.pid)
- if [ -z "$pid" ]; then
- return 0
- fi
-
- kill -TERM $pid
-}
-
diff --git a/ci/images/get-docker-url.sh b/ci/images/get-docker-url.sh
deleted file mode 100755
index 221b3462..00000000
--- a/ci/images/get-docker-url.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-set -e
-
-version="20.10.6"
-echo "https://download.docker.com/linux/static/stable/x86_64/docker-$version.tgz";
diff --git a/ci/images/setup.sh b/ci/images/setup.sh
deleted file mode 100755
index 6c90192c..00000000
--- a/ci/images/setup.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-set -ex
-
-###########################################################
-# UTILS
-###########################################################
-export DEBIAN_FRONTEND=noninteractive
-apt-get update
-apt-get install --no-install-recommends -y tzdata ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
-ln -fs /usr/share/zoneinfo/UTC /etc/localtime
-dpkg-reconfigure --frontend noninteractive tzdata
-rm -rf /var/lib/apt/lists/*
-curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
-
-###########################################################
-# JAVA
-###########################################################
-JDK_URL=https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jdk17.0.6+10-linux-amd64.tar.gz
-
-mkdir -p /opt/openjdk
-cd /opt/openjdk
-curl -L ${JDK_URL} | tar zx --strip-components=1
-test -f /opt/openjdk/bin/java
-test -f /opt/openjdk/bin/javac
-
-###########################################################
-# DOCKER
-###########################################################
-cd /
-DOCKER_URL=$( ./get-docker-url.sh )
-curl -L ${DOCKER_URL} | tar zx
-mv /docker/* /bin/
-chmod +x /bin/docker*
-export ENTRYKIT_VERSION=0.4.0
-curl -L https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz | tar zx
-chmod +x entrykit && \
-mv entrykit /bin/entrykit && \
-entrykit --symlink
\ No newline at end of file
diff --git a/ci/parameters.yml b/ci/parameters.yml
deleted file mode 100644
index d4564cd2..00000000
--- a/ci/parameters.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-project: spring-javaformat
-branch: main
-milestone: 0.0.x
-github-owner: spring-io
-github-repository: spring-javaformat
-docker-hub-ci-organization: springci
-ci-image: spring-javaformat-ci
-artifactory-server: https://repo.spring.io
-build-name: spring-javaformat
-task-timeout: 2h00m
diff --git a/ci/pipeline.yml b/ci/pipeline.yml
deleted file mode 100644
index 128c9014..00000000
--- a/ci/pipeline.yml
+++ /dev/null
@@ -1,326 +0,0 @@
-anchors:
- github-release-source: &github-release-source
- owner: ((github-owner))
- repository: ((github-repository))
- access_token: ((github-ci-release-token))
- artifactory-repo-put-params: &artifactory-repo-put-params
- signing_key: ((signing-key))
- signing_passphrase: ((signing-passphrase))
- repo: libs-snapshot-local
- folder: distribution-repository
- build_uri: https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}
- build_number: ${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}
- disable_checksum_uploads: true
- threads: 8
- sonatype-task-params: &sonatype-task-params
- SONATYPE_USERNAME: ((sonatype-username))
- SONATYPE_PASSWORD: ((sonatype-password))
- SONATYPE_URL: ((sonatype-url))
- SONATYPE_STAGING_PROFILE_ID: ((sonatype-staging-profile-id))
- artifactory-task-params: &artifactory-task-params
- ARTIFACTORY_SERVER: ((artifactory-server))
- ARTIFACTORY_USERNAME: ((artifactory-username))
- ARTIFACTORY_PASSWORD: ((artifactory-password))
- docker-hub-task-params: &docker-hub-task-params
- DOCKER_HUB_USERNAME: ((docker-hub-username))
- DOCKER_HUB_PASSWORD: ((docker-hub-password))
- slack-fail-params: &slack-fail-params
- text: >
- :concourse-failed:
- silent: true
- icon_emoji: ":concourse:"
- username: concourse-ci
- slack-success-params: &slack-success-params
- text: >
- :concourse-succeeded:
- silent: true
- icon_emoji: ":concourse:"
- username: concourse-ci
-resource_types:
-- name: artifactory-resource
- type: registry-image
- source:
- repository: springio/artifactory-resource
- tag: "0.0.18"
- username: ((docker-hub-username))
- password: ((docker-hub-password))
-- name: slack-notification
- type: registry-image
- source:
- repository: cfcommunity/slack-notification-resource
- username: ((docker-hub-username))
- password: ((docker-hub-password))
-resources:
-- name: git-repo
- type: git
- icon: github
- source:
- uri: https://github.com/((github-owner))/((github-repository)).git
- username: ((github-username))
- password: ((github-ci-release-token))
- branch: ((branch))
-- name: github-pre-release
- type: github-release
- icon: briefcase-download-outline
- source:
- <<: *github-release-source
- pre_release: true
- release: false
-- name: github-release
- type: github-release
- icon: briefcase-download
- source:
- <<: *github-release-source
- pre_release: false
- release: true
-- name: ci-images-git-repo
- type: git
- icon: github
- source:
- uri: https://github.com/((github-owner))/((github-repository)).git
- branch: ((branch))
- paths: ["ci/images/*"]
-- name: ci-image
- type: registry-image
- icon: docker
- source:
- username: ((docker-hub-username))
- password: ((docker-hub-password))
- tag: ((milestone))
- repository: ((docker-hub-ci-organization))/((ci-image))
-- name: artifactory-repo
- type: artifactory-resource
- icon: package-variant
- source:
- uri: ((artifactory-server))
- username: ((artifactory-username))
- password: ((artifactory-password))
- build_name: ((build-name))
-- name: slack-alert
- type: slack-notification
- icon: slack
- source:
- url: ((slack-webhook-url))
-jobs:
-- name: build-ci-images
- plan:
- - get: ci-images-git-repo
- trigger: true
- - get: git-repo
- - task: build-ci-image
- privileged: true
- file: git-repo/ci/tasks/build-ci-image.yml
- params:
- DOCKER_HUB_AUTH: ((docker-hub-auth))
- output_mapping:
- image: ci-image
- - put: ci-image
- params:
- image: ci-image/image.tar
-- name: build
- serial: true
- public: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: true
- - do:
- - task: build-project
- image: ci-image
- privileged: true
- timeout: ((task-timeout))
- file: git-repo/ci/tasks/build-project.yml
- params:
- <<: *docker-hub-task-params
- BRANCH: ((branch))
- on_failure:
- do:
- - put: slack-alert
- params:
- <<: *slack-fail-params
- - put: artifactory-repo
- params:
- <<: *artifactory-repo-put-params
- get_params:
- threads: 8
- on_failure:
- do:
- - put: slack-alert
- params:
- <<: *slack-fail-params
- - put: slack-alert
- params:
- <<: *slack-success-params
-- name: stage-milestone
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - task: stage
- image: ci-image
- file: git-repo/ci/tasks/stage.yml
- params:
- <<: *docker-hub-task-params
- RELEASE_TYPE: M
- - put: artifactory-repo
- params:
- <<: *artifactory-repo-put-params
- repo: libs-staging-local
- - put: git-repo
- params:
- repository: stage-git-repo
-- name: stage-rc
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - task: stage
- image: ci-image
- file: git-repo/ci/tasks/stage.yml
- params:
- <<: *docker-hub-task-params
- RELEASE_TYPE: RC
- - put: artifactory-repo
- params:
- <<: *artifactory-repo-put-params
- repo: libs-staging-local
- - put: git-repo
- params:
- repository: stage-git-repo
-- name: stage-release
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - task: stage
- image: ci-image
- file: git-repo/ci/tasks/stage.yml
- params:
- <<: *docker-hub-task-params
- RELEASE_TYPE: RELEASE
- - put: artifactory-repo
- params:
- <<: *artifactory-repo-put-params
- repo: libs-staging-local
- - put: git-repo
- params:
- repository: stage-git-repo
-- name: promote-milestone
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [stage-milestone]
- params:
- download_artifacts: false
- save_build_info: true
- - task: promote
- file: git-repo/ci/tasks/promote.yml
- params:
- RELEASE_TYPE: M
- <<: *artifactory-task-params
- - task: generate-changelog
- file: git-repo/ci/tasks/generate-changelog.yml
- params:
- RELEASE_TYPE: M
- GITHUB_USERNAME: ((github-username))
- GITHUB_TOKEN: ((github-ci-release-token))
- - put: github-pre-release
- params:
- name: generated-changelog/tag
- tag: generated-changelog/tag
- body: generated-changelog/changelog.md
-- name: promote-rc
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [stage-rc]
- params:
- download_artifacts: false
- save_build_info: true
- - task: promote
- file: git-repo/ci/tasks/promote.yml
- params:
- RELEASE_TYPE: RC
- <<: *artifactory-task-params
- - task: generate-changelog
- file: git-repo/ci/tasks/generate-changelog.yml
- params:
- RELEASE_TYPE: RC
- - put: github-pre-release
- params:
- name: generated-changelog/tag
- tag: generated-changelog/tag
- body: generated-changelog/changelog.md
-- name: promote-release
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [stage-release]
- params:
- download_artifacts: true
- save_build_info: true
- - task: promote
- file: git-repo/ci/tasks/promote.yml
- params:
- RELEASE_TYPE: RELEASE
- <<: *artifactory-task-params
- <<: *sonatype-task-params
-- name: create-github-release
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- - get: artifactory-repo
- trigger: true
- passed: [promote-release]
- params:
- download_artifacts: false
- save_build_info: true
- - task: generate-changelog
- file: git-repo/ci/tasks/generate-changelog.yml
- params:
- RELEASE_TYPE: RELEASE
- - put: github-release
- params:
- name: generated-changelog/tag
- tag: generated-changelog/tag
- body: generated-changelog/changelog.md
-- name: publish-eclipse-update-site
- serial: true
- plan:
- - get: ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [promote-release]
- params:
- save_build_info: true
- - task: publish-eclipse-update-site
- image: ci-image
- file: git-repo/ci/tasks/publish-eclipse-update-site.yml
- params:
- ARTIFACTORY_USERNAME: ((artifactory-username))
- ARTIFACTORY_PASSWORD: ((artifactory-password))
-groups:
-- name: builds
- jobs: [build]
-- name: releases
- jobs: [stage-milestone, stage-rc, stage-release, promote-milestone, promote-rc, promote-release, create-github-release, publish-eclipse-update-site]
-- name: ci-images
- jobs: [build-ci-images]
diff --git a/ci/scripts/build-project.sh b/ci/scripts/build-project.sh
deleted file mode 100755
index bc833d36..00000000
--- a/ci/scripts/build-project.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/common.sh
-repository=$(pwd)/distribution-repository
-
-pushd git-repo > /dev/null
-run_maven clean deploy -U -Dfull -DaltDeploymentRepository=distribution::default::file://${repository}
-popd > /dev/null
diff --git a/ci/scripts/common.sh b/ci/scripts/common.sh
deleted file mode 100644
index 8eea3f79..00000000
--- a/ci/scripts/common.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-source /opt/concourse-java.sh
-
-setup_symlinks
-
-if [[ -n $DOCKER_HUB_USERNAME ]]; then
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_PASSWORD
-fi
-
-cleanup_maven_repo "io.spring.javaformat"
diff --git a/ci/scripts/generate-changelog.sh b/ci/scripts/generate-changelog.sh
deleted file mode 100755
index 1e4b6e5b..00000000
--- a/ci/scripts/generate-changelog.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-set -e
-
-version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
-
-java -jar /github-changelog-generator.jar \
- --changelog.repository=spring-io/spring-javaformat \
- ${version} generated-changelog/changelog.md
-
-echo ${version} > generated-changelog/version
-echo v${version} > generated-changelog/tag
diff --git a/ci/scripts/promote.sh b/ci/scripts/promote.sh
deleted file mode 100755
index 4ce8285b..00000000
--- a/ci/scripts/promote.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-set -e
-
-CONFIG_DIR=git-repo/ci/config
-
-version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
-
-export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
-
-java -jar /concourse-release-scripts.jar \
- --spring.config.location=${CONFIG_DIR}/release-scripts.yml \
- publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
-
-java -jar /concourse-release-scripts.jar \
- --spring.config.location=${CONFIG_DIR}/release-scripts.yml \
- promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
-
-echo "Promotion complete"
diff --git a/ci/scripts/stage.sh b/ci/scripts/stage.sh
deleted file mode 100755
index 5b36e8b4..00000000
--- a/ci/scripts/stage.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/common.sh
-repository=$(pwd)/distribution-repository
-
-pushd git-repo > /dev/null
-git fetch --tags --all > /dev/null
-popd > /dev/null
-
-git clone git-repo stage-git-repo > /dev/null
-
-pushd stage-git-repo > /dev/null
-
-snapshotVersion=$( xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml )
-if [[ $RELEASE_TYPE = "M" ]]; then
- stageVersion=$( get_next_milestone_release $snapshotVersion)
- nextVersion=$snapshotVersion
-elif [[ $RELEASE_TYPE = "RC" ]]; then
- stageVersion=$( get_next_rc_release $snapshotVersion)
- nextVersion=$snapshotVersion
-elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
- stageVersion=$( get_next_release $snapshotVersion)
- nextVersion=$( bump_version_number $snapshotVersion)
-else
- echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
-fi
-
-echo "Staging ${stageVersion} (next version will be ${nextVersion})"
-run_maven versions:set -DnewVersion=${stageVersion} -DgenerateBackupPoms=false
-run_maven org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata
-run_maven --projects io.spring.javaformat:spring-javaformat-vscode-extension -P '!formatter-dependencies' antrun:run@update-version frontend:install-node-and-npm frontend:npm@update-package-lock
-
-git config user.name "Spring Builds" > /dev/null
-git config user.email "spring-builds@users.noreply.github.com" > /dev/null
-git add pom.xml > /dev/null
-git commit -m"Release v${stageVersion}" > /dev/null
-git tag -a "v${stageVersion}" -m"Release v${stageVersion}" > /dev/null
-
-run_maven clean deploy -U -Dfull -DaltDeploymentRepository=distribution::default::file://${repository}
-
-git reset --hard HEAD^ > /dev/null
-if [[ $nextVersion != $snapshotVersion ]]; then
- echo "Setting next development version (v$nextVersion)"
- run_maven versions:set -DnewVersion=$nextVersion -DgenerateBackupPoms=false
- run_maven org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata
- run_maven --projects io.spring.javaformat:spring-javaformat-vscode-extension -P '!formatter-dependencies' antrun:run@update-version frontend:npm@update-package-lock
- sed -i "s/:release-version:.*/:release-version: ${stageVersion}/g" README.adoc
- sed -i "s/spring-javaformat-gradle-plugin:.*/spring-javaformat-gradle-plugin:${nextVersion}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
- sed -i "s/spring-javaformat-checkstyle:.*/spring-javaformat-checkstyle:${nextVersion}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
- sed -i "s|.*|${nextVersion}|" samples/spring-javaformat-maven-sample/pom.xml
- git add -u . > /dev/null
- git commit -m"Next development version (v${nextVersion})" > /dev/null
-fi;
-
-popd > /dev/null
-
-echo "Staging Complete"
diff --git a/ci/scripts/sync-to-maven-central.sh b/ci/scripts/sync-to-maven-central.sh
deleted file mode 100755
index f691b9f9..00000000
--- a/ci/scripts/sync-to-maven-central.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
-version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
-java -jar /opt/concourse-release-scripts.jar syncToCentral "RELEASE" $BUILD_INFO_LOCATION || { exit 1; }
-
-echo "Sync complete"
diff --git a/ci/tasks/build-ci-image.yml b/ci/tasks/build-ci-image.yml
deleted file mode 100644
index 6f4de778..00000000
--- a/ci/tasks/build-ci-image.yml
+++ /dev/null
@@ -1,28 +0,0 @@
----
-platform: linux
-image_resource:
- type: registry-image
- source:
- repository: concourse/oci-build-task
- tag: 0.10.0
- username: ((docker-hub-username))
- password: ((docker-hub-password))
-inputs:
-- name: ci-images-git-repo
-outputs:
-- name: image
-caches:
-- path: ci-image-cache
-params:
- CONTEXT: ci-images-git-repo/ci/images
- DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
-run:
- path: /bin/sh
- args:
- - "-c"
- - |
- mkdir -p /root/.docker
- cat > /root/.docker/config.json <4.0.0
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
pom
Spring JavaFormat Build
Spring JavaFormat
@@ -32,12 +32,12 @@
UTF-8
1.8
https://download.eclipse.org/releases/2021-03/202103171000/
- https://download.eclipse.org/releases/2022-12/202212071000/
+ https://download.eclipse.org/releases/2024-03/202403131000/
https://checkstyle.org/eclipse-cs-update-site/
true
1.8.1
1.0b3
- 7.3.1
+ 9.6
3.8.0
9.3
2.4.21
@@ -53,8 +53,8 @@
1.16.0
1.16.0
3.0.3
- 3.0.1
- 3.0.1
+ 4.0.4
+ 4.0.4
@@ -290,6 +290,11 @@
cocoa
x86_64
+
+ macosx
+ cocoa
+ aarch64
+
@@ -461,7 +466,6 @@
src/checkstyle/checkstyle-suppressions.xml
src/checkstyle/checkstyle-header.txt
checkstyle.build.directory=${project.build.directory}
- UTF-8
true
true
true
diff --git a/samples/spring-javaformat-gradle-sample/build.gradle b/samples/spring-javaformat-gradle-sample/build.gradle
index af133b51..9e1f5c9a 100644
--- a/samples/spring-javaformat-gradle-sample/build.gradle
+++ b/samples/spring-javaformat-gradle-sample/build.gradle
@@ -4,7 +4,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.40-SNAPSHOT")
+ classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.47-SNAPSHOT")
}
}
@@ -25,5 +25,5 @@ checkstyle {
}
dependencies {
- checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.40-SNAPSHOT")
+ checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.47-SNAPSHOT")
}
diff --git a/samples/spring-javaformat-maven-sample/pom.xml b/samples/spring-javaformat-maven-sample/pom.xml
index d1787e95..9eb60913 100644
--- a/samples/spring-javaformat-maven-sample/pom.xml
+++ b/samples/spring-javaformat-maven-sample/pom.xml
@@ -8,7 +8,7 @@
0.0.1-SNAPSHOT
UTF-8
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.xml
index 86e75ce9..aebcd72d 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.xml
@@ -2,7 +2,7 @@
@@ -22,7 +22,7 @@
id="io.spring.javaformat.eclipse"
download-size="0"
install-size="0"
- version="0.0.40.qualifier"
+ version="0.0.47.qualifier"
unpack="false"/>
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml
index de73a542..7b4a2a51 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-eclipse
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
io.spring.javaformat.eclipse.feature
eclipse-feature
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/category.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/category.xml
index 1671bd14..cc2c89a7 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/category.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/category.xml
@@ -3,7 +3,7 @@
Maven Integration for Eclipse (maven-eclipse-plugin support)
-
+
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/io.spring.javaformat.eclipse.product b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/io.spring.javaformat.eclipse.product
index 122cd325..20f32d4b 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/io.spring.javaformat.eclipse.product
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/io.spring.javaformat.eclipse.product
@@ -1,7 +1,7 @@
-
+
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml
index 9ad814cb..982bb285 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-eclipse
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
io.spring.javaformat.eclipse.site
eclipse-repository
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/META-INF/MANIFEST.MF b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/META-INF/MANIFEST.MF
index e0eaabe7..d9e188f3 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/META-INF/MANIFEST.MF
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/META-INF/MANIFEST.MF
@@ -7,7 +7,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Spring Java Format Plugin Tests
Bundle-SymbolicName: io.spring.javaformat.eclipse.tests
Automatic-Module-Name: io.spring.javaformat.eclipse.tests
-Bundle-Version: 0.0.40.qualifier
+Bundle-Version: 0.0.47.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ClassPath: .,
lib/assertj-core.jar,
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml
index c478249a..99fa280e 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-eclipse
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
io.spring.javaformat.eclipse.tests
eclipse-test-plugin
@@ -14,6 +14,7 @@
${basedir}/../..
17
+ true
@@ -31,10 +32,31 @@
org.apache.maven.plugins
- maven-javadoc-plugin
-
- **/*Tests.java
-
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocatorTests.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocatorTests.java
index c9261ead..226e0625 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocatorTests.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocatorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -84,7 +84,7 @@ void jdtCorePrefsFormatterWhenDefaultUsesTabs() throws IOException {
Properties properties = new Properties();
properties.load(content);
assertThat(properties.get("org.eclipse.jdt.core.javaFormatter"))
- .isEqualTo("io.spring.javaformat.eclipse.formatter.jdk11.tabs");
+ .isEqualTo("io.spring.javaformat.eclipse.formatter.jdk17.tabs");
}
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/META-INF/MANIFEST.MF b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/META-INF/MANIFEST.MF
index c792e683..12cac3a6 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/META-INF/MANIFEST.MF
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Spring Java Format Plugin
Bundle-SymbolicName: io.spring.javaformat.eclipse;singleton:=true
Automatic-Module-Name: io.spring.javaformat.eclipse
-Bundle-Version: 0.0.40.qualifier
+Bundle-Version: 0.0.47.qualifier
Bundle-Activator: io.spring.javaformat.eclipse.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-11
Require-Bundle: org.eclipse.ui,
@@ -21,6 +21,6 @@ Bundle-ClassPath: .,
lib/spring-javaformat-config.jar,
lib/spring-javaformat-formatter.jar,
lib/spring-javaformat-checkstyle.jar,
- lib/spring-javaformat-formatter-eclipse-jdt-jdk11.jar,
+ lib/spring-javaformat-formatter-eclipse-jdt-jdk17.jar,
lib/spring-javaformat-formatter-eclipse-jdt-jdk8.jar
Bundle-ActivationPolicy: lazy
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
index 7780dc22..9bd6565a 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
@@ -6,5 +6,5 @@ bin.includes = META-INF/,\
lib/spring-javaformat-checkstyle.jar,\
lib/spring-javaformat-config.jar,\
lib/spring-javaformat-formatter.jar,\
- lib/spring-javaformat-formatter-eclipse-jdt-jdk11.jar,\
+ lib/spring-javaformat-formatter-eclipse-jdt-jdk17.jar,\
lib/spring-javaformat-formatter-eclipse-jdt-jdk8.jar
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml
index b6bdf963..f9864bd4 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml
@@ -3,13 +3,13 @@
io.spring.javaformat
spring-javaformat-eclipse
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
io.spring.javaformat.eclipse
eclipse-plugin
@@ -38,6 +38,18 @@
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
org.apache.maven.plugins
maven-javadoc-plugin
@@ -60,7 +72,7 @@
io.spring.javaformat
- spring-javaformat-formatter-eclipse-jdt-jdk11
+ spring-javaformat-formatter-eclipse-jdt-jdk17
${project.version}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Activator.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Activator.java
index 4b03b9eb..cfa779b0 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Activator.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Activator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -41,7 +41,7 @@ public class Activator extends AbstractUIPlugin {
public Activator() {
this.javaCorePlugins.add(new io.spring.javaformat.eclipse.jdt.jdk8.core.JavaCore());
- this.javaCorePlugins.add(new io.spring.javaformat.eclipse.jdt.jdk11.core.JavaCore());
+ this.javaCorePlugins.add(new io.spring.javaformat.eclipse.jdt.jdk17.core.JavaCore());
}
@Override
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Spaces.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java
similarity index 80%
rename from spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Spaces.java
rename to spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java
index e6775b74..8680dbf8 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Spaces.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -27,10 +27,10 @@
*
* @author Phillip Webb
*/
-public class SpringCodeFormatterJdk11Spaces extends SpringCodeFormatter {
+public class SpringCodeFormatterJdk17Spaces extends SpringCodeFormatter {
- public SpringCodeFormatterJdk11Spaces() {
- super(JavaFormatConfig.of(JavaBaseline.V11, IndentationStyle.SPACES));
+ public SpringCodeFormatterJdk17Spaces() {
+ super(JavaFormatConfig.of(JavaBaseline.V17, IndentationStyle.SPACES));
}
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Tabs.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Tabs.java
similarity index 80%
rename from spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Tabs.java
rename to spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Tabs.java
index 78bd7aba..b0301b2e 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk11Tabs.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Tabs.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -27,10 +27,10 @@
*
* @author Phillip Webb
*/
-public class SpringCodeFormatterJdk11Tabs extends SpringCodeFormatter {
+public class SpringCodeFormatterJdk17Tabs extends SpringCodeFormatter {
- public SpringCodeFormatterJdk11Tabs() {
- super(JavaFormatConfig.of(JavaBaseline.V11, IndentationStyle.TABS));
+ public SpringCodeFormatterJdk17Tabs() {
+ super(JavaFormatConfig.of(JavaBaseline.V17, IndentationStyle.TABS));
}
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocator.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocator.java
index 792d207e..5062bfe9 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocator.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -73,7 +73,7 @@ private String updateFormatter(JavaFormatConfig javaFormatConfig, String content
String formatterId = getFormatterId(javaFormatConfig);
if (formatterId != null) {
return content.replace(
- "org.eclipse.jdt.core.javaFormatter=io.spring.javaformat.eclipse.formatter.jdk11.tabs",
+ "org.eclipse.jdt.core.javaFormatter=io.spring.javaformat.eclipse.formatter.jdk17.tabs",
"org.eclipse.jdt.core.javaFormatter=" + formatterId);
}
return content;
@@ -81,6 +81,7 @@ private String updateFormatter(JavaFormatConfig javaFormatConfig, String content
private String getFormatterId(JavaFormatConfig config) {
String jdk = config.getJavaBaseline().name().substring(1);
+ jdk = (!"11".equals(jdk)) ? jdk : "17";
String indentation = config.getIndentationStyle().name().toLowerCase();
return "io.spring.javaformat.eclipse.formatter.jdk" + jdk + "." + indentation;
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.core.prefs b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.core.prefs
index fd682fe6..c08217ef 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.core.prefs
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.core.prefs
@@ -45,7 +45,7 @@ org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
@@ -82,7 +82,7 @@ org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=info
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
@@ -99,6 +99,8 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=info
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.javaFormatter=io.spring.javaformat.eclipse.formatter.jdk11.tabs
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.javaFormatter=io.spring.javaformat.eclipse.formatter.jdk17.tabs
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.ui.prefs b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.ui.prefs
index af9117f9..23d79e64 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.ui.prefs
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
cleanup.add_default_serial_version_id=true
cleanup.add_generated_serial_version_id=false
cleanup.add_missing_annotations=true
diff --git a/spring-javaformat-eclipse/pom.xml b/spring-javaformat-eclipse/pom.xml
index 1388f7a5..3590c925 100644
--- a/spring-javaformat-eclipse/pom.xml
+++ b/spring-javaformat-eclipse/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-eclipse
pom
@@ -17,9 +17,9 @@
- eclipse-jdk11
+ eclipse-jdk17
p2
- ${eclipse.jdk11.repository}
+ ${eclipse.jdk17.repository}
eclipse-checkstyle
diff --git a/spring-javaformat-gradle/io.spring.javaformat.gradle.plugin/pom.xml b/spring-javaformat-gradle/io.spring.javaformat.gradle.plugin/pom.xml
index af870f42..be5f1d3e 100644
--- a/spring-javaformat-gradle/io.spring.javaformat.gradle.plugin/pom.xml
+++ b/spring-javaformat-gradle/io.spring.javaformat.gradle.plugin/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat-gradle
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
io.spring.javaformat
io.spring.javaformat.gradle.plugin
diff --git a/spring-javaformat-gradle/pom.xml b/spring-javaformat-gradle/pom.xml
index bfe50daf..c13954a9 100644
--- a/spring-javaformat-gradle/pom.xml
+++ b/spring-javaformat-gradle/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-gradle
pom
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
index 49a158aa..5a6de1f3 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-gradle
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-gradle-plugin
pom
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
index 096e1109..7e531d42 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
@@ -24,10 +24,10 @@
import java.util.List;
import java.util.stream.Collectors;
-import org.gradle.api.GradleException;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
+import org.gradle.api.tasks.VerificationException;
import io.spring.javaformat.formatter.FileEdit;
@@ -63,7 +63,7 @@ public void checkFormatting() throws IOException, InterruptedException {
message.append("\nRun `format` to fix.");
Files.write(this.reportLocation.toPath(), Collections.singletonList(message.toString()),
StandardOpenOption.CREATE);
- throw new GradleException(message.toString());
+ throw new VerificationException(message.toString());
}
else {
this.reportLocation.createNewFile();
diff --git a/spring-javaformat-intellij-idea/pom.xml b/spring-javaformat-intellij-idea/pom.xml
index 1e5a3d97..4d8c434c 100644
--- a/spring-javaformat-intellij-idea/pom.xml
+++ b/spring-javaformat-intellij-idea/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-intellij-idea
pom
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
index 359131b6..611a99fe 100644
--- a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-intellij-idea
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-intellij-idea-plugin
Spring JavaFormat IntelliJ IDEA Plugin
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime/pom.xml b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime/pom.xml
index 43590141..dc437a12 100644
--- a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime/pom.xml
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-intellij-idea
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-intellij-idea-runtime
pom
diff --git a/spring-javaformat-maven/pom.xml b/spring-javaformat-maven/pom.xml
index 4e1b694d..a14e54eb 100644
--- a/spring-javaformat-maven/pom.xml
+++ b/spring-javaformat-maven/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-maven
pom
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
index aef8d6b2..88294ec8 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat-maven
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-maven-plugin
maven-plugin
diff --git a/spring-javaformat-vscode/pom.xml b/spring-javaformat-vscode/pom.xml
index 1cd28651..c217c403 100644
--- a/spring-javaformat-vscode/pom.xml
+++ b/spring-javaformat-vscode/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-vscode
pom
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json
index fcf5a077..5ea30c21 100644
--- a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "spring-javaformat-vscode-extension",
- "version": "0.0.40-SNAPSHOT",
+ "version": "0.0.47-SNAPSHOT",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "spring-javaformat-vscode-extension",
- "version": "0.0.40-SNAPSHOT",
+ "version": "0.0.47-SNAPSHOT",
"devDependencies": {
"@types/glob": "^8.0.1",
"@types/mocha": "^10.0.1",
@@ -14,7 +14,7 @@
"@types/vscode": "^1.75.0",
"@typescript-eslint/eslint-plugin": "^5.52.0",
"@vscode/test-electron": "^2.2.2",
- "@vscode/vsce": "^2.17.0",
+ "@vscode/vsce": "^2.19.0",
"eslint": "^8.33.0",
"glob": "8.1.0",
"mocha": "10.2.0",
@@ -376,9 +376,9 @@
}
},
"node_modules/@vscode/vsce": {
- "version": "2.17.0",
- "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.17.0.tgz",
- "integrity": "sha512-W4HN5MtTVj/mroQU1d82bUEeWM3dUykMFnMYZPtZ6jrMiHN1PUoN3RGcS896N0r2rIq8KpWDtufcQHgK8VfgpA==",
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.19.0.tgz",
+ "integrity": "sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==",
"dev": true,
"dependencies": {
"azure-devops-node-api": "^11.0.1",
@@ -387,6 +387,7 @@
"commander": "^6.1.0",
"glob": "^7.0.6",
"hosted-git-info": "^4.0.2",
+ "jsonc-parser": "^3.2.0",
"leven": "^3.1.0",
"markdown-it": "^12.3.2",
"mime": "^1.3.4",
@@ -397,7 +398,7 @@
"tmp": "^0.2.1",
"typed-rest-client": "^1.8.4",
"url-join": "^4.0.1",
- "xml2js": "^0.4.23",
+ "xml2js": "^0.5.0",
"yauzl": "^2.3.1",
"yazl": "^2.2.2"
},
@@ -2138,6 +2139,12 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
+ "node_modules/jsonc-parser": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
+ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
+ "dev": true
+ },
"node_modules/keytar": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
@@ -3636,9 +3643,9 @@
"dev": true
},
"node_modules/xml2js": {
- "version": "0.4.23",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
- "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"dev": true,
"dependencies": {
"sax": ">=0.6.0",
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json
index 32267383..63e3b775 100644
--- a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json
@@ -2,7 +2,7 @@
"name": "spring-javaformat-vscode-extension",
"description": "Spring JavaFormat Visual Studio Code Extension",
"displayName": "Spring JavaFormat",
- "version": "0.0.40-SNAPSHOT",
+ "version": "0.0.47-SNAPSHOT",
"publisher": "io.spring.javaformat",
"engines": {
"vscode": "^1.75.0"
@@ -33,7 +33,7 @@
"@types/vscode": "^1.75.0",
"@typescript-eslint/eslint-plugin": "^5.52.0",
"@vscode/test-electron": "^2.2.2",
- "@vscode/vsce": "^2.17.0",
+ "@vscode/vsce": "^2.19.0",
"eslint": "^8.33.0",
"glob": "8.1.0",
"mocha": "10.2.0",
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml b/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml
index 3354a18f..3c439b79 100644
--- a/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat-vscode
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-vscode-extension
Spring JavaFormat Visual Studio Code Extension
diff --git a/spring-javaformat/pom.xml b/spring-javaformat/pom.xml
index 81f95083..7c086cc7 100644
--- a/spring-javaformat/pom.xml
+++ b/spring-javaformat/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat-build
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat
pom
@@ -38,9 +38,9 @@
spring-javaformat-formatter-tests
spring-javaformat-formatter-eclipse-rewriter
spring-javaformat-formatter-eclipse-jdk8
- spring-javaformat-formatter-eclipse-jdk11
+ spring-javaformat-formatter-eclipse-jdk17
spring-javaformat-formatter-eclipse-jdt-jdk8
- spring-javaformat-formatter-eclipse-jdt-jdk11
+ spring-javaformat-formatter-eclipse-jdt-jdk17
spring-javaformat-formatter-eclipse-runtime
spring-javaformat-formatter-shader
spring-javaformat-formatter-shaded
diff --git a/spring-javaformat/spring-javaformat-checkstyle/pom.xml b/spring-javaformat/spring-javaformat-checkstyle/pom.xml
index c6f69b9c..7d74f0cc 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/pom.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-checkstyle
Spring JavaFormat CheckStyle
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringConfigurationLoader.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringConfigurationLoader.java
index 17e4e403..42ca7311 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringConfigurationLoader.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringConfigurationLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2025 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.
@@ -16,7 +16,11 @@
package io.spring.javaformat.checkstyle;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.StringReader;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
@@ -24,11 +28,14 @@
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader.IgnoredModulesOptions;
import com.puppycrawl.tools.checkstyle.PropertyResolver;
-import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+import com.puppycrawl.tools.checkstyle.api.Configurable;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.Context;
+import com.puppycrawl.tools.checkstyle.api.Contextualizable;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
+import com.puppycrawl.tools.checkstyle.api.Scope;
+import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheck;
import org.xml.sax.InputSource;
/**
@@ -49,17 +56,45 @@ class SpringConfigurationLoader {
}
public Collection load(PropertyResolver propertyResolver) {
- Configuration config = loadConfiguration(getClass().getResourceAsStream("spring-checkstyle.xml"),
- propertyResolver);
+ Configuration config = loadConfiguration(loadConfigurationSource(), propertyResolver);
return Arrays.stream(config.getChildren())
.filter(this.moduleFactory::nonFiltered)
.map(this::load)
.collect(Collectors.toList());
}
- private Configuration loadConfiguration(InputStream inputStream, PropertyResolver propertyResolver) {
+ private String loadConfigurationSource() {
+ try (InputStream stream = getClass().getResourceAsStream("spring-checkstyle.xml")) {
+ StringBuilder builder = new StringBuilder();
+ byte[] buffer = new byte[4096];
+ int read;
+ while ((read = stream.read(buffer)) > 0) {
+ builder.append(new String(buffer, 0, read, StandardCharsets.UTF_8));
+ }
+ return preprocessConfigurationSource(builder.toString());
+ }
+ catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private String preprocessConfigurationSource(String source) {
+ return source.replace("{{javadocVariableCheckScopeProperty}}", javadocVariableCheckScopeProperty());
+ }
+
+ private String javadocVariableCheckScopeProperty() {
try {
- InputSource inputSource = new InputSource(inputStream);
+ JavadocVariableCheck.class.getMethod("setScope", Scope.class);
+ return "scope";
+ }
+ catch (NoSuchMethodException ex) {
+ return "accessModifiers";
+ }
+ }
+
+ private Configuration loadConfiguration(String source, PropertyResolver propertyResolver) {
+ try {
+ InputSource inputSource = new InputSource(new StringReader(source));
return ConfigurationLoader.loadConfiguration(inputSource, propertyResolver, IgnoredModulesOptions.EXECUTE);
}
catch (CheckstyleException ex) {
@@ -79,9 +114,7 @@ private Object createModule(Configuration configuration) {
String name = configuration.getName();
try {
Object module = this.moduleFactory.createModule(name);
- if (module instanceof AutomaticBean) {
- initialize(configuration, (AutomaticBean) module);
- }
+ initialize(configuration, module);
return module;
}
catch (CheckstyleException ex) {
@@ -89,9 +122,13 @@ private Object createModule(Configuration configuration) {
}
}
- private void initialize(Configuration configuration, AutomaticBean bean) throws CheckstyleException {
- bean.contextualize(this.context);
- bean.configure(configuration);
+ private void initialize(Configuration configuration, Object module) throws CheckstyleException {
+ if (module instanceof Contextualizable) {
+ ((Contextualizable) module).contextualize(this.context);
+ }
+ if (module instanceof Configurable) {
+ ((Configurable) module).configure(configuration);
+ }
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationLocationCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationLocationCheck.java
new file mode 100644
index 00000000..f0fc0d5e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationLocationCheck.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017-2025 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
+ *
+ * https://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 io.spring.javaformat.checkstyle.check;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+import com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck;
+import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
+
+/**
+ * Spring variant of {@link AnnotationLocationCheck}.
+ *
+ * @author Phillip Webb
+ */
+public class SpringAnnotationLocationCheck extends AbstractCheck {
+
+ private static final Set JSPECIFY_ANNOTATION_NAMES = new HashSet<>(
+ Arrays.asList("NonNull", "Nullable", "NullMarked", "NullUnmarked"));
+
+ @Override
+ public int[] getDefaultTokens() {
+ return new int[] { TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF, TokenTypes.PACKAGE_DEF,
+ TokenTypes.ENUM_CONSTANT_DEF, TokenTypes.ENUM_DEF, TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF,
+ TokenTypes.VARIABLE_DEF, TokenTypes.RECORD_DEF, TokenTypes.COMPACT_CTOR_DEF, };
+ }
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return new int[] { TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF, TokenTypes.PACKAGE_DEF,
+ TokenTypes.ENUM_CONSTANT_DEF, TokenTypes.ENUM_DEF, TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF,
+ TokenTypes.VARIABLE_DEF, TokenTypes.ANNOTATION_DEF, TokenTypes.ANNOTATION_FIELD_DEF,
+ TokenTypes.RECORD_DEF, TokenTypes.COMPACT_CTOR_DEF, };
+ }
+
+ @Override
+ public int[] getRequiredTokens() {
+ return CommonUtil.EMPTY_INT_ARRAY;
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ if (ast.getType() != TokenTypes.VARIABLE_DEF || ast.getParent().getType() == TokenTypes.OBJBLOCK) {
+ DetailAST node = ast.findFirstToken(TokenTypes.MODIFIERS);
+ node = (node != null) ? node : ast.findFirstToken(TokenTypes.ANNOTATIONS);
+ checkAnnotations(node, getExpectedAnnotationIndentation(node));
+ }
+ }
+
+ private int getExpectedAnnotationIndentation(DetailAST node) {
+ return node.getColumnNo();
+ }
+
+ private void checkAnnotations(DetailAST node, int correctIndentation) {
+ DetailAST annotation = node.getFirstChild();
+ while (annotation != null && annotation.getType() == TokenTypes.ANNOTATION) {
+ checkAnnotation(correctIndentation, annotation);
+ annotation = annotation.getNextSibling();
+ }
+ }
+
+ private void checkAnnotation(int correctIndentation, DetailAST annotation) {
+ String annotationName = getAnnotationName(annotation);
+ if (!isCorrectLocation(annotation) && !isJSpecifyAnnotation(annotationName)) {
+ log(annotation, AnnotationLocationCheck.MSG_KEY_ANNOTATION_LOCATION_ALONE, annotationName);
+ }
+ else if (annotation.getColumnNo() != correctIndentation && !hasNodeBefore(annotation)) {
+ log(annotation, AnnotationLocationCheck.MSG_KEY_ANNOTATION_LOCATION, annotationName,
+ annotation.getColumnNo(), correctIndentation);
+ }
+ }
+
+ private String getAnnotationName(DetailAST annotation) {
+ DetailAST identNode = annotation.findFirstToken(TokenTypes.IDENT);
+ if (identNode == null) {
+ identNode = annotation.findFirstToken(TokenTypes.DOT).findFirstToken(TokenTypes.IDENT);
+ }
+ return identNode.getText();
+ }
+
+ private boolean isCorrectLocation(DetailAST annotation) {
+ return !hasNodeBeside(annotation);
+ }
+
+ private boolean hasNodeBeside(DetailAST annotation) {
+ return hasNodeBefore(annotation) || hasNodeAfter(annotation);
+ }
+
+ private boolean hasNodeBefore(DetailAST annotation) {
+ int annotationLineNo = annotation.getLineNo();
+ DetailAST previousNode = annotation.getPreviousSibling();
+ return (previousNode != null) && (annotationLineNo == previousNode.getLineNo());
+ }
+
+ private boolean hasNodeAfter(DetailAST annotation) {
+ int annotationLineNo = annotation.getLineNo();
+ DetailAST nextNode = annotation.getNextSibling();
+ nextNode = (nextNode != null) ? nextNode : annotation.getParent().getNextSibling();
+ return annotationLineNo == nextNode.getLineNo();
+ }
+
+ private boolean isJSpecifyAnnotation(String annotationName) {
+ return JSPECIFY_ANNOTATION_NAMES.contains(annotationName);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAvoidStaticImportCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAvoidStaticImportCheck.java
index 255316b0..2e0de968 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAvoidStaticImportCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAvoidStaticImportCheck.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -37,6 +37,7 @@ public class SpringAvoidStaticImportCheck extends AvoidStaticImportCheck {
excludes.add("io.restassured.RestAssured.*");
excludes.add("org.assertj.core.api.Assertions.*");
excludes.add("org.assertj.core.api.Assumptions.*");
+ excludes.add("org.assertj.core.api.BDDAssertions.*");
excludes.add("org.assertj.core.api.HamcrestCondition.*");
excludes.add("org.awaitility.Awaitility.*");
excludes.add("org.hamcrest.CoreMatchers.*");
@@ -46,11 +47,10 @@ public class SpringAvoidStaticImportCheck extends AvoidStaticImportCheck {
excludes.add("org.junit.internal.matchers.ThrowableMessageMatcher.*");
excludes.add("org.junit.jupiter.api.Assertions.*");
excludes.add("org.junit.jupiter.api.Assumptions.*");
- excludes.add("org.junit.jupiter.api.Assertions.*");
+ excludes.add("org.mockito.AdditionalMatchers.*");
excludes.add("org.mockito.ArgumentMatchers.*");
excludes.add("org.mockito.BDDMockito.*");
excludes.add("org.mockito.Matchers.*");
- excludes.add("org.mockito.AdditionalMatchers.*");
excludes.add("org.mockito.Mockito.*");
excludes.add("org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.*");
excludes.add("org.springframework.boot.configurationprocessor.TestCompiler.*");
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java
index 5b5dc191..cdd8efc4 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java
@@ -19,12 +19,14 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FullIdent;
@@ -38,33 +40,35 @@
*/
public class SpringJUnit5Check extends AbstractSpringCheck {
- private static final String JUNIT4_TEST_ANNOTATION = "org.junit.Test";
+ private static final String JUNIT4_TEST_ANNOTATION_NAME = "org.junit.Test";
- private static final List TEST_ANNOTATIONS;
+ private static final List TEST_ANNOTATIONS;
static {
- Set annotations = new LinkedHashSet<>();
- annotations.add("RepeatedTest");
- annotations.add("Test");
- annotations.add("TestFactory");
- annotations.add("TestTemplate");
- annotations.add("ParameterizedTest");
+ Set annotations = new LinkedHashSet<>();
+ annotations.add(new Annotation("org.junit.jupiter.api", "RepeatedTest"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "Test"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "TestFactory"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "TestTemplate"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "ParameterizedTest"));
TEST_ANNOTATIONS = Collections.unmodifiableList(new ArrayList<>(annotations));
}
- private static final List LIFECYCLE_ANNOTATIONS;
+ private static final List LIFECYCLE_ANNOTATIONS;
static {
- Set annotations = new LinkedHashSet<>();
- annotations.add("BeforeAll");
- annotations.add("BeforeEach");
- annotations.add("AfterAll");
- annotations.add("AfterEach");
+ Set annotations = new LinkedHashSet<>();
+ annotations.add(new Annotation("org.junit.jupiter.api", "BeforeAll"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "BeforeEach"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "AfterAll"));
+ annotations.add(new Annotation("org.junit.jupiter.api", "AfterEach"));
LIFECYCLE_ANNOTATIONS = Collections.unmodifiableList(new ArrayList<>(annotations));
}
+ private static final Annotation NESTED_ANNOTATION = new Annotation("org.junit.jupiter.api", "Nested");
+
private static final Set BANNED_IMPORTS;
static {
Set bannedImports = new LinkedHashSet<>();
- bannedImports.add(JUNIT4_TEST_ANNOTATION);
+ bannedImports.add(JUNIT4_TEST_ANNOTATION_NAME);
bannedImports.add("org.junit.After");
bannedImports.add("org.junit.AfterClass");
bannedImports.add("org.junit.Before");
@@ -82,16 +86,22 @@ public class SpringJUnit5Check extends AbstractSpringCheck {
private final List lifecycleMethods = new ArrayList<>();
+ private final List nestedTestClasses = new ArrayList<>();
+
+ private DetailAST testClass;
+
@Override
public int[] getAcceptableTokens() {
- return new int[] { TokenTypes.METHOD_DEF, TokenTypes.IMPORT };
+ return new int[] { TokenTypes.METHOD_DEF, TokenTypes.IMPORT, TokenTypes.CLASS_DEF };
}
@Override
public void beginTree(DetailAST rootAST) {
+ this.testClass = null;
this.imports.clear();
this.testMethods.clear();
this.lifecycleMethods.clear();
+ this.nestedTestClasses.clear();
}
@Override
@@ -99,26 +109,61 @@ public void visitToken(DetailAST ast) {
switch (ast.getType()) {
case TokenTypes.METHOD_DEF:
visitMethodDef(ast);
+ break;
case TokenTypes.IMPORT:
visitImport(ast);
break;
+ case TokenTypes.CLASS_DEF:
+ visitClassDefinition(ast);
+ break;
}
}
private void visitMethodDef(DetailAST ast) {
- if (AnnotationUtil.containsAnnotation(ast, TEST_ANNOTATIONS)) {
+ if (containsAnnotation(ast, TEST_ANNOTATIONS)) {
this.testMethods.add(ast);
}
- if (AnnotationUtil.containsAnnotation(ast, LIFECYCLE_ANNOTATIONS)) {
+ if (containsAnnotation(ast, LIFECYCLE_ANNOTATIONS)) {
this.lifecycleMethods.add(ast);
}
}
+ private boolean containsAnnotation(DetailAST ast, List annotations) {
+ List annotationNames = annotations.stream()
+ .flatMap((annotation) -> Stream.of(annotation.simpleName, annotation.fullyQualifiedName()))
+ .collect(Collectors.toList());
+ try {
+ return AnnotationUtil.containsAnnotation(ast, annotationNames);
+ }
+ catch (NoSuchMethodError ex) {
+ // Checkstyle >= 10.3 (https://github.com/checkstyle/checkstyle/issues/14134)
+ Set annotationNamesSet = new HashSet<>(annotationNames);
+ try {
+ return (boolean) AnnotationUtil.class.getMethod("containsAnnotation", DetailAST.class, Set.class)
+ .invoke(null, ast, annotationNamesSet);
+ }
+ catch (Exception ex2) {
+ throw new RuntimeException("containsAnnotation failed", ex2);
+ }
+ }
+ }
+
private void visitImport(DetailAST ast) {
FullIdent ident = FullIdent.createFullIdentBelow(ast);
this.imports.put(ident.getText(), ident);
}
+ private void visitClassDefinition(DetailAST ast) {
+ if (ast.getParent().getType() == TokenTypes.COMPILATION_UNIT) {
+ this.testClass = ast;
+ }
+ else {
+ if (containsAnnotation(ast, Arrays.asList(NESTED_ANNOTATION))) {
+ this.nestedTestClasses.add(ast);
+ }
+ }
+ }
+
@Override
public void finishTree(DetailAST rootAST) {
if (shouldCheck()) {
@@ -127,7 +172,7 @@ public void finishTree(DetailAST rootAST) {
}
private boolean shouldCheck() {
- if (this.testMethods.isEmpty() && this.lifecycleMethods.isEmpty()) {
+ if (this.testMethods.isEmpty() && this.lifecycleMethods.isEmpty() && this.nestedTestClasses.isEmpty()) {
return false;
}
for (String unlessImport : this.unlessImports) {
@@ -139,6 +184,10 @@ private boolean shouldCheck() {
}
private void check() {
+ if (this.testClass != null && !isAbstract(this.testClass)) {
+ checkVisibility(Arrays.asList(this.testClass), "junit5.publicClass", null);
+ }
+ checkVisibility(this.nestedTestClasses, "junit5.publicNestedClass", "junit5.privateNestedClass");
for (String bannedImport : BANNED_IMPORTS) {
FullIdent ident = this.imports.get(bannedImport);
if (ident != null) {
@@ -146,29 +195,34 @@ private void check() {
}
}
for (DetailAST testMethod : this.testMethods) {
- if (AnnotationUtil.containsAnnotation(testMethod, JUNIT4_TEST_ANNOTATION)) {
+ if (AnnotationUtil.containsAnnotation(testMethod, JUNIT4_TEST_ANNOTATION_NAME)) {
log(testMethod, "junit5.bannedTestAnnotation");
}
}
- checkMethodVisibility(this.testMethods, "junit5.testPublicMethod", "junit5.testPrivateMethod");
- checkMethodVisibility(this.lifecycleMethods, "junit5.lifecyclePublicMethod", "junit5.lifecyclePrivateMethod");
+ checkVisibility(this.testMethods, "junit5.testPublicMethod", "junit5.testPrivateMethod");
+ checkVisibility(this.lifecycleMethods, "junit5.lifecyclePublicMethod", "junit5.lifecyclePrivateMethod");
}
- private void checkMethodVisibility(List methods, String publicMessageKey, String privateMessageKey) {
- for (DetailAST method : methods) {
- DetailAST modifiers = method.findFirstToken(TokenTypes.MODIFIERS);
+ private boolean isAbstract(DetailAST ast) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+ return modifiers.findFirstToken(TokenTypes.ABSTRACT) != null;
+ }
+
+ private void checkVisibility(List asts, String publicMessageKey, String privateMessageKey) {
+ for (DetailAST ast : asts) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null) {
- log(method, publicMessageKey);
+ log(ast, publicMessageKey);
}
- if (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null) {
- log(method, privateMessageKey);
+ if ((privateMessageKey != null) && (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null)) {
+ log(ast, privateMessageKey);
}
}
}
- private void log(DetailAST method, String key) {
- String name = method.findFirstToken(TokenTypes.IDENT).getText();
- log(method.getLineNo(), method.getColumnNo(), key, name);
+ private void log(DetailAST ast, String key) {
+ String name = ast.findFirstToken(TokenTypes.IDENT).getText();
+ log(ast.getLineNo(), ast.getColumnNo(), key, name);
}
public void setUnlessImports(String unlessImports) {
@@ -176,4 +230,21 @@ public void setUnlessImports(String unlessImports) {
.unmodifiableList(Arrays.stream(unlessImports.split(",")).map(String::trim).collect(Collectors.toList()));
}
+ private static final class Annotation {
+
+ private final String packageName;
+
+ private final String simpleName;
+
+ private Annotation(String packageName, String simpleName) {
+ this.packageName = packageName;
+ this.simpleName = simpleName;
+ }
+
+ private String fullyQualifiedName() {
+ return this.packageName + "." + this.simpleName;
+ }
+
+ }
+
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLeadingWhitespaceCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLeadingWhitespaceCheck.java
index 188e6781..8e3fa83f 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLeadingWhitespaceCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLeadingWhitespaceCheck.java
@@ -17,7 +17,9 @@
package io.spring.javaformat.checkstyle.check;
import java.io.File;
+import java.util.ArrayDeque;
import java.util.Collections;
+import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
@@ -26,6 +28,7 @@
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FileContents;
import com.puppycrawl.tools.checkstyle.api.FileText;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import io.spring.javaformat.config.IndentationStyle;
import io.spring.javaformat.config.JavaFormatConfig;
@@ -49,14 +52,32 @@ public class SpringLeadingWhitespaceCheck extends AbstractSpringCheck {
private IndentationStyle indentationStyle;
+ private final Deque textBlockPairs = new ArrayDeque<>();
+
@Override
public int[] getAcceptableTokens() {
- return NO_REQUIRED_TOKENS;
+ return new int[] { TokenTypes.TEXT_BLOCK_LITERAL_BEGIN, TokenTypes.TEXT_BLOCK_LITERAL_END };
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ super.visitToken(ast);
+ if (ast.getType() == TokenTypes.TEXT_BLOCK_LITERAL_BEGIN) {
+ this.textBlockPairs.add(new TextBlockPair(ast));
+ }
+ else if (ast.getType() == TokenTypes.TEXT_BLOCK_LITERAL_END) {
+ this.textBlockPairs.getLast().end(ast);
+ }
}
@Override
public void beginTree(DetailAST rootAST) {
super.beginTree(rootAST);
+ this.textBlockPairs.clear();
+ }
+
+ @Override
+ public void finishTree(DetailAST rootAST) {
FileContents fileContents = getFileContents();
FileText fileText = fileContents.getText();
File file = fileText.getFile();
@@ -66,8 +87,11 @@ public void beginTree(DetailAST rootAST) {
IndentationStyle indentationStyle = (this.indentationStyle != null) ? this.indentationStyle
: JavaFormatConfig.findFrom(file.getParentFile()).getIndentationStyle();
for (int i = 0; i < fileText.size(); i++) {
- String line = fileText.get(i);
int lineNo = i + 1;
+ if (isInTextBlock(lineNo)) {
+ continue;
+ }
+ String line = fileText.get(i);
Matcher matcher = PATTERN.matcher(line);
boolean found = matcher.find(0);
while (found
@@ -78,6 +102,11 @@ public void beginTree(DetailAST rootAST) {
log(lineNo, "leadingwhitespace.incorrect", indentationStyle.toString().toLowerCase());
}
}
+ super.finishTree(rootAST);
+ }
+
+ private boolean isInTextBlock(int lineNo) {
+ return this.textBlockPairs.stream().anyMatch((textBlockPair) -> textBlockPair.contains(lineNo));
}
public void setIndentationStyle(String indentationStyle) {
@@ -85,4 +114,24 @@ public void setIndentationStyle(String indentationStyle) {
? IndentationStyle.valueOf(indentationStyle.toUpperCase()) : null;
}
+ private static class TextBlockPair {
+
+ private final DetailAST begin;
+
+ private DetailAST end;
+
+ TextBlockPair(DetailAST begin) {
+ this.begin = begin;
+ }
+
+ public boolean contains(int lineNo) {
+ return (lineNo > this.begin.getLineNo()) && (lineNo <= this.end.getLineNo());
+ }
+
+ void end(DetailAST end) {
+ this.end = end;
+ }
+
+ }
+
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java
index eeda7a05..01708750 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -18,14 +18,20 @@
import java.io.File;
+import com.puppycrawl.tools.checkstyle.JavaParser;
+import com.puppycrawl.tools.checkstyle.JavaParser.Options;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FileText;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
- * Checks that test filenames end {@literal Tests.java} and not {@literal Test.java}.
+ * Checks that test class filenames end {@literal Tests.java} and not
+ * {@literal Test.java}.
*
* @author Phillip Webb
+ * @author Andy Wilkinson
*/
public class SpringTestFileNameCheck extends AbstractFileSetCheck {
@@ -33,7 +39,18 @@ public class SpringTestFileNameCheck extends AbstractFileSetCheck {
protected void processFiltered(File file, FileText fileText) throws CheckstyleException {
String path = file.getPath().replace('\\', '/');
if (path.contains("src/test/java") && file.getName().endsWith("Test.java")) {
- log(1, "testfilename.wrongName");
+ visitCompilationUnit(JavaParser.parseFileText(fileText, Options.WITHOUT_COMMENTS));
+ }
+ }
+
+ private void visitCompilationUnit(DetailAST ast) {
+ DetailAST child = ast.getFirstChild();
+ while (child != null) {
+ if (child.getType() == TokenTypes.CLASS_DEF) {
+ log(1, "testfilename.wrongName");
+ return;
+ }
+ child = child.getNextSibling();
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties
index 9982830e..cdea619e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties
@@ -1,3 +1,5 @@
+annotation.location=Annotation ''{0}'' have incorrect indentation level {1}, expected level should be {2}.
+annotation.location.alone=Annotation ''{0}'' should be alone on line.
catch.singleLetter=Single letter catch variable (use "ex" instead).
catch.wideEye=''o_O'' catch variable (use "ex" instead).
header.unexpected=Unexpected header.
@@ -16,6 +18,9 @@ junit5.bannedImport=Import ''{0}'' should not be used in a JUnit 5 test.
junit5.bannedTestAnnotation=JUnit 4 @Test annotation should not be used in a JUnit 5 test.
junit5.lifecyclePrivateMethod=Lifecycle method ''{0}'' should not be private.
junit5.lifecyclePublicMethod=Lifecycle method ''{0}'' should not be public.
+junit5.publicClass=Test class ''{0}'' should not be public.
+junit5.publicNestedClass=Nested test class ''{0}'' should not be public.
+junit5.privateNestedClass=Nested test class ''{0}'' should not be private.
junit5.testPrivateMethod=Test method ''{0}'' should not be private.
junit5.testPublicMethod=Test method ''{0}'' should not be public.
lambda.missingParen=Lambda argument missing parentheses.
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle.xml b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle.xml
index c8838541..4da52558 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle.xml
@@ -22,11 +22,9 @@
+
-
-
-
+
@@ -70,6 +68,7 @@
+
@@ -88,7 +87,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTests.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTests.java
index 7d789a94..f3d31175 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTests.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -123,8 +123,10 @@ public static Collection paramaters() throws IOException {
.map(Parameter::new)
.collect(Collectors.toCollection(ArrayList::new));
parameters.add(new Parameter(new File(SOURCES_DIR, "nopackageinfo/NoPackageInfo.java")));
- parameters.add(new Parameter(new File(SOURCES_DIR, "src/test/java/NamedTest.java")));
- parameters.add(new Parameter(new File(SOURCES_DIR, "src/test/java/NamedTests.java")));
+ Arrays.stream(new File(SOURCES_DIR, "src/test/java").listFiles(SpringChecksTests::sourceFile))
+ .sorted()
+ .map(Parameter::new)
+ .forEach(parameters::add);
return parameters;
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringConfigurationLoaderTests.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringConfigurationLoaderTests.java
index 82e63f1e..33536e6b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringConfigurationLoaderTests.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringConfigurationLoaderTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -16,8 +16,10 @@
package io.spring.javaformat.checkstyle;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
@@ -48,18 +50,23 @@ public void loadShouldLoadChecks() {
assertThat(checks).hasSize(5);
TreeWalker treeWalker = (TreeWalker) checks.toArray()[4];
Set> ordinaryChecks = (Set>) Extractors.byName("ordinaryChecks").extract(treeWalker);
- assertThat(ordinaryChecks).hasSize(60);
+ assertThat(ordinaryChecks).hasSize(61);
+ Set> commentChecks = (Set>) Extractors.byName("commentChecks").extract(treeWalker);
+ assertThat(commentChecks).hasSize(6);
}
@Test
public void loadWithExcludeShouldExcludeChecks() {
- Set excludes = Collections
- .singleton("com.puppycrawl.tools.checkstyle.checks.whitespace.MethodParamPadCheck");
+ Set excludes = new HashSet(
+ Arrays.asList("com.puppycrawl.tools.checkstyle.checks.whitespace.MethodParamPadCheck",
+ "com.puppycrawl.tools.checkstyle.checks.annotation.MissingDeprecatedCheck"));
Collection checks = load(excludes);
assertThat(checks).hasSize(5);
TreeWalker treeWalker = (TreeWalker) checks.toArray()[4];
Set> ordinaryChecks = (Set>) Extractors.byName("ordinaryChecks").extract(treeWalker);
- assertThat(ordinaryChecks).hasSize(59);
+ assertThat(ordinaryChecks).hasSize(60);
+ Set> commentChecks = (Set>) Extractors.byName("commentChecks").extract(treeWalker);
+ assertThat(commentChecks).hasSize(5);
}
@Test
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationOnNewLine.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationOnNewLine.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationOnNewLine.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt
index 376aa13c..7ec1d4de 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt
@@ -1,7 +1,11 @@
++Test class 'JUnit5BadModifier' should not be public
++Nested test class 'PublicNestedTests' should not be public
++Nested test class 'PrivateNestedTests' should not be private
+Test method 'doSomethingWorks' should not be public
+Test method 'doSomethingElseWorks' should not be private
+Test method 'doSomethingWithTemplateWorks' should not be public
+Test method 'doSomethingElseWithTemplateWorks' should not be private
++Test method 'nestedPublicTest' should not be public
+Lifecycle method 'publicBeforeAll' should not be public
+Lifecycle method 'publicBeforeEach' should not be public
+Lifecycle method 'publicAfterAll' should not be public
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5PublicAbstractIsValid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5PublicAbstractIsValid.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5PublicAbstractIsValid.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabsAndTextBlock.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabsAndTextBlock.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabsAndTextBlock.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/AnnotationEndingInTest.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/AnnotationEndingInTest.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/AnnotationEndingInTest.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/InterfaceEndingInTest.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/InterfaceEndingInTest.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/InterfaceEndingInTest.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java
new file mode 100644
index 00000000..8799aae3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-2025 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
+ *
+ * https://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.
+ */
+
+import org.jspecify.annotations.Nullable;
+
+/**
+ * This is a valid example.
+ *
+ * @author Phillip Webb
+ */
+public class AnnotationOnNewLine {
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+ @Nullable String test1() {
+ return "";
+ }
+
+ @Override
+ @Nullable String test2() {
+ return "";
+ }
+
+ @Override
+ public @Nullable String test3() {
+ return "";
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java
index e9b91697..9c59c587 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java
@@ -88,4 +88,19 @@ private void doSomethingElseWithTemplateWorks() {
// test here
}
+ @Nested
+ public static class PublicNestedTests {
+
+ @Test
+ public void nestedPublicTest() {
+
+ }
+
+ }
+
+ @Nested
+ private static class PrivateNestedTests {
+
+ }
+
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5PublicAbstractIsValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5PublicAbstractIsValid.java
new file mode 100644
index 00000000..d56bbbd6
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5PublicAbstractIsValid.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-2024 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
+ *
+ * https://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.
+ */
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * This is a valid example. We allow abstract test classes to be
+ * public so that classes in other packages can extend them.
+ *
+ * @author Andy Wilkinson
+ */
+public abstract class JUnit5PublicAbstractIsValid {
+
+ @Test
+ void doSomethingWorks() {
+ // test here
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java
index cc7b4cd0..bad7023d 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2019 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -21,7 +21,7 @@
*
* @author Phillip Webb
*/
-public class JUnit5Valid {
+class JUnit5Valid {
@Test
void doSomethingWorks() {
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabsAndTextBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabsAndTextBlock.java
new file mode 100644
index 00000000..e9e27b7b
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabsAndTextBlock.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-2021 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
+ *
+ * https://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.
+ */
+
+/**
+ * Leading whitepace with a text block.
+ *
+ * @author Phillip Webb
+ */
+public class LeadingWhitespaceTabsAndTextBlock {
+
+ /**
+ * Comments are ignored.
+ */
+ public void hello() {
+ System.out.println(""""
+ Hello
+ World!""");
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/AnnotationEndingInTest.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/AnnotationEndingInTest.java
new file mode 100644
index 00000000..7579aac2
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/AnnotationEndingInTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-2024 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
+ *
+ * https://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.
+ */
+
+/**
+ * This is an annotation with a legal name. Only test classes must
+ * have a name that ends with {@code Tests}.
+ *
+ * @author Andy Wilkinson
+ */
+public @interface AnnotationEndingInTest {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/InterfaceEndingInTest.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/InterfaceEndingInTest.java
new file mode 100644
index 00000000..b2aad5f9
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/InterfaceEndingInTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-2024 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
+ *
+ * https://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.
+ */
+
+/**
+ * This is an interface with a legal name. Only test classes must
+ * have a name that ends with {@code Tests}.
+ *
+ * @author Andy Wilkinson
+ */
+public interface InterfaceEndingInTest {
+
+}
diff --git a/spring-javaformat/spring-javaformat-config/pom.xml b/spring-javaformat/spring-javaformat-config/pom.xml
index c29dccfd..72fe7b7b 100644
--- a/spring-javaformat/spring-javaformat-config/pom.xml
+++ b/spring-javaformat/spring-javaformat-config/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-config
Spring JavaFormat Config
diff --git a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaBaseline.java b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaBaseline.java
index 90bde24a..492f068c 100644
--- a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaBaseline.java
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaBaseline.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -29,8 +29,8 @@ public enum JavaBaseline {
V8,
/**
- * Use JDK 11+ or higher compatible formatter.
+ * Use JDK 17+ or higher compatible formatter.
*/
- V11
+ V17
}
diff --git a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaFormatConfig.java b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaFormatConfig.java
index 300fcce1..89d19b78 100644
--- a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaFormatConfig.java
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaFormatConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -32,7 +32,7 @@ public interface JavaFormatConfig {
/**
* The default {@link JavaFormatConfig}.
*/
- JavaFormatConfig DEFAULT = of(JavaBaseline.V11, IndentationStyle.TABS);
+ JavaFormatConfig DEFAULT = of(JavaBaseline.V17, IndentationStyle.TABS);
/**
* Java JDK baseline version expected be used when formatting.
diff --git a/spring-javaformat/spring-javaformat-config/src/test/java/io/spring/javaformat/config/PropertiesJavaFormatConfigTests.java b/spring-javaformat/spring-javaformat-config/src/test/java/io/spring/javaformat/config/PropertiesJavaFormatConfigTests.java
index 135e9e0e..4fc21f26 100644
--- a/spring-javaformat/spring-javaformat-config/src/test/java/io/spring/javaformat/config/PropertiesJavaFormatConfigTests.java
+++ b/spring-javaformat/spring-javaformat-config/src/test/java/io/spring/javaformat/config/PropertiesJavaFormatConfigTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2020 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -33,7 +33,7 @@ class PropertiesJavaFormatConfigTests {
void getJavaBaselineWhenNoPropertyReturnsJava11() {
Properties properties = new Properties();
PropertiesJavaFormatConfig config = new PropertiesJavaFormatConfig(properties);
- assertThat(config.getJavaBaseline()).isEqualTo(JavaBaseline.V11);
+ assertThat(config.getJavaBaseline()).isEqualTo(JavaBaseline.V17);
}
@Test
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/META-INF/MANIFEST.MF b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF
similarity index 78%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/META-INF/MANIFEST.MF
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF
index 265335f9..f3b70674 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/META-INF/MANIFEST.MF
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF
@@ -1,8 +1,8 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: Spring Formatter Eclipse Runtime JDK11
-Bundle-SymbolicName: spring-javaformat-formatter-eclipse-jdk11
-Bundle-Version: 0.0.40.qualifier
+Bundle-Name: Spring Formatter Eclipse Runtime JDK17
+Bundle-SymbolicName: spring-javaformat-formatter-eclipse-jdk17
+Bundle-Version: 0.0.47.qualifier
Require-Bundle: org.eclipse.jdt.core;bundle-version="[1.0.0,10.0.0)",
org.eclipse.jface;bundle-version="[1.0.0,10.0.0)",
org.eclipse.jdt.core.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/build.properties b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/build.properties
similarity index 100%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/build.properties
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/build.properties
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml
similarity index 90%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/pom.xml
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml
index 06ae09e3..cd3752e1 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk11/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml
@@ -6,11 +6,11 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
- spring-javaformat-formatter-eclipse-jdk11
+ spring-javaformat-formatter-eclipse-jdk17
eclipse-plugin
- Spring JavaFormat Eclipse JDK-11
+ Spring JavaFormat Eclipse JDK-17
${basedir}/../..
org.eclipse.jdt.core.source,org.eclipse.jface.source,org.eclipse.text.source
@@ -23,13 +23,29 @@
- eclipse-jdk11
+ eclipse-jdk17
p2
- ${eclipse.jdk11.repository}
+ ${eclipse.jdk17.repository}
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
+
org.apache.maven.plugins
maven-antrun-plugin
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
index 438832d3..652b5065 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Spring Formatter Eclipse JDK8
Bundle-SymbolicName: spring-javaformat-formatter-eclipse-jdk8
-Bundle-Version: 0.0.40.qualifier
+Bundle-Version: 0.0.47.qualifier
Require-Bundle: org.eclipse.jdt.core;bundle-version="[1.0.0,10.0.0)",
org.eclipse.jface;bundle-version="[1.0.0,10.0.0)",
org.eclipse.jdt.core.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml
index c0b49d6c..f22c974e 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-eclipse-jdk8
eclipse-plugin
@@ -30,6 +30,22 @@
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
+
org.apache.maven.plugins
maven-antrun-plugin
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
similarity index 85%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/pom.xml
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
index 88c061e4..8621592f 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
@@ -6,17 +6,17 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
- spring-javaformat-formatter-eclipse-jdt-jdk11
- Spring JavaFormat Eclipse JDT JDK-11
+ spring-javaformat-formatter-eclipse-jdt-jdk17
+ Spring JavaFormat Eclipse JDT JDK-17
${basedir}/../..
io.spring.javaformat
- spring-javaformat-formatter-eclipse-jdk11
+ spring-javaformat-formatter-eclipse-jdk17
${project.version}
true
@@ -48,7 +48,7 @@
- io.spring.javaformat:spring-javaformat-formatter-eclipse-jdk11
+ io.spring.javaformat:spring-javaformat-formatter-eclipse-jdk17
org/eclipse/jdt/**
@@ -57,7 +57,7 @@
org.eclipse.jdt
- io.spring.javaformat.eclipse.jdt.jdk11
+ io.spring.javaformat.eclipse.jdt.jdk17
false
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
similarity index 98%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
index 60b0e6e1..46e0f01d 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
similarity index 95%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
index 9873fc96..df66cda6 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk11/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -54,7 +54,7 @@ enum Phase {
/**
* Apply the preparator after wrapping.
*/
- POST_WRAPPING;
+ POST_WRAPPING
}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/pom.xml
index 98b380f7..0689734b 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-eclipse-jdt-jdk8
Spring JavaFormat Eclipse JDT JDK-8
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
index 9873fc96..df66cda6 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -54,7 +54,7 @@ enum Phase {
/**
* Apply the preparator after wrapping.
*/
- POST_WRAPPING;
+ POST_WRAPPING
}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
index 655863ec..306b6166 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
@@ -5,7 +5,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-eclipse-rewriter
Spring JavaFormat Eclipse Rewriter
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/src/main/java/io/spring/javaformat/formatter/eclipse/rewrite/EclipseRewriter.java b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/src/main/java/io/spring/javaformat/formatter/eclipse/rewrite/EclipseRewriter.java
index 60aad783..e7ccea52 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/src/main/java/io/spring/javaformat/formatter/eclipse/rewrite/EclipseRewriter.java
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/src/main/java/io/spring/javaformat/formatter/eclipse/rewrite/EclipseRewriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -80,7 +80,7 @@ private void rewrite(JdkVersion jdkVersion, FileSystem zip) throws IOException {
deleteWrapPreparator(zip);
}
else {
- rewrite(zip, "org/eclipse/osgi/util/NLS.class", NlsJdk11Manipulator::new);
+ rewrite(zip, "org/eclipse/osgi/util/NLS.class", NlsJdk17Manipulator::new);
}
}
@@ -111,12 +111,12 @@ public static void main(String[] args) throws Exception {
private static class DefaultCodeFormatterManipulator extends ClassVisitor {
DefaultCodeFormatterManipulator(ClassVisitor visitor) {
- super(Opcodes.ASM7, visitor);
+ super(Opcodes.ASM9, visitor);
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
- if (access == Opcodes.ACC_PRIVATE && UPDATED_FIELDS.contains(name)) {
+ if ((access & Opcodes.ACC_PRIVATE) != 0 && UPDATED_FIELDS.contains(name)) {
access = Opcodes.ACC_PROTECTED;
}
return super.visitField(access, name, desc, signature, value);
@@ -124,7 +124,7 @@ public FieldVisitor visitField(int access, String name, String desc, String sign
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- if (access == Opcodes.ACC_PRIVATE && UPDATED_METHODS.contains(name)) {
+ if ((access & Opcodes.ACC_PRIVATE) != 0 && UPDATED_METHODS.contains(name)) {
access = Opcodes.ACC_PROTECTED;
}
return new DefaultCodeFormatterMethodManipulator(
@@ -140,7 +140,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
private static class DefaultCodeFormatterMethodManipulator extends MethodVisitor {
DefaultCodeFormatterMethodManipulator(MethodVisitor mv) {
- super(Opcodes.ASM7, mv);
+ super(Opcodes.ASM9, mv);
}
@Override
@@ -160,7 +160,7 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc,
private static class NlsJdk8Manipulator extends ClassVisitor {
NlsJdk8Manipulator(ClassVisitor visitor) {
- super(Opcodes.ASM7, visitor);
+ super(Opcodes.ASM9, visitor);
}
@Override
@@ -182,7 +182,7 @@ private static class NslJdk8MethodManipulator extends MethodVisitor {
private final MethodVisitor methodVisitor;
NslJdk8MethodManipulator(MethodVisitor mv) {
- super(Opcodes.ASM7, null);
+ super(Opcodes.ASM9, null);
this.methodVisitor = mv;
}
@@ -202,16 +202,16 @@ public void visitEnd() {
* {@link ClassVisitor} to update the {@code NLS} class in the JDK 8 version so it
* doesn't use a System property to disable warning messages.
*/
- private static class NlsJdk11Manipulator extends ClassVisitor {
+ private static class NlsJdk17Manipulator extends ClassVisitor {
- NlsJdk11Manipulator(ClassVisitor visitor) {
- super(Opcodes.ASM7, visitor);
+ NlsJdk17Manipulator(ClassVisitor visitor) {
+ super(Opcodes.ASM9, visitor);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if ("".equals(name)) {
- return new NslJdk11MethodManipulator(super.visitMethod(access, name, desc, signature, exceptions));
+ return new NslJdk17MethodManipulator(super.visitMethod(access, name, desc, signature, exceptions));
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
@@ -222,12 +222,12 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
* {@link MethodVisitor} to update the {@code NLS} class in the JDK 8 version so it
* doesn't use a System property to disable warning messages.
*/
- private static class NslJdk11MethodManipulator extends MethodVisitor {
+ private static class NslJdk17MethodManipulator extends MethodVisitor {
private final MethodVisitor methodVisitor;
- NslJdk11MethodManipulator(MethodVisitor mv) {
- super(Opcodes.ASM7, null);
+ NslJdk17MethodManipulator(MethodVisitor mv) {
+ super(Opcodes.ASM9, null);
this.methodVisitor = mv;
}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
index 12989051..73007642 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-eclipse-runtime
Spring JavaFormat Eclipse Runtime
diff --git a/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml b/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml
index 6222dd58..5476a0c9 100644
--- a/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-shaded
Spring JavaFormat Formatter Shaded
diff --git a/spring-javaformat/spring-javaformat-formatter-shader/pom.xml b/spring-javaformat/spring-javaformat-formatter-shader/pom.xml
index fc4b092a..0648a5b4 100644
--- a/spring-javaformat/spring-javaformat-formatter-shader/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-shader/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-shader
Spring JavaFormat Formatter Shader
diff --git a/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml b/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml
index 203a96a0..e34149fe 100644
--- a/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-test-support
Spring JavaFormat Formatter Test Support
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/pom.xml b/spring-javaformat/spring-javaformat-formatter-tests/pom.xml
index a50507a4..ce9bf2a2 100644
--- a/spring-javaformat/spring-javaformat-formatter-tests/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-tests/pom.xml
@@ -6,13 +6,13 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter-tests
Spring JavaFormat Formatter Tests
${basedir}/../..
- 11
+ 17
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/AbstractFormatterTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/AbstractFormatterTests.java
index bf873dd2..f2bebe0a 100644
--- a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/AbstractFormatterTests.java
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/AbstractFormatterTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2025 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.
@@ -21,6 +21,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
import io.spring.javaformat.config.JavaBaseline;
@@ -60,6 +61,7 @@ protected static Item[] items(String expectedOverride) {
addItem(items, javaBaseline, source, expected, config);
}
}
+ items.sort(Comparator.comparing(Item::getName));
return items.toArray(new Item[0]);
}
@@ -139,6 +141,10 @@ private JavaFormatConfig loadConfig(JavaBaseline javaBaseline, File configFile)
return JavaFormatConfig.of(javaBaseline, config.getIndentationStyle());
}
+ String getName() {
+ return this.source.getName();
+ }
+
public File getSource() {
return this.source;
}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterIntegrationTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterIntegrationTests.java
index 88d41505..4639a550 100644
--- a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterIntegrationTests.java
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -54,16 +54,16 @@ void formatCodeWithV8BaselineCanFormatOnAllVersions(String version) throws Excep
}
@ParameterizedTest
- @ValueSource(strings = { "11", "17" })
+ @ValueSource(strings = { "17" })
void formatCodeWithV11BaselineCanFormatOn11OrHigher(String version) throws Exception {
- runFormatter(JavaBaseline.V11, version);
+ runFormatter(JavaBaseline.V17, version);
}
@ParameterizedTest
@ValueSource(strings = "8")
void formatCodeWithV11BaselineCannotFormatOn8(String version) throws Exception {
assertThatExceptionOfType(ContainerLaunchException.class)
- .isThrownBy(() -> runFormatter(JavaBaseline.V11, version));
+ .isThrownBy(() -> runFormatter(JavaBaseline.V17, version));
}
private void runFormatter(JavaBaseline baseline, String version) throws IOException, Exception {
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/javadoc-with-format-off.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/javadoc-with-format-off.txt
new file mode 100644
index 00000000..157ea11b
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/javadoc-with-format-off.txt
@@ -0,0 +1,8 @@
+/**
+ * This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test.
+ * @formatter:off
+ * @formatter:on
+ */
+public class Format {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-not-jspecify.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-not-jspecify.txt
new file mode 100644
index 00000000..dbdb1f45
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-not-jspecify.txt
@@ -0,0 +1,23 @@
+package example;
+
+import com.example.Nullable;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override
+ @Nullable
+ String myMethod(String param);
+
+ @Override
+ public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array,
+ @Nullable String @Nullable... varargs);
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-wildcard-import.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-wildcard-import.txt
new file mode 100644
index 00000000..053cbc13
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable-wildcard-import.txt
@@ -0,0 +1,22 @@
+package example;
+
+import org.jspecify.annotations.*;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override
+ @Nullable String myMethod(String param);
+
+ @Override
+ public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array,
+ @Nullable String @Nullable ... varargs);
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable.txt
new file mode 100644
index 00000000..b3e8f925
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/nullable.txt
@@ -0,0 +1,29 @@
+package example;
+
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override
+ @Nullable String myMethod(String param);
+
+ @Override
+ public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array,
+ @Nullable String @Nullable ... varargs);
+
+ default Object inBody() {
+ @Nullable Object[] args = new Object[length];
+ @Nullable List<@Nullable Object> list = new Object[length];
+ Object @Nullable [] moreArgs = new Object[length];
+ return args;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/v11/record-with-generic.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/v17/record-with-generic.txt
similarity index 100%
rename from spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/v11/record-with-generic.txt
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/v17/record-with-generic.txt
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/javadoc-with-format-off.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/javadoc-with-format-off.txt
new file mode 100644
index 00000000..dbfef5c0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/javadoc-with-format-off.txt
@@ -0,0 +1,7 @@
+/**
+ * This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test.
+ * @formatter:off
+ * @formatter:on
+ */
+public class Format {
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-not-jspecify.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-not-jspecify.txt
new file mode 100644
index 00000000..011a2189
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-not-jspecify.txt
@@ -0,0 +1,20 @@
+package example;
+
+import com.example.Nullable;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override @Nullable String myMethod(String param);
+
+ @Override public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array, @Nullable
+ String @Nullable ... varargs);
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-wildcard-import.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-wildcard-import.txt
new file mode 100644
index 00000000..11c65198
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable-wildcard-import.txt
@@ -0,0 +1,20 @@
+package example;
+
+import org.jspecify.annotations.*;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override @Nullable String myMethod(String param);
+
+ @Override public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array, @Nullable
+ String @Nullable ... varargs);
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable.txt
new file mode 100644
index 00000000..acbefead
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/source/nullable.txt
@@ -0,0 +1,27 @@
+package example;
+
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Nullable.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public interface ExampleNullables {
+
+ @Override @Nullable String myMethod(String param);
+
+ @Override public @Nullable String myPublicMethod(String param);
+
+ Object myArrayMethod(@Nullable String string, @Nullable String @Nullable [] array, @Nullable
+ String @Nullable ... varargs);
+
+ default Object inBody() {
+ @Nullable Object[] args = new Object[length];
+ @Nullable List<@Nullable Object> list = new Object[length];
+ Object @Nullable [] moreArgs = new Object[length];
+ return args;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/pom.xml b/spring-javaformat/spring-javaformat-formatter/pom.xml
index fc5611c1..24b89552 100644
--- a/spring-javaformat/spring-javaformat-formatter/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter/pom.xml
@@ -6,7 +6,7 @@
io.spring.javaformat
spring-javaformat
- 0.0.40-SNAPSHOT
+ 0.0.47-SNAPSHOT
spring-javaformat-formatter
Spring JavaFormat Formatter
@@ -27,7 +27,7 @@
io.spring.javaformat
- spring-javaformat-formatter-eclipse-jdt-jdk11
+ spring-javaformat-formatter-eclipse-jdt-jdk17
${project.version}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/Formatter.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/Formatter.java
index 53415a7a..dd87b20c 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/Formatter.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/Formatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -24,7 +24,7 @@
import io.spring.javaformat.config.JavaBaseline;
import io.spring.javaformat.config.JavaFormatConfig;
import io.spring.javaformat.formatter.eclipse.EclipseCodeFormatter;
-import io.spring.javaformat.formatter.jdk11.eclipse.EclipseJdk11CodeFormatter;
+import io.spring.javaformat.formatter.jdk17.eclipse.EclipseJdk17CodeFormatter;
import io.spring.javaformat.formatter.jdk8.eclipse.EclipseJdk8CodeFormatter;
/**
@@ -76,7 +76,7 @@ public Formatter() {
*/
public Formatter(JavaFormatConfig javaFormatConfig) {
this.delegate = javaFormatConfig.getJavaBaseline() == JavaBaseline.V8
- ? new EclipseJdk8CodeFormatter(javaFormatConfig) : new EclipseJdk11CodeFormatter(javaFormatConfig);
+ ? new EclipseJdk8CodeFormatter(javaFormatConfig) : new EclipseJdk17CodeFormatter(javaFormatConfig);
}
/**
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/CodeLineBreakPreparator.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/CodeLineBreakPreparator.java
similarity index 77%
rename from spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/CodeLineBreakPreparator.java
rename to spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/CodeLineBreakPreparator.java
index 15057474..51c98b52 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/CodeLineBreakPreparator.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/CodeLineBreakPreparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-package io.spring.javaformat.formatter.jdk11.eclipse;
+package io.spring.javaformat.formatter.jdk17.eclipse;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.ASTNode;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.ASTVisitor;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.AbstractTypeDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.AnnotationTypeDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.EnumDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.FieldDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.SimpleName;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.TypeDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.formatter.CodeFormatter;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.compiler.parser.TerminalTokens;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.Preparator;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.Token;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.TokenManager;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTNode;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTVisitor;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.AbstractTypeDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.AnnotationTypeDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.EnumDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.FieldDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.SimpleName;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.TypeDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.formatter.CodeFormatter;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.compiler.parser.TerminalTokens;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Preparator;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Token;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.TokenManager;
/**
* {@link Preparator} to finetune curly-brace line breaks.
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/EclipseJdk11CodeFormatter.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/EclipseJdk17CodeFormatter.java
similarity index 68%
rename from spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/EclipseJdk11CodeFormatter.java
rename to spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/EclipseJdk17CodeFormatter.java
index e4d57dc5..b902e3f3 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/EclipseJdk11CodeFormatter.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/EclipseJdk17CodeFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2025 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.
@@ -14,35 +14,36 @@
* limitations under the License.
*/
-package io.spring.javaformat.formatter.jdk11.eclipse;
+package io.spring.javaformat.formatter.jdk17.eclipse;
import java.util.Map;
import io.spring.javaformat.config.JavaFormatConfig;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.ExtendedCodeFormatter;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.Preparator;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.ExtendedCodeFormatter;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Preparator;
import io.spring.javaformat.formatter.eclipse.EclipseCodeFormatter;
import io.spring.javaformat.formatter.eclipse.Options;
/**
- * Internal delegate JDK 11 baseline {@link EclipseCodeFormatter} to apply Spring
+ * Internal delegate JDK 17 baseline {@link EclipseCodeFormatter} to apply Spring
* {@literal formatter.prefs} and add {@link Preparator Preparators}.
*
* @author Phillip Webb
*/
-public class EclipseJdk11CodeFormatter extends ExtendedCodeFormatter implements EclipseCodeFormatter {
+public class EclipseJdk17CodeFormatter extends ExtendedCodeFormatter implements EclipseCodeFormatter {
private final Map appliedOptions;
- public EclipseJdk11CodeFormatter(JavaFormatConfig javaFormatConfig) {
- this(new Options("io.spring.javaformat.eclipse.jdt.jdk11").load(javaFormatConfig));
+ public EclipseJdk17CodeFormatter(JavaFormatConfig javaFormatConfig) {
+ this(new Options("io.spring.javaformat.eclipse.jdt.jdk17").load(javaFormatConfig));
}
- EclipseJdk11CodeFormatter(Map options) {
+ EclipseJdk17CodeFormatter(Map options) {
super(options);
this.appliedOptions = options;
addPreparator(new JavadocLineBreakPreparator());
addPreparator(new CodeLineBreakPreparator());
+ addPreparator(new JSpecifyPreparator());
}
@Override
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JSpecifyPreparator.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JSpecifyPreparator.java
new file mode 100644
index 00000000..645bf75d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JSpecifyPreparator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2017-2025 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
+ *
+ * https://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 io.spring.javaformat.formatter.jdk17.eclipse;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTNode;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTVisitor;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.Annotation;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.CompilationUnit;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.IExtendedModifier;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ImportDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.MethodDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.SingleVariableDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.VariableDeclarationStatement;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.formatter.CodeFormatter;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Preparator;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.TokenManager;
+
+public class JSpecifyPreparator implements Preparator {
+
+ private static final String PACKAGE_NAME = "org.jspecify.annotations";
+
+ private static final Set ANNOTATION_NAMES = new HashSet<>(
+ Arrays.asList("NonNull", "Nullable", "NullMarked", "NullUnmarked"));
+
+ private static final Set FULLY_QUALIFIED_ANNOTATION_NAMES = ANNOTATION_NAMES.stream()
+ .map((annotationName) -> PACKAGE_NAME + "." + annotationName)
+ .collect(Collectors.toSet());
+
+ @Override
+ public void apply(int kind, TokenManager tokenManager, ASTNode astRoot) {
+ if ((kind & CodeFormatter.K_COMPILATION_UNIT) != 0) {
+ ASTVisitor visitor = new Vistor(tokenManager);
+ astRoot.accept(visitor);
+ }
+ }
+
+ private static class Vistor extends ASTVisitor {
+
+ private final TokenManager tokenManager;
+
+ private final Map fullyQualified = new HashMap<>();
+
+ Vistor(TokenManager tokenManager) {
+ this.tokenManager = tokenManager;
+ }
+
+ @Override
+ public boolean visit(CompilationUnit node) {
+ this.fullyQualified.clear();
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(ImportDeclaration node) {
+ String name = node.getName().toString();
+ if (name.equals(PACKAGE_NAME) || name.startsWith(PACKAGE_NAME)) {
+ Set annotationNames = (node.isOnDemand()) ? ANNOTATION_NAMES
+ : Collections.singleton(name.substring(name.lastIndexOf(".") + 1));
+ for (String annotationName : annotationNames) {
+ this.fullyQualified.put(annotationName, PACKAGE_NAME + "." + annotationName);
+ }
+ }
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(MethodDeclaration node) {
+ clearLineBreaksIfHasJSpecifyAnnotation(node.modifiers());
+ return true;
+ }
+
+ @Override
+ public boolean visit(VariableDeclarationStatement node) {
+ clearLineBreaksIfHasJSpecifyAnnotation(node.modifiers());
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void endVisit(SingleVariableDeclaration node) {
+ if (node.isVarargs()) {
+ List annotations = node.varargsAnnotations();
+ Annotation lastAnnotation = getLastAnnotation(annotations);
+ if (isJSpecifyAnnotation(lastAnnotation)) {
+ this.tokenManager.lastTokenIn(lastAnnotation, -1).spaceAfter();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void clearLineBreaksIfHasJSpecifyAnnotation(List> modifiers) {
+ Annotation lastAnnotation = getLastAnnotation((List) modifiers);
+ if (isJSpecifyAnnotation(lastAnnotation)) {
+ this.tokenManager.lastTokenIn(lastAnnotation, -1).clearLineBreaksAfter();
+ }
+ }
+
+ private Annotation getLastAnnotation(List extends IExtendedModifier> modifiers) {
+ Annotation annotation = null;
+ for (IExtendedModifier modifier : modifiers) {
+ if (!modifier.isAnnotation()) {
+ return annotation;
+ }
+ annotation = (Annotation) modifier;
+ }
+ return annotation;
+ }
+
+ private boolean isJSpecifyAnnotation(Annotation annotation) {
+ String fullyQualifiedName = (annotation != null)
+ ? this.fullyQualified.get(annotation.getTypeName().toString()) : null;
+ return (fullyQualifiedName != null) && FULLY_QUALIFIED_ANNOTATION_NAMES.contains(fullyQualifiedName);
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/JavadocLineBreakPreparator.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JavadocLineBreakPreparator.java
similarity index 74%
rename from spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/JavadocLineBreakPreparator.java
rename to spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JavadocLineBreakPreparator.java
index e367de90..b66efa27 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk11/eclipse/JavadocLineBreakPreparator.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk17/eclipse/JavadocLineBreakPreparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -14,25 +14,25 @@
* limitations under the License.
*/
-package io.spring.javaformat.formatter.jdk11.eclipse;
+package io.spring.javaformat.formatter.jdk17.eclipse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.ASTNode;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.ASTVisitor;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.AbstractTypeDeclaration;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.Comment;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.CompilationUnit;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.Javadoc;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.TagElement;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.dom.TextElement;
-import io.spring.javaformat.eclipse.jdt.jdk11.core.formatter.CodeFormatter;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.compiler.parser.TerminalTokens;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.Preparator;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.Token;
-import io.spring.javaformat.eclipse.jdt.jdk11.internal.formatter.TokenManager;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTNode;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.ASTVisitor;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.AbstractTypeDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.Comment;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.CompilationUnit;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.Javadoc;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.TagElement;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.dom.TextElement;
+import io.spring.javaformat.eclipse.jdt.jdk17.core.formatter.CodeFormatter;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.compiler.parser.TerminalTokens;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Preparator;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.Token;
+import io.spring.javaformat.eclipse.jdt.jdk17.internal.formatter.TokenManager;
/**
* {@link Preparator} to finetune Javadoc whitespace.
@@ -93,7 +93,8 @@ private static class Vistor extends ASTVisitor {
public boolean visit(Javadoc node) {
int commentIndex = this.tokenManager.firstIndexIn(node, TerminalTokens.TokenNameCOMMENT_JAVADOC);
Token commentToken = this.tokenManager.get(commentIndex);
- this.commentTokenManager = new TokenManager(commentToken.getInternalStructure(), this.tokenManager);
+ this.commentTokenManager = (commentToken.getInternalStructure() != null)
+ ? new TokenManager(commentToken.getInternalStructure(), this.tokenManager) : null;
this.declaration = node.getParent();
this.firstTagElement = true;
this.hasText = false;
@@ -108,7 +109,7 @@ public boolean visit(TextElement node) {
@Override
public boolean visit(TagElement node) {
- if (isSquashRequired(node, this.declaration)) {
+ if (this.commentTokenManager != null && isSquashRequired(node, this.declaration)) {
int startIndex = this.commentTokenManager.findIndex(node.getStartPosition(), -1, false);
Token token = this.commentTokenManager.get(startIndex);
token.clearLineBreaksBefore();
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/EclipseJdk8CodeFormatter.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/EclipseJdk8CodeFormatter.java
index 7b747cd2..fa365db4 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/EclipseJdk8CodeFormatter.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/EclipseJdk8CodeFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2021 the original author or authors.
+ * Copyright 2017-2025 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.
@@ -25,7 +25,7 @@
import io.spring.javaformat.formatter.eclipse.Options;
/**
- * Internal delegate JDK 11 baseline {@link EclipseCodeFormatter} to apply Spring
+ * Internal delegate JDK 8 baseline {@link EclipseCodeFormatter} to apply Spring
* {@literal formatter.prefs} and add {@link Preparator Preparators}.
*
* @author Phillip Webb
@@ -43,6 +43,7 @@ public EclipseJdk8CodeFormatter(JavaFormatConfig javaFormatConfig) {
this.appliedOptions = options;
addPreparator(new JavadocLineBreakPreparator());
addPreparator(new CodeLineBreakPreparator());
+ addPreparator(new JSpecifyPreparator());
}
@Override
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JSpecifyPreparator.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JSpecifyPreparator.java
new file mode 100644
index 00000000..4bc1aa0e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JSpecifyPreparator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2017-2025 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
+ *
+ * https://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 io.spring.javaformat.formatter.jdk8.eclipse;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.ASTNode;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.ASTVisitor;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.Annotation;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.CompilationUnit;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.IExtendedModifier;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.ImportDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.MethodDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.SingleVariableDeclaration;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.dom.VariableDeclarationStatement;
+import io.spring.javaformat.eclipse.jdt.jdk8.core.formatter.CodeFormatter;
+import io.spring.javaformat.eclipse.jdt.jdk8.internal.formatter.Preparator;
+import io.spring.javaformat.eclipse.jdt.jdk8.internal.formatter.TokenManager;
+
+public class JSpecifyPreparator implements Preparator {
+
+ private static final String PACKAGE_NAME = "org.jspecify.annotations";
+
+ private static final Set ANNOTATION_NAMES = new HashSet<>(
+ Arrays.asList("NonNull", "Nullable", "NullMarked", "NullUnmarked"));
+
+ private static final Set FULLY_QUALIFIED_ANNOTATION_NAMES = ANNOTATION_NAMES.stream()
+ .map((annotationName) -> PACKAGE_NAME + "." + annotationName)
+ .collect(Collectors.toSet());
+
+ @Override
+ public void apply(int kind, TokenManager tokenManager, ASTNode astRoot) {
+ if ((kind & CodeFormatter.K_COMPILATION_UNIT) != 0) {
+ ASTVisitor visitor = new Vistor(tokenManager);
+ astRoot.accept(visitor);
+ }
+ }
+
+ private static class Vistor extends ASTVisitor {
+
+ private final TokenManager tokenManager;
+
+ private final Map fullyQualified = new HashMap<>();
+
+ Vistor(TokenManager tokenManager) {
+ this.tokenManager = tokenManager;
+ }
+
+ @Override
+ public boolean visit(CompilationUnit node) {
+ this.fullyQualified.clear();
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(ImportDeclaration node) {
+ String name = node.getName().toString();
+ if (name.equals(PACKAGE_NAME) || name.startsWith(PACKAGE_NAME)) {
+ Set annotationNames = (node.isOnDemand()) ? ANNOTATION_NAMES
+ : Collections.singleton(name.substring(name.lastIndexOf(".") + 1));
+ for (String annotationName : annotationNames) {
+ this.fullyQualified.put(annotationName, PACKAGE_NAME + "." + annotationName);
+ }
+ }
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(MethodDeclaration node) {
+ clearLineBreaksIfHasJSpecifyAnnotation(node.modifiers());
+ return true;
+ }
+
+ @Override
+ public boolean visit(VariableDeclarationStatement node) {
+ clearLineBreaksIfHasJSpecifyAnnotation(node.modifiers());
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void endVisit(SingleVariableDeclaration node) {
+ if (node.isVarargs()) {
+ List annotations = node.varargsAnnotations();
+ Annotation lastAnnotation = getLastAnnotation(annotations);
+ if (isJSpecifyAnnotation(lastAnnotation)) {
+ this.tokenManager.lastTokenIn(lastAnnotation, -1).spaceAfter();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void clearLineBreaksIfHasJSpecifyAnnotation(List> modifiers) {
+ Annotation lastAnnotation = getLastAnnotation((List) modifiers);
+ if (isJSpecifyAnnotation(lastAnnotation)) {
+ this.tokenManager.lastTokenIn(lastAnnotation, -1).clearLineBreaksAfter();
+ }
+ }
+
+ private Annotation getLastAnnotation(List extends IExtendedModifier> modifiers) {
+ Annotation annotation = null;
+ for (IExtendedModifier modifier : modifiers) {
+ if (!modifier.isAnnotation()) {
+ return annotation;
+ }
+ annotation = (Annotation) modifier;
+ }
+ return annotation;
+ }
+
+ private boolean isJSpecifyAnnotation(Annotation annotation) {
+ String fullyQualifiedName = (annotation != null)
+ ? this.fullyQualified.get(annotation.getTypeName().toString()) : null;
+ return (fullyQualifiedName != null) && FULLY_QUALIFIED_ANNOTATION_NAMES.contains(fullyQualifiedName);
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JavadocLineBreakPreparator.java b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JavadocLineBreakPreparator.java
index 68723201..3a4a5f41 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JavadocLineBreakPreparator.java
+++ b/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/jdk8/eclipse/JavadocLineBreakPreparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-2024 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.
@@ -93,7 +93,8 @@ private static class Vistor extends ASTVisitor {
public boolean visit(Javadoc node) {
int commentIndex = this.tokenManager.firstIndexIn(node, TerminalTokens.TokenNameCOMMENT_JAVADOC);
Token commentToken = this.tokenManager.get(commentIndex);
- this.commentTokenManager = new TokenManager(commentToken.getInternalStructure(), this.tokenManager);
+ this.commentTokenManager = (commentToken.getInternalStructure() != null)
+ ? new TokenManager(commentToken.getInternalStructure(), this.tokenManager) : null;
this.declaration = node.getParent();
this.firstTagElement = true;
this.hasText = false;
@@ -108,7 +109,7 @@ public boolean visit(TextElement node) {
@Override
public boolean visit(TagElement node) {
- if (isSquashRequired(node, this.declaration)) {
+ if (this.commentTokenManager != null && isSquashRequired(node, this.declaration)) {
int startIndex = this.commentTokenManager.findIndex(node.getStartPosition(), -1, false);
Token token = this.commentTokenManager.get(startIndex);
token.clearLineBreaksBefore();
diff --git a/src/checkstyle/checkstyle.xml b/src/checkstyle/checkstyle.xml
index 0c6b5e96..c13faf85 100644
--- a/src/checkstyle/checkstyle.xml
+++ b/src/checkstyle/checkstyle.xml
@@ -65,6 +65,7 @@
+