diff --git a/.eclipse/org.eclipse.jdt.core.prefs b/.eclipse/org.eclipse.jdt.core.prefs
index fd349833..cc3e405e 100644
--- a/.eclipse/org.eclipse.jdt.core.prefs
+++ b/.eclipse/org.eclipse.jdt.core.prefs
@@ -25,7 +25,7 @@ org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
@@ -127,7 +127,7 @@ org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=84
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
@@ -136,6 +136,7 @@ org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration
org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
@@ -384,7 +385,7 @@ org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=90
+org.eclipse.jdt.core.formatter.lineSplit=120
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
diff --git a/.eclipse/org.eclipse.jdt.ui.prefs b/.eclipse/org.eclipse.jdt.ui.prefs
index ebacdff2..ccf98e6a 100644
--- a/.eclipse/org.eclipse.jdt.ui.prefs
+++ b/.eclipse/org.eclipse.jdt.ui.prefs
@@ -64,13 +64,13 @@ formatter_settings_version=13
org.eclipse.jdt.ui.exception.name=e
org.eclipse.jdt.ui.gettersetter.use.is=true
org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=java;javax;;org.springframework;\#;
+org.eclipse.jdt.ui.importorder=java;javax;;io.spring;\#;
org.eclipse.jdt.ui.javadoc=true
org.eclipse.jdt.ui.keywordthis=false
org.eclipse.jdt.ui.ondemandthreshold=9999
org.eclipse.jdt.ui.overrideannotation=true
org.eclipse.jdt.ui.staticondemandthreshold=9999
-org.eclipse.jdt.ui.text.custom_code_templates=/**\n * @return the ${bare_field_name}\n *//**\n * @param ${param} the ${bare_field_name} to set\n *//**\n * ${tags}\n *//*\n * Copyright 2017-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http\://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *//**\n * @author ${user}\n *//**\n * \n *//**\n * ${tags}\n *//* (non-Javadoc)\n * ${see_to_overridden}\n *//**\n * ${tags}\n * ${see_to_target}\n */${filecomment}\n\n${package_declaration}\n${typecomment}\n${type_declaration}\n\n\n\n// ${todo} Auto-generated catch block\nthrow new UnsupportedOperationException("Auto-generated method stub", ${exception_var});// ${todo} Auto-generated method stub\nthrow new UnsupportedOperationException("Auto-generated method stub");${body_statement}\n// ${todo} Auto-generated constructor stubreturn ${field};${field} \= ${param};
+org.eclipse.jdt.ui.text.custom_code_templates=/**\n * @return the ${bare_field_name}\n *//**\n * @param ${param} the ${bare_field_name} to set\n *//**\n * ${tags}\n *//*\n * Copyright 2017-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https\://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *//**\n * @author ${user}\n *//**\n * \n *//**\n * ${tags}\n *//* (non-Javadoc)\n * ${see_to_overridden}\n *//**\n * ${tags}\n * ${see_to_target}\n */${filecomment}\n\n${package_declaration}\n${typecomment}\n${type_declaration}\n\n\n\n// ${todo} Auto-generated catch block\nthrow new UnsupportedOperationException("Auto-generated method stub", ${exception_var});// ${todo} Auto-generated method stub\nthrow new UnsupportedOperationException("Auto-generated method stub");${body_statement}\n// ${todo} Auto-generated constructor stubreturn ${field};${field} \= ${param};
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
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 94%
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
index 0ce880e7..6ee635e0 100755
--- a/ci/scripts/publish-eclipse-update-site-pom-template.xml
+++ b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site-pom-template.xml
@@ -1,6 +1,6 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0org.eclipse.m2e.maveneclipsem2eclipse-maveneclipse-publish
@@ -25,7 +25,7 @@
-##respositories##
+##repositories##
${project.build.directory}/repositorytrue
diff --git a/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh
new file mode 100644
index 00000000..9ddcee29
--- /dev/null
+++ b/.github/actions/publish-eclipse-update-site/publish-eclipse-update-site.sh
@@ -0,0 +1,51 @@
+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/' )
+
+echo "Publishing ${buildName}/${buildNumber} (${groupId}:${version}) to Eclipse Update Site"
+
+jfrog rt dl --build spring-javaformat-${VERSION}/${BUILD_NUMBER} '**/io.spring.javaformat.eclipse.site*.zip'
+
+curl \
+ -s \
+ --connect-timeout 240 \
+ --max-time 2700 \
+ -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \
+ -f \
+ -H "X-Explode-Archive: true" \
+ -X PUT \
+ -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 )
+
+repositories=""
+while read -r releasedVersion; do
+ echo "Adding repository for ${releasedVersion}"
+ repositories="${repositories}https://repo.spring.io/javaformat-eclipse-update-site/${releasedVersion}p2"
+done <<< "${releasedVersions}"
+
+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 \
+ --connect-timeout 240 \
+ --max-time 2700 \
+ -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \
+ -f \
+ -X PUT \
+ -T "target/repository/content.jar" \
+ "https://repo.spring.io/javaformat-eclipse-update-site/" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
+
+curl \
+ -s \
+ --connect-timeout 240 \
+ --max-time 2700 \
+ -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \
+ -f \
+ -X PUT \
+ -T "target/repository/artifacts.jar" \
+ "https://repo.spring.io/javaformat-eclipse-update-site/" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
+
+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/images/setup-idea-dependency.png b/.github/images/setup-idea-dependency.png
new file mode 100644
index 00000000..06958617
Binary files /dev/null and b/.github/images/setup-idea-dependency.png differ
diff --git a/.github/images/setup-idea-library.png b/.github/images/setup-idea-library.png
new file mode 100644
index 00000000..d3563c7c
Binary files /dev/null and b/.github/images/setup-idea-library.png differ
diff --git a/.github/images/setup-idea-plugin-module.png b/.github/images/setup-idea-plugin-module.png
new file mode 100644
index 00000000..694a1370
Binary files /dev/null and b/.github/images/setup-idea-plugin-module.png differ
diff --git a/.github/images/setup-idea-plugin-sdk.png b/.github/images/setup-idea-plugin-sdk.png
new file mode 100644
index 00000000..3766bdb0
Binary files /dev/null and b/.github/images/setup-idea-plugin-sdk.png differ
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/.gitignore b/.gitignore
index e43e9edb..20cd4cfc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,8 @@ target
*.ipr
*.iws
spring-javaformat-eclipse/io.spring.javaformat.eclipse/lib
+spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/lib
+spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/lib
spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib
.gradle
spring-javaformat-gradle/spring-javaformat-gradle-plugin/bin
@@ -20,3 +22,12 @@ spring-javaformat/spring-javaformat-checkstyle/bin
spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/bin
build.log
pid
+.factorypath
+
+# npm
+node_modules/
+
+# vscode
+spring-javaformat-vscode/spring-javaformat/out/
+spring-javaformat-vscode/spring-javaformat/runtime/
+*.vsix
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/.mvn/jvm.config b/.mvn/jvm.config
index 9b109f37..629555a1 100644
--- a/.mvn/jvm.config
+++ b/.mvn/jvm.config
@@ -1 +1,2 @@
--Xmx1024m
\ No newline at end of file
+-Xmx1536m
+-Dtycho.disableP2Mirrors=true
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
old mode 100755
new mode 100644
index 9cc84ea9..bf82ff01
Binary files a/.mvn/wrapper/maven-wrapper.jar and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
old mode 100755
new mode 100644
index 71793467..6686a643
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1 +1,18 @@
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.0/apache-maven-3.9.0-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
diff --git a/.sdkmanrc b/.sdkmanrc
new file mode 100644
index 00000000..83ec5a0a
--- /dev/null
+++ b/.sdkmanrc
@@ -0,0 +1,3 @@
+# Enable auto-env through the sdkman_auto_env config
+# Add key=value pairs of SDKs to use below
+java=17.0.14-librca
diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc
index f013d6f3..17783c7c 100644
--- a/CODE_OF_CONDUCT.adoc
+++ b/CODE_OF_CONDUCT.adoc
@@ -40,5 +40,5 @@ appropriate to the circumstances. Maintainers are obligated to maintain confiden
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
-http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
-http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
+https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
+https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc
index e5619989..a7e07f62 100644
--- a/CONTRIBUTING.adoc
+++ b/CONTRIBUTING.adoc
@@ -3,27 +3,36 @@
Spring Java Format is released under the Apache 2.0 license.
If you would like to contribute something, or simply want to hack on the code this document should help you get started.
+
+
== Code of Conduct
This project adheres to the Contributor Covenant link:CODE_OF_CONDUCT.adoc[code of conduct].
By participating, you are expected to uphold this code.
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.
-== Working with the code
+
+== 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].
+
+
+
+== Working With the Code
If you don't have an IDE preference we would recommend that you use
https://spring.io/tools/sts[Spring Tools Suite] or
-http://eclipse.org[Eclipse] when working with the code. We use the
-http://eclipse.org/m2e/[M2Eclipse] eclipse plugin for maven support. Other IDEs and tools
+https://eclipse.org[Eclipse] when working with the code. We use the
+https://eclipse.org/m2e/[M2Eclipse] eclipse plugin for maven support. Other IDEs and tools
should also work without issue.
-=== Building from source
-To build the source you will need to install JDK 1.8.
-==== Default build
+
+=== Building From Source
+To build the source you will need to install JDK 17.
+
+
+
+==== Default Build
The project can be built from the root directory using the standard maven command:
[indent=0]
@@ -33,30 +42,172 @@ The project can be built from the root directory using the standard maven comman
NOTE: You may need to increase the amount of memory available to Maven by setting a `MAVEN_OPTS` environment variable with the value `-Xmx512m`
-=== Importing into eclipse
-You can import the code into any Eclipse based distribution as long as it had the http://eclipse.org/m2e/[M2Eclipse] eclipse plugin.
+
+
+=== Importing Into Eclipse
+You can import the code into any Eclipse based distribution as long as it had the https://eclipse.org/m2e/[M2Eclipse] eclipse plugin.
If you don't already have m2eclipse installed it is available from the "Eclipse marketplace".
+Once imported, you can apply eclipse settings by running:
+
+[indent=0]
+----
+ $ ./mvnw -Peclipse validate
+----
+
NOTE: You'll need to close the `spring-javaformat-formatter-eclipse` and `spring-javaformat-formatter-eclipse-runtime` projects following import since they contain rewritten packages that aren't supported by the IDE
-=== Importing into other IDEs
+
+
+=== Importing Into IntelliJ IDEA
+You can import the code as a maven project into IntelliJ IDEA.
+
+
+
+==== Module Dependencies
+When IntelliJ IDEA parses `pom.xml`, it automatically creates inter-module dependencies if dependent libraries are coming from other modules within the project.
+However, when dependent modules perform repackaging (e.g. `spring-javaformat-formatter-eclipse-runtime` module), the current module cannot resolve all classes by module dependencies because repackaging (shade & binary manipulation) moves around classes.
+Therefore, you need to manually update the dependencies from the module to the produced jars.
+
+Following modules perform repackaging.
+
+* `spring-javaformat-formatter-eclipse`
+* `spring-javaformat-formatter-eclipse-runtime`
+
+Modules that depend on these modules need jar dependencies instead of module dependencies.
+
+
+
+===== Setting up Jar Dependencies
+The following steps define jar-based project libraries on IDE and add them to the modules that need jar dependencies.
+
+*Add a jar file-based project library*
+
+* "Project Settings" -> "Libraries"
+* Click "+" sign, then select "Java"
+* Specify the jar file
+
+For example, you can specify the jar file in the target directory(`/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/target/spring-javaformat-formatter-eclipse-runtime-0.0.28-SNAPSHOT.jar`)
+or one in the local maven repository(`~/.m2/repository/io/spring/javaformat/spring-javaformat-formatter-eclipse-runtime/0.0.28-SNAPSHOT/spring-javaformat-formatter-eclipse-runtime-0.0.28-SNAPSHOT.jar`).
+
+image::.github/images/setup-idea-library.png[Setup IntelliJ IDEA library]
+
+*Add library dependencies to modules*
+
+* "Project Settings" -> "Modules"
+* Select a module that depends on repackaging modules
+* Click "+" sign and "2 Library"
+* "Choose Libraries" and select necessary libraries that have added in the previous step
+* Move up the added libraries higher than the module dependencies (or remove the module dependencies)
+
+image::.github/images/setup-idea-dependency.png[Setup IntelliJ IDEA Dependencies]
+
+
+
+=== Setting up IntelliJ IDEA Plugin Development
+
+
+
+==== Download Images
+To develop the `spring-javaformat-intellij-idea-plugin` module, you need an IntelliJ IDEA application on your local machine.
+
+* Open the `pom.xml` in `spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime`.
+* Check `intellij.binary` and `intellij.source` properties to find out the appropriate IntelliJ IDEA version.
+* Download the binary from the url in `intellij.binary`.
+(For OSX, replace the `.tar.gz` to `.dmg` to download the image file.)
+* Install the image to the local machine
+* Download the source files from github specified in `intellij.source` and unzip it.
+
+
+
+==== Setup SDK
+* Open "Project Structure" - "Platform Settings" - "SDKs"
+* Click "+" sign, "Add Intellij Platform Plugin SDK..."
+* Specify the installed intellij image. (`/applications/IntelliJ IDEA CE` for OSX)
+* On the right panel, "Sourcepath", Click "+" sign, specify unzipped intellij source directory
+* Specify "Sandbox Home" directory
+
+image::.github/images/setup-idea-plugin-sdk.png[Setup IntelliJ IDEA Plugin SDK]
+
+Please see the https://plugins.jetbrains.com/docs/intellij/setting-up-environment.html[IntelliJ IDEA reference] for how to setup a plugin development in details.
+
+
+
+==== Convert to Plugin Module
+The imported `spring-javaformat-intellij-idea-plugin` module is recognized as a java module.
+This needs to be converted to a plugin module.
+
+* Open `spring-javaformat-intellij-idea-plugin.iml` in `spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin`
+* Change `type="JAVA_MODULE"` to `type="PLUGIN_MODULE"`
+
+[source,xml]
+----
+
+----
+
+Reference https://stackoverflow.com/questions/18278440/how-to-import-and-run-existing-plugins-from-intellij-community-edition-repo[how to convert existing module to a plugin module]
+
+* Open "Project Structure" - "Modules"
+* Check `spring-javaformat-intellij-idea-plugin` icon turns to a plugin icon
+* "Plugin Deployment" - "Path to META-INF/plugin.xml"
+* Specify `spring-javaformat/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources`
+
+image::.github/images/setup-idea-plugin-module.png[Setup IntelliJ IDEA Plugin Module]
+
+
+
+=== Setting up Gradle Plugin Development
+`spring-javaformat-gradle-plugin` module is a gradle plugin and requires gradle related classes.
+
+To add gradle classes, convert this module to a gradle project.
+
+* On the project pain, right-click `build.gradle` in `spring-javaformat-gradle-plugin` module
+* Select "Import Gradle Project"
+
+
+
+=== Setting up Visual Studio Code Extension Development
+The `spring-javaformat-vscode-extension` extension consists of a formatter written in Java and an extension written in TypeScript.
+If you want to work on the TypeScript code it can opened directly with Visual Studio Code.
+
+Maven delegates to `npm run package` to actually generate the extension.
+
+Code is formatted with prettier.
+If you need to reform the code you can run `npx prettier --write .`
+
+There is a basic test included with the project, but since it needs UI elements it doesn't run as part of the regular build.
+If you make changes to the extension, you should run "`Extension Tests`" from vscode.
+
+
+
+=== Importing Into Other IDEs
Maven is well supported by most Java IDEs. Refer to your vendor documentation.
-== Understanding the code
+
+
+== Understanding the Code
There are quite a few moving parts to this project and the build is quite complex.
-At the top level there are 5 projects:
+At the top level there are 6 projects:
* `spring-javaformat` - The main formatter project
* `spring-javaformat-eclipse` - The Eclipse plugin
* `spring-javaformat-gradle` - The Gradle plugin
* `spring-javaformat-intellij` - The IntelliJ IDEA plugin
* `spring-javaformat-maven` - The Maven plugin
+* `spring-javaformat-vscode` - The Visual Studo Code extension
Under `spring-javaformat` the following projects are defined:
* `spring-javaformat-checkstyle` - The checkstyle plugin
* `spring-javaformat-formatter` - The main formatter code
-* `spring-javaformat-formatter-eclipse` - The eclipse formatter (repackaged and slightly adapted)
+* `spring-javaformat-formatter-test-support` - Support classes for tests
+* `spring-javaformat-formatter-tests` - Tests for the formatter (external so that they we can test Java 8 and 11)
+* `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-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-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 6ba3ae8c..907d9a2c 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,22 +1,27 @@
-:release-version: 0.0.6
-:checkstyle-version: 8.11
-## Spring Java Format
+:release-version: 0.0.47
+:checkstyle-version: 9.3
+== Spring Java Format
-### What is this?
+
+
+=== What is This?
A set of plugins that can be applied to any Java project to provide a consistent "`Spring`" style.
The set currently consists of:
* A source formatter that applies wrapping and whitespace conventions
-* A checkstyle plugin that enforces consistency across a codebase
+* A Checkstyle plugin that enforces consistency across a codebase
Since the aim of this project is to provide consistency, each plugin is not generally configurable.
You need to change your code to match the required conventions.
You can't configure the plugin conventions to match your style!
-### Maven
-#### Source Formatting
+=== Maven
+
+
+
+==== Source Formatting
For source formatting, add the `spring-javaformat-maven-plugin` to your `build` plugins as follows:
[source,xml,indent=0,subs="normal"]
@@ -67,9 +72,17 @@ If you want to enforce that all code matches the required style, add the followi
----
-#### Checkstyle
+NOTE: The source formatter does not fundamentally change your code.
+For example, it will not change the order of import statements.
+It is effectively limited to adding or removing whitespace and line feeds.
+
+TIP: You can use `-Dspring-javaformat.validate.skip=true` or `-Dspring-javaformat.apply.skip=true` command line arguments to temporarily skip the validation or format goals.
+If you want to skip both, you can use `-Dspring-javaformat.skip=true`.
+
+
-To enforce checksyle conventions add the checkstyle plugin and include a dependency on `spring-javaformat-checkstyle`:
+==== Checkstyle
+To enforce Checkstyle conventions, add the Checkstyle plugin and include a dependency on `spring-javaformat-checkstyle`:
[source,xml,indent=0,subs="normal"]
----
@@ -78,7 +91,7 @@ To enforce checksyle conventions add the checkstyle plugin and include a depende
org.apache.maven.pluginsmaven-checkstyle-plugin
- 3.0.0
+ 3.1.1com.puppycrawl.tools
@@ -110,63 +123,114 @@ To enforce checksyle conventions add the checkstyle plugin and include a depende
----
-### Gradle
-#### Source Formatting
-For source formatting, add the `spring-javaformat-gradle-plugin` to your `build` plugins as follows:
+
+=== Gradle
+A plugin is provided.
+To use it, first update `settings.gradle` to add Maven Central as a plugin repository:
[source,groovy,indent=0,subs="normal"]
----
- buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:{release-version}")
- }
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenCentral()
}
+}
+----
+
+The plugin can then be added in the usual way in `build.gradle`:
- apply plugin: 'io.spring.javaformat'
+[source,groovy,indent=0,subs="normal"]
+----
+plugins {
+ id "io.spring.javaformat" version "{release-version}"
+}
----
+==== Source Formatting
The plugin adds `format` and `checkFormat` tasks to your project.
-The `checkFormat` task is automatically applied when running the standard Gradle `check` task.
+The `checkFormat` task is automatically executed when running the standard Gradle `check` task.
-#### Checkstyle
-To enforce checksyle conventions add the checkstyle plugin and include a dependency on `spring-javaformat-checkstyle`:
+In case you want to exclude a package from being checked, for example if you generate sources, add configuration similar to the following:
[source,groovy,indent=0,subs="normal"]
----
-apply plugin: 'checkstyle'
+tasks.withType(io.spring.javaformat.gradle.tasks.CheckFormat) {
+ exclude "package/to/exclude"
+}
+----
+
+
+
+==== Checkstyle
+To enforce Checkstyle conventions, apply the Checkstyle plugin in addition to the `io.spring.javaformat` plugin:
+
+[source,groovy,indent=0,subs="normal"]
+----
+plugins {
+ id "io.spring.javaformat" version "{release-version}"
+ id "checkstyle"
+}
+----
+
+The Spring Java Format plugin will react to the Checkstyle plugin being applied and configure the necessary dependencies in the `checkstyle` configuration.
+You should also configure Checkstyle's tool version:
+
+[source,groovy,indent=0,subs="normal"]
+----
checkstyle {
toolVersion = "{checkstyle-version}"
}
+----
+
+To configure Checkstyle to use the default Spring checks, add the following configuration:
-dependencies {
- checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:{release-version}")
+[source,groovy,indent=0,subs="normal"]
+----
+springJavaFormat {
+ checkstyle {
+ applyDefaultConfig()
+ }
}
----
-Your `checkstyle.xml` file should look then like this:
+Alternatively, provide your own `checkstyle.xml` that configures the `io.spring.javaformat.checkstyle.SpringChecks` module.
-[source,xml,indent=0]
+If you want to use both Spring Java Format and Checkstyle but you do not want to use Spring Java Format's checks, disable the aforementioned dependency configuration:
+
+[source,groovy,indent=0,subs="normal"]
----
-
-
-
-
-
+springJavaFormat {
+ checkstyle {
+ configureDependencies = false
+ }
+}
----
-### Eclipse
+
+=== Java 8 Support
+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:
+
+[source,properties]
+----
+java-baseline=8
+----
+
+
+
+=== Eclipse
The Eclipse plugin provides a custom formatter implementation and automatically applies project specific settings.
The plugin is automatically activated whenever the Maven or Gradle plugins are discovered in a project build script.
-If you need to customize the project specific settings that the plugin applies you should add a `.eclipse` folder in the root of your project.
+If you need to customize the project specific settings that the plugin applies, you should add a `.eclipse` folder in the root of your project.
All `.prefs` files from this folder will be copied to the project `.settings` folders.
-Usually you'll provide your own `org.eclipse.jdt.core.prefs` and `org.eclipse.jdt.ui.prefs` files.
+Usually, you'll provide your own `org.eclipse.jdt.core.prefs` and `org.eclipse.jdt.ui.prefs` files.
You can also add a `.eclipse/eclipse.properties` file to customize the following items:
@@ -176,62 +240,178 @@ You can also add a `.eclipse/eclipse.properties` file to customize the following
----
To install the plugin use the `io.spring.javaformat.eclipse.site` zip file.
-You can download the latest version from http://repo.spring.io/release/io/spring/javaformat/io.spring.javaformat.eclipse.site/{release-version}[repo.spring.io] or use the https://dl.bintray.com/spring/javaformat-eclipse/[update site].
+You can download the latest version from
+https://repo1.maven.org/maven2/io/spring/javaformat/io.spring.javaformat.eclipse.site/{release-version}[Maven Central]
+or use the `https://repo.spring.io/javaformat-eclipse-update-site/` as an Eclipse update site (do not use the `/ui/native/` links that you are redirected to when using a web browser).
-### IntelliJ IDEA
-The IntelliJ plugin provides custom formatter support for IDEA.
-The plugin is automatically activated whenever the Maven or Gradle plugins are discovered in a project build script.
-A Spring Java Format icon (image:spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/spring-javaformat/formatOn.png[title="Icon"]) will also be displayed in the status bar to indicate the formatter is active.
+
+
+=== IntelliJ IDEA
+The IntelliJ IDEA plugin provides custom formatter support for IntelliJ IDEA.
+The plugin is automatically activated whenever the Maven or Gradle plugins are discovered in a project build script or if a `.springjavaformatconfig` file.
+A Spring Java Format icon (image:spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/spring-javaformat/formatOn.png[title="Icon"]) will also be displayed in the status bar to indicate the formatter is active.
You can use the standard `code` -> `reformat code` action to format the code.
-To install the plugin use the `spring-javaformat-intellij-plugin` jar file.
-You can download the latest version from http://repo.spring.io/release/io/spring/javaformat/spring-javaformat-intellij-plugin/{release-version}[repo.spring.io].
+To install the plugin, use the `spring-javaformat-intellij-idea-plugin` jar file.
+You can download the latest version from https://repo1.maven.org/maven2/io/spring/javaformat/spring-javaformat-intellij-idea-plugin/{release-version}[Maven Central].
+
+
+
+==== Enable the Plugin
+The plugin is automatically enabled when one or more of the following conditions match:
+
+* `.springjavaformatconfig` file exists
+* For a Maven-based project, `spring-javaformat-maven-plugin` plugin is defined in `pom.xml`
+* For a Gradle-based project, `io.spring.javaformat` plugin is applied
-### About the conventions
-Most of the coding conventions and style comes from the Spring Framework and Spring Boot projects.
-Spring Framework manually formats code, where as Spring Boot uses automatic formatting.
-### Tips
+
+==== CheckStyle-IDEA plugin
+The https://plugins.jetbrains.com/plugin/1065-checkstyle-idea[CheckStyle-IDEA plugin] provides Checkstyle integration for IntelliJ IDEA.
+
+To configure the plugin, create your own Checkstyle configuration file with the following content:
+
+[source,xml,indent=0]
+----
+
+
+
+
+
+----
+
+Once the configuration file is created, configure your IDE to use it:
+
+* Download `spring-javaformat-checkstyle-{release-version}.jar` from https://repo1.maven.org/maven2/io/spring/javaformat/spring-javaformat-checkstyle/{release-version}[Maven Central].
+* Download `spring-javaformat-config-{release-version}.jar` from https://repo1.maven.org/maven2/io/spring/javaformat/spring-javaformat-config/{release-version}[Maven Central].
+* Open `Preferences` - `Tools` - `Checkstyle`
+* Add `spring-javaformat-checkstyle-{release-version}.jar` and `spring-javaformat-config-{release-version}.jar` to the `Third-Party Checks`
+* Specify the appropriate `Checkstyle version`
+* Add and enable your Checkstyle configuration file
+
+
+
+=== Visual Studio Code
+The Visual Studio Code extension provides custom formatter support for Microsoft Visual Studio Code.
+The extension uses the https://code.visualstudio.com/api/references/vscode-api#DocumentFormattingEditProvider[`DocumentFormattingEditProvider`] API.
+Once installed it may be activated by using the "`Format Document`" action available in the editor context menu or from the Command Palette.
+
+To install the extension, select "`Install from VSIX`" in the extensions panel and choose the `spring-javaformat-vscode-extension` vsix file.
+You can download the latest version from https://repo1.maven.org/maven2/io/spring/javaformat/spring-javaformat-vscode-extension/{release-version}[Maven Central].
+
+
+
+=== About the Conventions
+Most of the coding conventions and style come from the Spring Framework and Spring Boot projects.
+Spring Framework manually formats code, whereas Spring Boot uses automatic formatting.
+
+
+
+=== Indenting With Spaces
+By default, tabs are used for indenting formatted code.
+We strongly recommend that this default is not changed, especially for official Spring projects.
+If, however, you feel that you can't live with tabs, switching to spaces is the one configuration option that we do support.
+
+To use spaces rather than tabs, add a file called `.springjavaformatconfig` to the root of your project with the following content:
+
+[source,properties]
+----
+indentation-style=spaces
+----
+
+
+
+=== Tips
Formatting and Checkstyle alone are not enough to produce truly consistent code.
Here are some tips that we've found useful when developing Spring Boot.
-#### Wrapping
-The source formatter intentionally uses a low character count of 90 chars for wrapping.
-If you're used to longer lines, this can take some getting used to.
-Specifically, if you have many nesting levels things can start to look quite bad.
-Generally, if you see code bunched up to the right of your screen you should take that as a signal to use the "`extract method`" refactor.
-Extracting small private methods will improve formatting and it helps when reading the code and debugging.
-#### Whitespace
-Keeping whitespace lines out method bodies can help make the code easier to scan.
-If blank lines are only included between methods it becomes easier to see the overall structure of the class.
-If you find you need whitespace inside your method, consider if extracting a private method might give a better result.
+==== Excluding Specific Checks
+If you want most `SpringChecks` but need to exclude one or two, you can do something like this in your `checkstyle.xml`:
-#### Comments
+[source,xml,indent=0]
+----
+
+
+
+
+
+
+
+----
+
+
+
+==== Disabling Formatting For Blocks of Code
+Some code isn't particularly amenable to automatic formatting.
+For example, Spring Security configurations often work better when manually formatted.
+
+If you need to disable formatting for a specific block of code, you can enclose it in a `@formatter:off` / `@formatter:on` set:
+
+[source,java]
+----
+// @formatter:off
+
+... code not be formatted
+
+// @formatter:on
+----
+
+
+
+==== Wrapping
+The source formatter uses 120 chars for wrapping. This aims to strike a balance between
+making use of available horizontal space in your IDE and avoiding unwanted additional
+wrapping when viewing code on GitHub and the like.
+
+If you're used to longer lines, 120 chars can take some getting used to. Specifically, if
+you have many nesting levels, things can start to look quite bad. Generally, if you see
+code bunched up to the right of your screen, you should take that as a signal to use the
+"`extract method`" refactor. Extracting small private methods will improve formatting and
+it helps when reading the code and debugging.
+
+
+
+==== Whitespace
+Keeping whitespace lines out of method bodies can help make the code easier to scan.
+If blank lines are only included between methods, it becomes easier to see the overall structure of the class.
+If you find you need whitespace inside your method, consider whether extracting a private method might give a better result.
+
+
+
+==== Comments
Try to add javadoc for each public method and constant.
Private methods shouldn't generally need javadoc, unless it provides a natural place to document unusual behavior.
-The checkstyle rules will enforce that all public classes have javadoc.
+The Checkstyle rules will enforce that all public classes have javadoc.
They will also ensure that `@author` tags are well formed.
-#### Final
+
+
+==== Final
Private members should be `final` whenever possible.
-Local variable and parameters should generally not be explicitly declared as final since it adds so much noise.
+Local variables and parameters should generally not be explicitly declared as final since it adds so much noise.
+
+
-#### Read-down methods, fields and parameters
+==== Read-down Methods, Fields and Parameters
Methods don't need to be organized by scope.
There's no need to group all `private`, `protected` and `public` methods together.
-Instead try to make your code easy to read when scanning the file from top to bottom.
-In other words, try to have methods only reference method further down in the file.
+Instead, try to make your code easy to read when scanning the file from top to bottom.
+In other words, try to have methods only reference methods further down in the file.
Keep private methods as close to the thing that calls them as possible.
-It's also recommend that you try to keep consistent ordering with fields and constructor parameters.
+It's also recommended that you try to keep consistent ordering with fields and constructor parameters.
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 e78d45bf..00000000
--- a/ci/README.adoc
+++ /dev/null
@@ -1,37 +0,0 @@
-== Concourse pipeline
-
-The pipeline can be deployed using the following command:
-
-[source]
-----
-$ fly -t spring 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.
-
-=== Release
-
-To release a milestone:
-
-[source]
-----
-$ fly -t spring trigger-job -j spring-javaformat/stage-milestone
-$ fly -t spring trigger-job -j spring-javaformat/promote-milestone
-----
-
-To release an RC:
-
-[source]
-----
-$ fly -t spring trigger-job -j spring-javaformat/stage-rc
-$ fly -t spring trigger-job -j spring-javaformat/promote-rc
-----
-
-To release a GA:
-
-[source]
-----
-$ fly -t spring trigger-job -j spring-javaformat/stage-release
-$ fly -t spring trigger-job -j spring-javaformat/promote-release
-----
diff --git a/ci/images/spring-javaformat-ci-image/Dockerfile b/ci/images/spring-javaformat-ci-image/Dockerfile
deleted file mode 100644
index 45512c3f..00000000
--- a/ci/images/spring-javaformat-ci-image/Dockerfile
+++ /dev/null
@@ -1,33 +0,0 @@
-FROM openjdk:8u141-jdk
-
-RUN apt-get update && \
- apt-get install -y git && \
- apt-get install -y libxml2-utils && \
- apt-get install -y jq
-
-ADD https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.2/concourse-java.sh /opt/
-
-ENV DOCKER_VERSION=17.05.0-ce \
- ENTRYKIT_VERSION=0.4.0
-
-RUN apt-get update && \
- apt-get install -y curl && \
- apt-get install -y libudev1 && \
- apt-get install -y iptables && \
- curl https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz | tar zx && \
- mv /docker/* /bin/ && chmod +x /bin/docker*
-
-# Install entrykit
-RUN 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
-
-ADD https://raw.githubusercontent.com/spring-projects/spring-boot/master/ci/images/docker-lib.sh /docker-lib.sh
-
-ENTRYPOINT [ \
- "switch", \
- "shell=/bin/sh", "--", \
- "codep", \
- "/bin/docker daemon" \
-]
\ No newline at end of file
diff --git a/ci/parameters.yml b/ci/parameters.yml
deleted file mode 100644
index 1c908148..00000000
--- a/ci/parameters.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-github-repo: "https://github.com/spring-io/spring-javaformat.git"
-github-repo-name: "spring-io/spring-javaformat"
-docker-hub-organization: "springci"
-artifactory-server: "https://repo.spring.io"
-branch: "master"
-build-name: "spring-javaformat"
-bintray-subject: "spring"
-bintray-repo: "jars"
diff --git a/ci/pipeline.yml b/ci/pipeline.yml
deleted file mode 100644
index 3da5043a..00000000
--- a/ci/pipeline.yml
+++ /dev/null
@@ -1,193 +0,0 @@
-resource_types:
-- name: artifactory-resource
- type: docker-image
- source:
- repository: springio/artifactory-resource
- tag: 0.0.3
-- name: pull-request
- type: docker-image
- source:
- repository: jtarchie/pr
-resources:
-- name: git-repo
- type: git
- source:
- uri: ((github-repo))
- username: ((github-username))
- password: ((github-password))
- branch: ((branch))
- ignore_paths: ["ci/images/*"]
-- name: git-pull-request
- type: pull-request
- source:
- access_token: ((github-access-token))
- repo: ((github-repo-name))
- base: ((branch))
- ignore_paths: ["ci/*"]
-- name: ci-images-git-repo
- type: git
- source:
- uri: ((github-repo))
- branch: ((branch))
- paths: ["ci/images/*"]
-- name: spring-javaformat-ci-image
- type: docker-image
- source:
- repository: ((docker-hub-organization))/spring-javaformat-ci-image
- username: ((docker-hub-username))
- password: ((docker-hub-password))
- tag: ((branch))
-- name: artifactory-repo
- type: artifactory-resource
- source:
- uri: ((artifactory-server))
- username: ((artifactory-username))
- password: ((artifactory-password))
- build_name: ((build-name))
-jobs:
-- name: build-spring-javaformat-ci-images
- plan:
- - get: ci-images-git-repo
- trigger: true
- - put: spring-javaformat-ci-image
- params:
- build: ci-images-git-repo/ci/images/spring-javaformat-ci-image
-- name: build
- serial: true
- public: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- trigger: true
- - do:
- - task: build-project
- privileged: true
- timeout: 1h30m
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/build-project.yml
- - put: artifactory-repo
- params: &artifactory-params
- repo: libs-snapshot-local
- build_number: "${BUILD_ID}"
- 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
-- name: build-pull-requests
- serial: true
- public: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- resource: git-pull-request
- trigger: true
- version: every
- - do:
- - put: git-pull-request
- params:
- path: git-repo
- status: pending
- - task: build-project
- timeout: 1h30m
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/build-pr-project.yml
- on_success:
- put: git-pull-request
- params:
- path: git-repo
- status: success
- on_failure:
- put: git-pull-request
- params:
- path: git-repo
- status: failure
-- name: stage-release
- serial: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- trigger: false
- - task: stage
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/stage.yml
- params:
- RELEASE_TYPE: RELEASE
- - put: artifactory-repo
- params:
- <<: *artifactory-params
- repo: libs-staging-local
- - put: git-repo
- params:
- repository: stage-git-repo
-- name: promote-release
- serial: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [stage-release]
- params:
- save_build_info: true
- - task: promote
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/promote.yml
- params:
- RELEASE_TYPE: RELEASE
- ARTIFACTORY_SERVER: ((artifactory-server))
- ARTIFACTORY_USERNAME: ((artifactory-username))
- ARTIFACTORY_PASSWORD: ((artifactory-password))
- BINTRAY_SUBJECT: ((bintray-subject))
- BINTRAY_REPO: ((bintray-repo))
-- name: sync-to-maven-central
- serial: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [promote-release]
- params:
- save_build_info: true
- - task: sync-to-maven-central
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/sync-to-maven-central.yml
- params:
- BINTRAY_USERNAME: ((bintray-username))
- BINTRAY_PASSWORD: ((bintray-password))
- SONATYPE_USERNAME: ((sonatype-username))
- SONATYPE_PASSWORD: ((sonatype-password))
- BINTRAY_SUBJECT: ((bintray-subject))
- BINTRAY_REPO: ((bintray-repo))
-- name: publish-eclipse-update-site
- serial: true
- plan:
- - get: spring-javaformat-ci-image
- - get: git-repo
- trigger: false
- - get: artifactory-repo
- trigger: false
- passed: [sync-to-maven-central]
- params:
- save_build_info: true
- - task: publish-eclipse-update-site
- image: spring-javaformat-ci-image
- file: git-repo/ci/tasks/publish-eclipse-update-site.yml
- params:
- BINTRAY_USERNAME: ((bintray-username))
- BINTRAY_PASSWORD: ((bintray-password))
- SONATYPE_USERNAME: ((sonatype-username))
- SONATYPE_PASSWORD: ((sonatype-password))
- BINTRAY_SUBJECT: ((bintray-subject))
- BINTRAY_REPO: ((bintray-repo))
-groups:
-- name: "Build"
- jobs: ["build"]
-- name: "Release"
- jobs: ["stage-release", "promote-release", "sync-to-maven-central", "publish-eclipse-update-site"]
-- name: "CI Images"
- jobs: ["build-spring-javaformat-ci-images"]
-- name: "Build Pull Requests"
- jobs: ["build-pull-requests"]
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 0198d39a..00000000
--- a/ci/scripts/common.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-source /opt/concourse-java.sh
-
-setup_symlinks
-cleanup_maven_repo "io.spring.javaformat"
diff --git a/ci/scripts/promote.sh b/ci/scripts/promote.sh
deleted file mode 100755
index 2d9fdec1..00000000
--- a/ci/scripts/promote.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/common.sh
-
-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/' )
-
-
-if [[ $RELEASE_TYPE = "M" ]]; then
- targetRepo="libs-milestone-local"
-elif [[ $RELEASE_TYPE = "RC" ]]; then
- targetRepo="libs-milestone-local"
-elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
- targetRepo="libs-release-local"
-else
- echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
-fi
-
-echo "Promoting ${buildName}/${buildNumber} to ${targetRepo}"
-
-curl \
- -s \
- --connect-timeout 240 \
- --max-time 900 \
- -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \
- -H "Content-type:application/json" \
- -d "{\"status\": \"staged\", \"sourceRepo\": \"libs-staging-local\", \"targetRepo\": \"${targetRepo}\"}" \
- -f \
- -X \
- POST "${ARTIFACTORY_SERVER}/api/build/promote/${buildName}/${buildNumber}" > /dev/null || { echo "Failed to promote" >&2; exit 1; }
-
-if [[ $RELEASE_TYPE = "RELEASE" ]]; then
- curl \
- -s \
- --connect-timeout 240 \
- --max-time 2700 \
- -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \
- -H "Content-type:application/json" \
- -d "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}" \
- -f \
- -X \
- POST "${ARTIFACTORY_SERVER}/api/build/distribute/${buildName}/${buildNumber}" > /dev/null || { echo "Failed to distribute" >&2; exit 1; }
-
- echo "Waiting for artifacts to be published"
- ARTIFACTS_PUBLISHED=false
- WAIT_TIME=5
- COUNTER=0
- while [ $ARTIFACTS_PUBLISHED == "false" ] && [ $COUNTER -lt 60 ]; do
- result=$( curl -s https://api.bintray.com/packages/"${BINTRAY_SUBJECT}"/"${BINTRAY_REPO}"/"${groupId}" )
- versions=$( echo "$result" | jq -r '.versions' )
- exists=$( echo "$versions" | grep "$version" -o || true )
- if [ "$exists" = "$version" ]; then
- ARTIFACTS_PUBLISHED=true
- fi
- COUNTER=$(( COUNTER + 1 ))
- sleep $WAIT_TIME
- done
- if [[ $ARTIFACTS_PUBLISHED = "false" ]]; then
- echo "Failed to publish"
- exit 1
- fi
-fi
-
-
-echo "Promotion complete"
diff --git a/ci/scripts/publish-eclipse-update-site.sh b/ci/scripts/publish-eclipse-update-site.sh
deleted file mode 100755
index 923b3bf5..00000000
--- a/ci/scripts/publish-eclipse-update-site.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-set -e
-
-source $(dirname $0)/common.sh
-
-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/' )
-
-echo "Publishing ${buildName}/${buildNumber} to Eclipse Update Site"
-curl \
- -s \
- --connect-timeout 240 \
- --max-time 2700 \
- -u ${BINTRAY_USERNAME}:${BINTRAY_PASSWORD} \
- -f \
- -X PUT \
- -T "artifactory-repo/io/spring/javaformat/io.spring.javaformat.eclipse.site/${version}/io.spring.javaformat.eclipse.site-${version}.zip" \
- "https://api.bintray.com/content/spring/javaformat-eclipse/update-site/${version}/${version}/site.zip?explode=1&publish=1" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
-
-releasedVersions=$( curl -f -X GET https://api.bintray.com/packages/spring/javaformat-eclipse/update-site | jq -r '.versions[]' )
-respositories=""
-while read -r releasedVersion; do
- respositories="${respositories}https://dl.bintray.com/spring/javaformat-eclipse/${releasedVersion}p2"
-done <<< "${releasedVersions}"
-
-pushd git-repo > /dev/null
-sed "s|##respositories##|${respositories}|" 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; }
-
-curl \
- -s \
- --connect-timeout 240 \
- --max-time 2700 \
- -u ${BINTRAY_USERNAME}:${BINTRAY_PASSWORD} \
- -f \
- -X PUT \
- -T "target/repository/content.jar" \
- "https://api.bintray.com/content/spring/javaformat-eclipse/content.jar" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
-
-curl \
- -s \
- --connect-timeout 240 \
- --max-time 2700 \
- -u ${BINTRAY_USERNAME}:${BINTRAY_PASSWORD} \
- -f \
- -X PUT \
- -T "target/repository/artifacts.jar" \
- "https://api.bintray.com/content/spring/javaformat-eclipse/artifacts.jar" > /dev/null || { echo "Failed to publish" >&2; exit 1; }
-
-popd > /dev/null
-
-echo "Publish complete"
diff --git a/ci/scripts/stage.sh b/ci/scripts/stage.sh
deleted file mode 100755
index 4b36ed7d..00000000
--- a/ci/scripts/stage.sh
+++ /dev/null
@@ -1,45 +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 = "RELEASE" ]]; then
- stageVersion=$( strip_snapshot_suffix $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
-
-git config user.name "Spring Buildmaster" > /dev/null
-git config user.email "buildmaster@springframework.org" > /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
-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
-sed -i "s/:release-version:.*/:release-version: ${stageVersion}/g" README.adoc
-git add . > /dev/null
-git commit -m"Next development version (v$nextVersion)" > /dev/null
-
-echo "DONE"
-
-popd > /dev/null
diff --git a/ci/scripts/sync-to-maven-central.sh b/ci/scripts/sync-to-maven-central.sh
deleted file mode 100755
index d644c3bf..00000000
--- a/ci/scripts/sync-to-maven-central.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-set -e
-
-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/' )
-
-echo "Syncing ${buildName}/${buildNumber} to Maven Central"
- curl \
- -s \
- --connect-timeout 240 \
- --max-time 2700 \
- -u ${BINTRAY_USERNAME}:${BINTRAY_PASSWORD} \
- -H "Content-Type: application/json" -d "{\"username\": \"${SONATYPE_USERNAME}\", \"password\": \"${SONATYPE_PASSWORD}\"}" \
- -f \
- -X \
- POST "https://api.bintray.com/maven_central_sync/${BINTRAY_SUBJECT}/${BINTRAY_REPO}/${groupId}/versions/${version}" > /dev/null || { echo "Failed to sync" >&2; exit 1; }
-echo "Sync complete"
\ No newline at end of file
diff --git a/ci/tasks/build-pr-project.yml b/ci/tasks/build-pr-project.yml
deleted file mode 100644
index 9430bc00..00000000
--- a/ci/tasks/build-pr-project.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-outputs:
-- name: distribution-repository
-caches:
-- path: maven
-- path: gradle
-run:
- path: git-repo/ci/scripts/build-project.sh
\ No newline at end of file
diff --git a/ci/tasks/build-project.yml b/ci/tasks/build-project.yml
deleted file mode 100644
index 649e2e4b..00000000
--- a/ci/tasks/build-project.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-outputs:
-- name: distribution-repository
-caches:
-- path: maven
-- path: gradle
-run:
- path: bash
- args:
- - -ec
- - |
- source /docker-lib.sh
- start_docker
- ${PWD}/git-repo/ci/scripts/build-project.sh
-
diff --git a/ci/tasks/promote.yml b/ci/tasks/promote.yml
deleted file mode 100644
index 92b92c34..00000000
--- a/ci/tasks/promote.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-- name: artifactory-repo
-run:
- path: git-repo/ci/scripts/promote.sh
diff --git a/ci/tasks/publish-eclipse-update-site.yml b/ci/tasks/publish-eclipse-update-site.yml
deleted file mode 100644
index 78b15b72..00000000
--- a/ci/tasks/publish-eclipse-update-site.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-- name: artifactory-repo
-run:
- path: git-repo/ci/scripts/publish-eclipse-update-site.sh
diff --git a/ci/tasks/stage.yml b/ci/tasks/stage.yml
deleted file mode 100644
index 1cbcc1fa..00000000
--- a/ci/tasks/stage.yml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-outputs:
-- name: stage-git-repo
-- name: distribution-repository
-caches:
-- path: maven
-- path: gradle
-run:
- path: git-repo/ci/scripts/stage.sh
diff --git a/ci/tasks/sync-to-maven-central.yml b/ci/tasks/sync-to-maven-central.yml
deleted file mode 100644
index e267c673..00000000
--- a/ci/tasks/sync-to-maven-central.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-platform: linux
-inputs:
-- name: git-repo
-- name: artifactory-repo
-run:
- path: git-repo/ci/scripts/sync-to-maven-central.sh
diff --git a/license.txt b/license.txt
index 427417b6..ff773796 100644
--- a/license.txt
+++ b/license.txt
@@ -1,7 +1,7 @@
Apache License
Version 2.0, January 2004
- http://www.apache.org/licenses/
+ https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
@@ -193,7 +193,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ 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,
diff --git a/mvnw b/mvnw
index 5bf251c0..b7f06462 100755
--- a/mvnw
+++ b/mvnw
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
-# Maven2 Start Up Batch script
+# Apache Maven Wrapper startup batch script, version 3.1.1
#
# Required ENV vars:
# ------------------
@@ -27,7 +27,6 @@
#
# Optional ENV vars
# -----------------
-# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -36,6 +35,10 @@
if [ -z "$MAVEN_SKIP_RC" ] ; then
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
@@ -58,9 +61,9 @@ case "`uname`" in
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
- export JAVA_HOME="`/usr/libexec/java_home`"
+ JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME
else
- export JAVA_HOME="/Library/Java/Home"
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
@@ -72,49 +75,18 @@ if [ -z "$JAVA_HOME" ] ; then
fi
fi
-if [ -z "$M2_HOME" ] ; then
- ## resolve links - $0 may be a link to maven's home
- PRG="$0"
-
- # need this for relative symlinks
- while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG="`dirname "$PRG"`/$link"
- fi
- done
-
- saveddir=`pwd`
-
- M2_HOME=`dirname "$PRG"`/..
-
- # make it fully qualified
- M2_HOME=`cd "$M2_HOME" && pwd`
-
- cd "$saveddir"
- # echo Using m2 at $M2_HOME
-fi
-
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
- [ -n "$M2_HOME" ] &&
- M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
-# For Migwn, ensure paths are in UNIX format before anything is touched
+# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
- [ -n "$M2_HOME" ] &&
- M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
- # TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
@@ -146,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then
JAVACMD="$JAVA_HOME/bin/java"
fi
else
- JAVACMD="`which java`"
+ JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
@@ -160,12 +132,9 @@ if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
-CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
-
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
-
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
@@ -185,7 +154,7 @@ find_maven_basedir() {
fi
# end of workaround
done
- echo "${basedir}"
+ printf '%s' "$(cd "$basedir"; pwd)"
}
# concatenates all lines of a file
@@ -195,19 +164,106 @@ concat_lines() {
fi
}
-BASE_DIR=`find_maven_basedir "$(pwd)"`
+BASE_DIR=$(find_maven_basedir "$(dirname $0)")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
-export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
-echo $MAVEN_PROJECTBASEDIR
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $wrapperUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ QUIET="--quiet"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ QUIET=""
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath"
+ fi
+ [ $? -eq 0 ] || rm -f "$wrapperJarPath"
+ elif command -v curl > /dev/null; then
+ QUIET="--silent"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ QUIET=""
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L
+ fi
+ [ $? -eq 0 ] || rm -f "$wrapperJarPath"
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=`cygpath --path --windows "$javaSource"`
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
- [ -n "$M2_HOME" ] &&
- M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
@@ -216,10 +272,16 @@ if $cygwin; then
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
- "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
old mode 100755
new mode 100644
index 019bd74d..cba1f040
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -1,143 +1,187 @@
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Maven2 Start Up Batch script
-@REM
-@REM Required ENV vars:
-@REM JAVA_HOME - location of a JDK home dir
-@REM
-@REM Optional ENV vars
-@REM M2_HOME - location of maven2's installed home dir
-@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
-@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
-@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
-@REM e.g. to debug Maven itself, use
-@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
-@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
-@REM ----------------------------------------------------------------------------
-
-@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
-@echo off
-@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
-@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
-
-@REM set %HOME% to equivalent of $HOME
-if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
-
-@REM Execute a user defined script before this one
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
-@REM check for pre script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
-if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
-:skipRcPre
-
-@setlocal
-
-set ERROR_CODE=0
-
-@REM To isolate internal variables from possible post scripts, we use another setlocal
-@setlocal
-
-@REM ==== START VALIDATION ====
-if not "%JAVA_HOME%" == "" goto OkJHome
-
-echo.
-echo Error: JAVA_HOME not found in your environment. >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-:OkJHome
-if exist "%JAVA_HOME%\bin\java.exe" goto init
-
-echo.
-echo Error: JAVA_HOME is set to an invalid directory. >&2
-echo JAVA_HOME = "%JAVA_HOME%" >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-@REM ==== END VALIDATION ====
-
-:init
-
-@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
-@REM Fallback to current working directory if not found.
-
-set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
-IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
-
-set EXEC_DIR=%CD%
-set WDIR=%EXEC_DIR%
-:findBaseDir
-IF EXIST "%WDIR%"\.mvn goto baseDirFound
-cd ..
-IF "%WDIR%"=="%CD%" goto baseDirNotFound
-set WDIR=%CD%
-goto findBaseDir
-
-:baseDirFound
-set MAVEN_PROJECTBASEDIR=%WDIR%
-cd "%EXEC_DIR%"
-goto endDetectBaseDir
-
-:baseDirNotFound
-set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
-cd "%EXEC_DIR%"
-
-:endDetectBaseDir
-
-IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
-
-@setlocal EnableExtensions EnableDelayedExpansion
-for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
-@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
-
-:endReadAdditionalConfig
-
-SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
-
-set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
-set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
-
-%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
-if ERRORLEVEL 1 goto error
-goto end
-
-:error
-set ERROR_CODE=1
-
-:end
-@endlocal & set ERROR_CODE=%ERROR_CODE%
-
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
-@REM check for post script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
-if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
-:skipRcPost
-
-@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
-if "%MAVEN_BATCH_PAUSE%" == "on" pause
-
-if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
-
-exit /B %ERROR_CODE%
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.1.1
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
index 8578e8b1..c07e765a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,19 +1,19 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-build
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTpomSpring JavaFormat BuildSpring JavaFormat
- https://github.com/spring-io/spring-javaformat/#
+ https://github.com/spring-io/spring-javaformat/Apache License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
@@ -24,44 +24,55 @@
Pivotalinfo@pivotal.ioPivotal Software, Inc.
- http://www.spring.io
+ https://www.spring.io${basedir}UTF-81.8
- http://download.eclipse.org/releases/oxygen
+ https://download.eclipse.org/releases/2021-03/202103171000/
+ https://download.eclipse.org/releases/2024-03/202403131000/
+ https://checkstyle.org/eclipse-cs-update-site/
+ true1.8.11.0b3
- 5.2
+ 9.63.8.0
- 3.4
- 2.4.7
- 3.5.0
+ 9.3
+ 2.4.21
+ 2.17.1
+ 3.8.8${maven-core.version}
- 3.5
- 2.8.47
- 4.12
+ 3.8.2
+ 3.6.28
+ 5.8.13.21.0-GA1.2
+ 4.0.31.16.0
+ 1.16.03.0.3
- 1.1.0
- 1.1.0
+ 4.0.4
+ 4.0.4
+
+ com.github.eirslett
+ frontend-maven-plugin
+ 1.12.1
+ com.github.wvengenproguard-maven-plugin
- 2.0.14
+ 2.6.0
- net.sf.proguard
- proguard-base
- 5.3
+ com.guardsquare
+ proguard-core
+ 9.0.7runtime
@@ -69,54 +80,49 @@
com.googlecode.maven-download-plugindownload-maven-plugin
- 1.3.0
+ 1.6.8org.apache.maven.pluginsmaven-antrun-plugin
- 1.8
+ 3.1.0org.apache.maven.pluginsmaven-checkstyle-plugin
- 2.17
+ 3.2.1com.puppycrawl.toolscheckstyle
- 8.11
+ ${checkstyle.version}org.apache.maven.pluginsmaven-clean-plugin
- 3.0.0
+ 3.2.0org.apache.maven.pluginsmaven-compiler-plugin
- 3.6.1
+ 3.10.1org.apache.maven.pluginsmaven-deploy-plugin
- 2.8.2
+ 3.0.0org.apache.maven.pluginsmaven-dependency-plugin
- 3.0.1
-
-
- org.apache.maven.plugins
- maven-eclipse-plugin
- 2.10
+ 3.5.0org.apache.maven.pluginsmaven-failsafe-plugin
- 2.20
+ 2.22.2
@@ -129,37 +135,37 @@
org.apache.maven.pluginsmaven-install-plugin
- 2.5.2
+ 3.1.0org.apache.maven.pluginsmaven-invoker-plugin
- 3.0.0
+ 3.4.0org.apache.maven.pluginsmaven-jar-plugin
- 3.0.2
+ 3.3.0org.apache.maven.pluginsmaven-plugin-plugin
- 3.5
+ 3.7.1org.apache.maven.pluginsmaven-shade-plugin
- 3.0.0
+ 3.4.1org.apache.maven.pluginsmaven-site-plugin
- 3.6
+ 3.12.1org.apache.maven.pluginsmaven-surefire-plugin
- 2.20
+ 2.22.2**/*Tests.java
@@ -173,32 +179,36 @@
org.apache.maven.pluginsmaven-source-plugin
- 3.0.1
+ 3.2.1org.apache.maven.pluginsmaven-javadoc-plugin
- 3.0.0
+ 3.4.1
+
+ 8
+ -Xdoclint:none
+ org.apache.maven.pluginsmaven-resources-plugin
- 3.0.2
+ 3.3.0org.codehaus.mojoversions-maven-plugin
- 2.3
+ 2.14.2org.codehaus.mojoexec-maven-plugin
- 1.6.0
+ 3.1.0org.codehaus.mojobuild-helper-maven-plugin
- 3.0.0
+ 3.3.0org.eclipse.tycho
@@ -214,7 +224,8 @@
**/Abstract*.java${ui.test.vmargs}
- 7200
+ 7200
+ false
@@ -224,16 +235,14 @@
${tycho.version}
- org.eclipse.tycho.extras
+ org.eclipse.tychotycho-buildtimestamp-jgit
- ${tycho-extras.version}
+ ${tycho.version}jgit
-
- pom.xml
-
+ pom.xmlwarning
@@ -266,6 +275,11 @@
win32x86
+
+ win32
+ win32
+ x86_64
+ linuxgtk
@@ -276,6 +290,11 @@
cocoax86_64
+
+ macosx
+ cocoa
+ aarch64
+
@@ -301,53 +320,35 @@
-
- org.apache.maven.plugins
-
-
- maven-checkstyle-plugin
-
-
- [2.17,)
-
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ [2.17,)check
-
+
-
- org.codehaus.mojo
-
-
- flatten-maven-plugin
-
-
- [1.0.0,)
-
+ org.codehaus.mojo
+ flatten-maven-plugin
+ [1.0.0,)flatten
-
+
-
- org.eclipse.tycho
-
-
- tycho-versions-plugin
-
-
- [1.1.0,)
-
+ org.eclipse.tycho
+ tycho-versions-plugin
+ [1.1.0,)
update-eclipse-metadata
@@ -355,22 +356,35 @@
-
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ [1.8,)
+
+ run
+
+
+
+
- org.apache.maven.plugins
+ com.github.eirslett
- maven-antrun-plugin
+ frontend-maven-plugin
- [1.8,)
+ [1.12.1,)
- run
+ npx
@@ -390,6 +404,11 @@
${java.version}${java.version}
+ -Werror
+ -Xlint:deprecation
+ -Xlint:rawtypes
+ -Xlint:unchecked
+ -Xlint:varargs
@@ -447,7 +466,6 @@
src/checkstyle/checkstyle-suppressions.xmlsrc/checkstyle/checkstyle-header.txtcheckstyle.build.directory=${project.build.directory}
- UTF-8truetruetrue
@@ -463,14 +481,31 @@
- junit
- junit
- ${junit.version}
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ ${log4j.version}
+
+
+ org.junit
+ junit-bom
+ 5.8.1
+ pom
+ importcom.puppycrawl.toolscheckstyle
- 8.11
+ ${checkstyle.version}net.sf.trove4j
@@ -503,46 +538,6 @@
groovy${groovy.version}
-
- org.gradle
- gradle-base-services
- ${gradle.version}
-
-
- org.gradle
- gradle-base-services-groovy
- ${gradle.version}
-
-
- org.gradle
- gradle-core
- ${gradle.version}
-
-
- org.gradle
- gradle-language-java
- ${gradle.version}
-
-
- org.gradle
- gradle-language-jvm
- ${gradle.version}
-
-
- org.gradle
- gradle-platform-jvm
- ${gradle.version}
-
-
- org.gradle
- gradle-plugins
- ${gradle.version}
-
-
- org.gradle
- gradle-tooling-api
- ${gradle.version}
- org.javassistjavassist
@@ -563,13 +558,28 @@
picocontainer${picocontainer.version}
+
+ org.codehaus.plexus
+ plexus-utils
+ ${plexus-utils.version}
+
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+
- junit
- junit
+ org.junit.jupiter
+ junit-jupitertest
@@ -583,19 +593,13 @@
test
-
-
- eclipse
- p2
- ${eclipse.repository}
-
- spring-javaformat
- spring-javaformat-maven
- spring-javaformat-gradlespring-javaformat-eclipse
- spring-javaformat-intellij
+ spring-javaformat-gradle
+ spring-javaformat-intellij-idea
+ spring-javaformat-maven
+ spring-javaformat-vscode
@@ -607,7 +611,7 @@
- -Xmx512m -XX:MaxPermSize=256m -XstartOnFirstThread
+ -Xmx512m -XstartOnFirstThread
@@ -619,7 +623,7 @@
- -Xmx512m -XX:MaxPermSize=256m
+ -Xmx512m
diff --git a/samples/spring-javaformat-gradle-sample/.eclipse/eclipse.properties b/samples/spring-javaformat-gradle-sample/.eclipse/eclipse.properties
new file mode 100644
index 00000000..217686f5
--- /dev/null
+++ b/samples/spring-javaformat-gradle-sample/.eclipse/eclipse.properties
@@ -0,0 +1 @@
+copyright-year=2017-2019
\ No newline at end of file
diff --git a/samples/spring-javaformat-gradle-sample/build.gradle b/samples/spring-javaformat-gradle-sample/build.gradle
index 93df30ee..3fa4c986 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.6-SNAPSHOT")
+ classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.48-SNAPSHOT")
}
}
@@ -21,9 +21,9 @@ repositories {
}
checkstyle {
- toolVersion = "8.9"
+ toolVersion = "8.29"
}
dependencies {
- checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.6-SNAPSHOT")
+ checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.48-SNAPSHOT")
}
diff --git a/samples/spring-javaformat-gradle-sample/config/checkstyle/checkstyle.xml b/samples/spring-javaformat-gradle-sample/config/checkstyle/checkstyle.xml
index b1231c9b..886a68d2 100644
--- a/samples/spring-javaformat-gradle-sample/config/checkstyle/checkstyle.xml
+++ b/samples/spring-javaformat-gradle-sample/config/checkstyle/checkstyle.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/samples/spring-javaformat-gradle-sample/gradle/wrapper/gradle-wrapper.properties b/samples/spring-javaformat-gradle-sample/gradle/wrapper/gradle-wrapper.properties
index a452b450..4d9ca164 100644
--- a/samples/spring-javaformat-gradle-sample/gradle/wrapper/gradle-wrapper.properties
+++ b/samples/spring-javaformat-gradle-sample/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Thu Apr 26 21:27:14 PDT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip
diff --git a/samples/spring-javaformat-gradle-sample/src/checkstyle/checkstyle.xml b/samples/spring-javaformat-gradle-sample/src/checkstyle/checkstyle.xml
index 3c433aee..284595fc 100644
--- a/samples/spring-javaformat-gradle-sample/src/checkstyle/checkstyle.xml
+++ b/samples/spring-javaformat-gradle-sample/src/checkstyle/checkstyle.xml
@@ -1,5 +1,7 @@
-
+
\ No newline at end of file
diff --git a/samples/spring-javaformat-gradle-sample/src/main/java/sample/SampleApplication.java b/samples/spring-javaformat-gradle-sample/src/main/java/sample/SampleApplication.java
index ed240148..480785d1 100644
--- a/samples/spring-javaformat-gradle-sample/src/main/java/sample/SampleApplication.java
+++ b/samples/spring-javaformat-gradle-sample/src/main/java/sample/SampleApplication.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/samples/spring-javaformat-maven-sample/.checkstyle b/samples/spring-javaformat-maven-sample/.checkstyle
new file mode 100644
index 00000000..5783bc0d
--- /dev/null
+++ b/samples/spring-javaformat-maven-sample/.checkstyle
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/samples/spring-javaformat-maven-sample/.eclipse/eclipse.properties b/samples/spring-javaformat-maven-sample/.eclipse/eclipse.properties
index f3b95ce3..217686f5 100644
--- a/samples/spring-javaformat-maven-sample/.eclipse/eclipse.properties
+++ b/samples/spring-javaformat-maven-sample/.eclipse/eclipse.properties
@@ -1 +1 @@
-copyright-year=2017-2018
\ No newline at end of file
+copyright-year=2017-2019
\ No newline at end of file
diff --git a/samples/spring-javaformat-maven-sample/pom.xml b/samples/spring-javaformat-maven-sample/pom.xml
index b2891b3d..9354db42 100644
--- a/samples/spring-javaformat-maven-sample/pom.xml
+++ b/samples/spring-javaformat-maven-sample/pom.xml
@@ -1,17 +1,21 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformat.samplespring-javaformat-maven-sample0.0.1-SNAPSHOT
+
+ UTF-8
+ 0.0.48-SNAPSHOT
+ io.spring.javaformatspring-javaformat-maven-plugin
- 0.0.6-SNAPSHOT
+ ${spring-javaformat.version}
@@ -28,12 +32,12 @@
com.puppycrawl.toolscheckstyle
- 8.8
+ 8.29io.spring.javaformatspring-javaformat-checkstyle
- ${project.version}
+ 0.0.20-SNAPSHOT
diff --git a/samples/spring-javaformat-maven-sample/src/main/java/sample/SampleApplication.java b/samples/spring-javaformat-maven-sample/src/main/java/sample/SampleApplication.java
index ed240148..480785d1 100644
--- a/samples/spring-javaformat-maven-sample/src/main/java/sample/SampleApplication.java
+++ b/samples/spring-javaformat-maven-sample/src/main/java/sample/SampleApplication.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.properties b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.properties
index 2fb1fe2a..12c7b165 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.properties
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/feature.properties
@@ -1,14 +1,15 @@
featureName=Spring Java Format
providerName=Spring
+vendorName=Pivotal
description=Spring Java Format Eclipse Plugin
copyright=\
-Copyright 2000-2014 the original author or authors.\n\
+Copyright 2000-2019 the original author or authors.\n\
All rights reserved. This program and the accompanying materials\n\
are made available under the terms of the Apache License v2.0\n\
which accompanies this distribution, and is available at\n\
-http://www.apache.org/licenses/LICENSE-2.0\n\
+https://www.apache.org/licenses/LICENSE-2.0\n\
\n
licenseURL=license.html
@@ -20,7 +21,7 @@ Licensed under the Apache License, Version 2.0 (the "License");\n\
you may not use this file except in compliance with the License.\n\
You may obtain a copy of the License at\n\
\n\
- http://www.apache.org/licenses/LICENSE-2.0\n\
+ https://www.apache.org/licenses/LICENSE-2.0\n\
\n\
Unless required by applicable law or agreed to in writing, software\n\
distributed under the License is distributed on an "AS IS" BASIS,\n\
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 92815e82..5204ad42 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.7.qualifier"
+ version="0.0.48.qualifier"
unpack="false"/>
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/license.html b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/license.html
index 65825a7a..6810f277 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/license.html
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/license.html
@@ -1,5 +1,5 @@
-
+
@@ -30,7 +30,7 @@
Apache License Version 2.0
-Copyright 2017-2018 the original author or authors.
+Copyright 2017-2019 the original author or authors.
Unless required by applicable law or agreed to in writing, software
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 5bad3f8f..7b294c42 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.feature/pom.xml
@@ -1,17 +1,18 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-eclipse
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTio.spring.javaformat.eclipse.featureeclipse-feature
- Spring JavaFormat Eclipse Feature
+ Spring JavaFormat Eclipse Plugin Feature${basedir}/../..
+ 17
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 a92e1f32..325568f3 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 608bfc9a..4fc99abc 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 516f3220..5d4e2f97 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.site/pom.xml
@@ -1,18 +1,19 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-eclipse
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTio.spring.javaformat.eclipse.siteeclipse-repository
- Spring JavaFormat Eclipse Site
+ Spring JavaFormat Eclipse Plugin Site${basedir}/../..
+ 17
@@ -21,7 +22,6 @@
tycho-packaging-plugin${project.artifactId}
- true
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 3c8c5f4a..650cb7b0 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
@@ -1,15 +1,18 @@
Manifest-Version: 1.0
Fragment-Host: io.spring.javaformat.eclipse
+Import-Package: org.junit,
+ org.junit.jupiter.api,
+ org.junit.jupiter.api.io
Bundle-ManifestVersion: 2
-Bundle-Name: Spring Java Format Tests
+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.7.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Require-Bundle: org.junit;bundle-version="4.12"
+Bundle-Version: 0.0.48.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ClassPath: .,
lib/assertj-core.jar,
lib/byte-buddy-agent.jar,
lib/byte-buddy.jar,
lib/mockito-core.jar,
- lib/objenesis.jar
+ lib/objenesis.jar,
+ lib/junit-jupiter-api.jar
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/build.properties b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/build.properties
index f084befe..b62f58dd 100755
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/build.properties
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/build.properties
@@ -6,4 +6,5 @@ bin.includes = META-INF/,\
lib/byte-buddy-agent.jar,\
lib/byte-buddy.jar,\
lib/mockito-core.jar,\
- lib/objenesis.jar
+ lib/objenesis.jar,\
+ lib/junit-jupiter-api.jar
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/.gitignore b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/.gitignore
new file mode 100644
index 00000000..72e8ffc0
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/assertj-core.jar b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/assertj-core.jar
deleted file mode 100644
index 49976cdd..00000000
Binary files a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/assertj-core.jar and /dev/null differ
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy-agent.jar b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy-agent.jar
deleted file mode 100644
index 350e6cc9..00000000
Binary files a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy-agent.jar and /dev/null differ
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy.jar b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy.jar
deleted file mode 100644
index 04c0f847..00000000
Binary files a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/byte-buddy.jar and /dev/null differ
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/mockito-core.jar b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/mockito-core.jar
deleted file mode 100644
index 2e10d748..00000000
Binary files a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/mockito-core.jar and /dev/null differ
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/objenesis.jar b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/objenesis.jar
deleted file mode 100644
index 7b60a8b4..00000000
Binary files a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/lib/objenesis.jar and /dev/null differ
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 569e1f05..532aefb8 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/pom.xml
@@ -1,18 +1,20 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-eclipse
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTio.spring.javaformat.eclipse.testseclipse-test-pluginSpring JavaFormat Eclipse Test${basedir}/../..
+ 17
+ true
@@ -26,4 +28,36 @@
runtime
+
+
+
+ org.apache.maven.plugins
+ 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/MessagesTests.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/MessagesTests.java
index 6a5bbfaa..7684c764 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/MessagesTests.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/MessagesTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -17,7 +17,7 @@
package io.spring.javaformat.eclipse;
import org.eclipse.osgi.util.NLS;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -29,10 +29,9 @@
public class MessagesTests {
@Test
- public void bindHasCorrectMessage() {
+ void bindHasCorrectMessage() {
String message = NLS.bind(Messages.springFormatSettingsImportError, "reason");
- assertThat(message)
- .isEqualTo("Error importing project specific settings: reason");
+ assertThat(message).isEqualTo("Error importing project specific settings: reason");
}
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectPropertiesTests.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectPropertiesTests.java
index d1e188d5..a8568832 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectPropertiesTests.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectPropertiesTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -22,12 +22,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.time.LocalDate;
import java.util.Properties;
import java.util.stream.Collectors;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import io.spring.javaformat.config.JavaFormatConfig;
import static org.assertj.core.api.Assertions.assertThat;
@@ -38,53 +40,51 @@
*/
public class ProjectPropertiesTests {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ @TempDir
+ public File temp;
@Test
- public void addFromFolderAddsEclipseProperties() throws IOException {
- File folder = this.temp.newFolder();
- File file = new File(folder, "eclipse.properties");
+ void addFromFolderAddsEclipseProperties() throws IOException {
+ File file = new File(this.temp, "eclipse.properties");
writeProperties(file, "2018");
ProjectProperties properties = new ProjectProperties();
- properties.addFromFolder(folder);
+ properties.addFromFolder(this.temp);
assertThat(properties.get("copyright-year")).isEqualTo("2018");
}
@Test
- public void addFromFolderWhenAlreadySetDoesNotOverwrite() throws IOException {
+ void addFromFolderWhenAlreadySetDoesNotOverwrite() throws IOException {
ProjectProperties properties = new ProjectProperties();
- File folder = this.temp.newFolder();
- writeProperties(new File(folder, "eclipse.properties"), "2018");
- properties.addFromFolder(folder);
- folder = this.temp.newFolder();
- writeProperties(new File(folder, "eclipse.properties"), "2017");
- properties.addFromFolder(folder);
+ File folder1 = new File(this.temp, "1");
+ folder1.mkdirs();
+ writeProperties(new File(folder1, "eclipse.properties"), "2018");
+ properties.addFromFolder(folder1);
+ File folder2 = new File(this.temp, "2");
+ folder2.mkdirs();
+ writeProperties(new File(folder2, "eclipse.properties"), "2017");
+ properties.addFromFolder(folder2);
assertThat(properties.get("copyright-year")).isEqualTo("2018");
}
@Test
- public void addFromEmptyFolderUsesDefaults() throws IOException {
+ void addFromEmptyFolderUsesDefaults() throws IOException {
ProjectProperties properties = new ProjectProperties();
- File folder = this.temp.newFolder();
- properties.addFromFolder(folder);
- assertThat(properties.get("copyright-year")).isEqualTo("2018");
+ properties.addFromFolder(this.temp);
+ String currentYear = String.valueOf(LocalDate.now().getYear());
+ assertThat(properties.get("copyright-year")).isEqualTo(currentYear);
}
@Test
- public void getModifiedContentReplacesCopyrightYear() throws IOException {
- File folder = this.temp.newFolder();
- File file = new File(folder, "eclipse.properties");
- writeProperties(file, "2016-2020");
+ void getModifiedContentReplacesCopyrightYear() throws IOException {
+ String year = "2016-2020";
+ File file = new File(this.temp, "eclipse.properties");
+ writeProperties(file, year);
ProjectProperties properties = new ProjectProperties();
- properties.addFromFolder(folder);
- ProjectSettingsFiles files = new ProjectSettingsFilesLocator()
- .locateSettingsFiles();
+ properties.addFromFolder(this.temp);
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
ProjectSettingsFile prefs = getFile(files, "org.eclipse.jdt.ui.prefs");
- String content = loadContent(properties.getModifiedContent(prefs));
- assertThat(content)
- .contains("Copyright 2016-2020 the original author or authors");
-
+ String content = loadContent(properties.getModifiedContent(prefs).getContent(JavaFormatConfig.DEFAULT));
+ assertThat(content).contains("Copyright " + year + " the original author or authors");
}
private ProjectSettingsFile getFile(ProjectSettingsFiles files, String name) {
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFileTests.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFileTests.java
index 3237d0a3..769226b6 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFileTests.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFileTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,9 +21,10 @@
import java.io.FileNotFoundException;
import java.io.PrintWriter;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import io.spring.javaformat.config.JavaFormatConfig;
import static org.assertj.core.api.Assertions.assertThat;
@@ -34,26 +35,25 @@
*/
public class ProjectSettingsFileTests {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ @TempDir
+ public File temp;
@Test
- public void fromFileAdaptsFile() throws Exception {
- File file = this.temp.newFile();
+ void fromFileAdaptsFile() throws Exception {
+ File file = new File(this.temp, "file");
writeText(file, "test");
ProjectSettingsFile projectSettingsFile = ProjectSettingsFile.fromFile(file);
assertThat(projectSettingsFile.getName()).isEqualTo(file.getName());
- assertThat(projectSettingsFile.getContent())
- .hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
+ assertThat(projectSettingsFile.getContent(JavaFormatConfig.DEFAULT))
+ .hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
}
@Test
- public void fromClasspathResourceAdaptsResource() throws Exception {
- ProjectSettingsFile projectSettingsFile = ProjectSettingsFile
- .fromClasspath(getClass(), "test.txt");
+ void fromClasspathResourceAdaptsResource() throws Exception {
+ ProjectSettingsFile projectSettingsFile = ProjectSettingsFile.fromClasspath(getClass(), "test.txt");
assertThat(projectSettingsFile.getName()).isEqualTo("test.txt");
- assertThat(projectSettingsFile.getContent())
- .hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
+ assertThat(projectSettingsFile.getContent(JavaFormatConfig.DEFAULT))
+ .hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
}
private void writeText(File file, String s) throws FileNotFoundException {
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 24e831ad..26ca3380 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -19,13 +19,18 @@
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Properties;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
import static org.assertj.core.api.Assertions.assertThat;
@@ -36,44 +41,72 @@
*/
public class ProjectSettingsFilesLocatorTests {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ @TempDir
+ public File temp;
@Test
- public void locateSettingsFilesWhenNoFoldersShouldReturnDefault() throws IOException {
- ProjectSettingsFiles files = new ProjectSettingsFilesLocator()
- .locateSettingsFiles();
+ void locateSettingsFilesWhenNoFoldersReturnsDefault() throws IOException {
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
assertThat(files.iterator()).extracting(ProjectSettingsFile::getName)
- .containsOnly("org.eclipse.jdt.core.prefs", "org.eclipse.jdt.ui.prefs");
+ .containsOnly("org.eclipse.jdt.core.prefs", "org.eclipse.jdt.ui.prefs");
}
@Test
- public void locateSettingsFilesOnlyFindPrefs() throws Exception {
- File folder = this.temp.newFolder();
- writeFile(folder, "foo.prefs");
- writeFile(folder, "bar.notprefs");
- ProjectSettingsFiles files = new ProjectSettingsFilesLocator(folder)
- .locateSettingsFiles();
+ void locateSettingsFilesOnlyFindPrefs() throws Exception {
+ writeFile(this.temp, "foo.prefs");
+ writeFile(this.temp, "bar.notprefs");
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator(this.temp).locateSettingsFiles();
assertThat(files.iterator()).extracting(ProjectSettingsFile::getName)
- .containsOnly("org.eclipse.jdt.core.prefs", "org.eclipse.jdt.ui.prefs",
- "foo.prefs");
+ .containsOnly("org.eclipse.jdt.core.prefs", "org.eclipse.jdt.ui.prefs", "foo.prefs");
}
@Test
- public void locateSettingsFilesWhenMultipleFoldersFindsInEarliest() throws Exception {
- File folder1 = this.temp.newFolder();
+ void locateSettingsFilesWhenMultipleFoldersFindsInEarliest() throws Exception {
+ File folder1 = new File(this.temp, "1");
writeFile(folder1, "foo.prefs", "foo1");
- File folder2 = this.temp.newFolder();
+ File folder2 = new File(this.temp, "2");
writeFile(folder2, "foo.prefs", "foo2");
writeFile(folder2, "org.eclipse.jdt.core.prefs", "core2");
- ProjectSettingsFiles files = new ProjectSettingsFilesLocator(folder1, folder2)
- .locateSettingsFiles();
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator(folder1, folder2).locateSettingsFiles();
Map found = new LinkedHashMap<>();
files.iterator().forEachRemaining((f) -> found.put(f.getName(), f));
- assertThat(found.get("foo.prefs").getContent())
- .hasSameContentAs(new ByteArrayInputStream("foo1".getBytes()));
- assertThat(found.get("org.eclipse.jdt.core.prefs").getContent())
- .hasSameContentAs(new ByteArrayInputStream("core2".getBytes()));
+ assertThat(found.get("foo.prefs").getContent(JavaFormatConfig.DEFAULT))
+ .hasSameContentAs(new ByteArrayInputStream("foo1".getBytes()));
+ assertThat(found.get("org.eclipse.jdt.core.prefs").getContent(JavaFormatConfig.DEFAULT))
+ .hasSameContentAs(new ByteArrayInputStream("core2".getBytes()));
+ }
+
+ @Test
+ void jdtCorePrefsFormatterWhenDefaultUsesTabs() throws IOException {
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
+ ProjectSettingsFile file = get(files, "org.eclipse.jdt.core.prefs");
+ try (InputStream content = file.getContent(JavaFormatConfig.DEFAULT)) {
+ Properties properties = new Properties();
+ properties.load(content);
+ assertThat(properties.get("org.eclipse.jdt.core.javaFormatter"))
+ .isEqualTo("io.spring.javaformat.eclipse.formatter.jdk17.tabs");
+ }
+ }
+
+ @Test
+ void jdtCorePrefsFormatterWhenSpacesUsesSpaces() throws IOException {
+ ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
+ ProjectSettingsFile file = get(files, "org.eclipse.jdt.core.prefs");
+ try (InputStream content = file.getContent(JavaFormatConfig.of(JavaBaseline.V8, IndentationStyle.SPACES))) {
+ Properties properties = new Properties();
+ properties.load(content);
+ assertThat(properties.get("org.eclipse.jdt.core.javaFormatter"))
+ .isEqualTo("io.spring.javaformat.eclipse.formatter.jdk8.spaces");
+ }
+ }
+
+ private ProjectSettingsFile get(ProjectSettingsFiles files, String name) {
+ for (ProjectSettingsFile file : files) {
+ if (file.getName().equals(name)) {
+ return file;
+ }
+ }
+ return null;
}
private void writeFile(File folder, String name) throws IOException {
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesTests.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesTests.java
index 78770981..a5eb2ed1 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesTests.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,19 +16,28 @@
package io.spring.javaformat.eclipse.projectsettings;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.Collections;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.will;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -39,31 +48,62 @@
*/
public class ProjectSettingsFilesTests {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ @TempDir
+ public File temp;
@Test
- public void iteratorIteratesFiles() throws Exception {
- ProjectSettingsFile file = ProjectSettingsFile.fromFile(this.temp.newFile());
- ProjectSettingsFiles files = new ProjectSettingsFiles(Collections.singleton(file),
- new ProjectProperties());
+ void iteratorIteratesFiles() throws Exception {
+ ProjectSettingsFile file = ProjectSettingsFile.fromFile(new File(this.temp, "file.prefs"));
+ ProjectSettingsFiles files = new ProjectSettingsFiles(Collections.singleton(file), new ProjectProperties());
assertThat(files).containsOnly(file);
}
@Test
- public void applyToProjectCopiesToDotSettings() throws Exception {
- ProjectSettingsFile file = ProjectSettingsFile
- .fromFile(this.temp.newFile("foo.prefs"));
- ProjectSettingsFiles files = new ProjectSettingsFiles(Collections.singleton(file),
- new ProjectProperties());
+ void applyToProjectWithoutFileCopiesToDotSettings() throws Exception {
+ ProjectSettingsFile file = createPrefsFile();
+ ProjectSettingsFiles files = new ProjectSettingsFiles(Collections.singleton(file), new ProjectProperties());
+ IProject project = mock(IProject.class);
+ IProgressMonitor monitor = mock(IProgressMonitor.class);
+ IFile projectFile = mock(IFile.class);
+ given(project.getFile(".settings/foo.prefs")).willReturn(projectFile);
+ given(projectFile.exists()).willReturn(false);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ will((invocation) -> {
+ invocation.getArgument(0, InputStream.class).transferTo(out);
+ return null;
+ }).given(projectFile).create(any(), anyBoolean(), any());
+ files.applyToProject(project, monitor);
+ verify(projectFile).create(any(), eq(true), any());
+ assertThat(out.toString(StandardCharsets.UTF_8)).isEqualTo("y=z\n");
+ }
+
+ @Test
+ void applyToProjectWithFileMergesToDotSettings() throws Exception {
+ ProjectSettingsFile file = createPrefsFile();
+ ProjectSettingsFiles files = new ProjectSettingsFiles(Collections.singleton(file), new ProjectProperties());
IProject project = mock(IProject.class);
IProgressMonitor monitor = mock(IProgressMonitor.class);
IFile projectFile = mock(IFile.class);
given(project.getFile(".settings/foo.prefs")).willReturn(projectFile);
given(projectFile.exists()).willReturn(true);
+ given(projectFile.getContents(true))
+ .willReturn(new ByteArrayInputStream("a=b\n".getBytes(StandardCharsets.UTF_8)));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ will((invocation) -> {
+ invocation.getArgument(0, InputStream.class).transferTo(out);
+ return null;
+ }).given(projectFile).setContents((InputStream) any(), anyInt(), any());
files.applyToProject(project, monitor);
- verify(projectFile).delete(true, monitor);
- verify(projectFile).create(any(), eq(true), eq(monitor));
+ verify(projectFile).setContents((InputStream) any(), eq(1), eq(monitor));
+ assertThat(out.toString(StandardCharsets.UTF_8))
+ .isEqualToNormalizingNewlines("a=b\ny=z\n");
+ }
+
+ private ProjectSettingsFile createPrefsFile() throws IOException {
+ File prefsFile = new File(this.temp, "foo.prefs");
+ Files.copy(new ByteArrayInputStream("y=z\n".getBytes(StandardCharsets.UTF_8)), prefsFile.toPath());
+ ProjectSettingsFile file = ProjectSettingsFile.fromFile(prefsFile);
+ return file;
}
}
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 747d18bf..2e0f34c4 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
@@ -1,23 +1,26 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: Spring Java Format
+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.7.qualifier
+Bundle-Version: 0.0.48.qualifier
Bundle-Activator: io.spring.javaformat.eclipse.Activator
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-RequiredExecutionEnvironment: JavaSE-11
Require-Bundle: org.eclipse.ui,
org.eclipse.core.resources,
org.eclipse.core.runtime,
+ org.eclipse.ui.ide,
org.eclipse.jdt.core,
org.eclipse.jface.text,
org.eclipse.m2e.jdt;resolution:=optional,
org.eclipse.m2e.core;resolution:=optional,
org.eclipse.m2e.maven.runtime;resolution:=optional,
org.eclipse.buildship.core;resolution:=optional,
- com.gradleware.tooling.model;resolution:=optional,
- org.slf4j.api;bundle-version="1.7.0"
+ net.sf.eclipsecs.core;resolution:=optional
Bundle-ClassPath: .,
- lib/spring-javaformat-formatter-eclipse.jar,
- lib/spring-javaformat-formatter.jar
+ lib/spring-javaformat-config.jar,
+ lib/spring-javaformat-formatter.jar,
+ lib/spring-javaformat-checkstyle.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/bin/META-INF/MANIFEST.MF b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/META-INF/MANIFEST.MF
deleted file mode 100644
index 753e0f61..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,7 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Spring Javaformat
-Bundle-SymbolicName: io.spring.javaformat.eclipse.plugin;singleton:=true
-Bundle-Version: 0.0.1.qualifier
-Automatic-Module-Name: test
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/build.properties b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/build.properties
deleted file mode 100644
index 34d2e4d2..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/build.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/plugin.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/plugin.xml
deleted file mode 100644
index 5db0254f..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/plugin.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/pom.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/pom.xml
deleted file mode 100644
index 178b0b40..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/bin/pom.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
- 4.0.0
-
- io.spring.javaformat
- spring-javaformat-eclipse
- 0.0.1-SNAPSHOT
-
- spring-javaformat-eclipse-plugin
- eclipse-plugin
-
- ${basedir}/../../..
-
-
-
-
- org.eclipse.tycho
- tycho-maven-plugin
-
-
- org.eclipse.tycho
- target-platform-configuration
-
-
-
-
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
index a9ce579d..9bd6565a 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties
@@ -3,6 +3,8 @@ bin.includes = META-INF/,\
.,\
plugin.xml,\
lifecycle-mapping-metadata.xml,\
- lib/spring-javaformat-formatter-eclipse.jar,\
- lib/spring-javaformat-formatter.jar
-
+ lib/spring-javaformat-checkstyle.jar,\
+ lib/spring-javaformat-config.jar,\
+ lib/spring-javaformat-formatter.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 723871df..f9864bd4 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml
@@ -3,26 +3,48 @@
+ class="io.spring.javaformat.eclipse.formatter.SpringCodeFormatterJdk17Tabs"
+ id="io.spring.javaformat.eclipse.formatter.jdk17.tabs"
+ name="Spring (tabs)">
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/pom.xml b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/pom.xml
index ee9f0837..3ccfe109 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/pom.xml
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/pom.xml
@@ -1,26 +1,83 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-eclipse
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTio.spring.javaformat.eclipseeclipse-plugin
- Spring JavaFormat Eclipse Parent
+ Spring JavaFormat Eclipse Plugin${basedir}/../..
+ 17
+
+ io.spring.javaformat
+ spring-javaformat-config
+ runtime
+ ${project.version}
+ io.spring.javaformatspring-javaformat-formatterruntime${project.version}
+
+ io.spring.javaformat
+ spring-javaformat-checkstyle
+ runtime
+ ${project.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+ io.spring.javaformat
+ spring-javaformat-config
+ ${project.version}
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ ${project.version}
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-jdt-jdk8
+ ${project.version}
+
+
+ io.spring.javaformat
+ 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 ee7e6122..bef6af6b 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,7 +16,10 @@
package io.spring.javaformat.eclipse;
-import io.spring.javaformat.eclipse.gradle.RefreshProjectSettingsListeners;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Plugin;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
@@ -34,18 +37,27 @@ public class Activator extends AbstractUIPlugin {
private static Activator plugin;
+ private final List javaCorePlugins = new ArrayList<>();
+
public Activator() {
+ this.javaCorePlugins.add(new io.spring.javaformat.eclipse.jdt.jdk8.core.JavaCore());
+ this.javaCorePlugins.add(new io.spring.javaformat.eclipse.jdt.jdk17.core.JavaCore());
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
- RefreshProjectSettingsListeners.attach();
plugin = this;
+ for (Plugin javaCorePlugin : this.javaCorePlugins) {
+ javaCorePlugin.start(context);
+ }
}
@Override
public void stop(BundleContext context) throws Exception {
+ for (Plugin javaCorePlugin : this.javaCorePlugins) {
+ javaCorePlugin.stop(context);
+ }
plugin = null;
super.stop(context);
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Executor.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Executor.java
index 27f1065e..7782afd3 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Executor.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Executor.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -52,8 +52,7 @@ public void run(Command command) throws CoreException {
throw (CoreException) ex;
}
String msg = NLS.bind(this.failureMessage, ex.getMessage());
- throw new CoreException(
- new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, msg, ex));
+ throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, msg, ex));
}
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Messages.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Messages.java
index 05f4fe5f..3fc7ab01 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Messages.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Messages.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -25,8 +25,7 @@
*/
public final class Messages extends NLS {
- private static final String BUNDLE_NAME = Messages.class.getPackage().getName()
- + ".messages"; //$NON-NLS-1$
+ private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$
/**
* General error message.
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Startup.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Startup.java
index fc9b14e8..c19e50e9 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Startup.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/Startup.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatter.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatter.java
index 74129974..d26d70bd 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatter.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -18,32 +18,35 @@
import java.util.Map;
-import io.spring.javaformat.formatter.Formatter;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jface.text.IRegion;
import org.eclipse.text.edits.TextEdit;
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.Formatter;
+
/**
- * Eclipse {@link CodeFormatter} for Spring formatting.
+ * Eclipse {@link CodeFormatter} base class for Spring formatting.
*
* @author Phillip Webb
*/
-public class SpringCodeFormatter extends CodeFormatter {
+public abstract class SpringCodeFormatter extends CodeFormatter {
- private Formatter delegate = new Formatter();
+ private final Formatter delegate;
+
+ public SpringCodeFormatter(JavaFormatConfig javaFormatConfig) {
+ this.delegate = new Formatter(javaFormatConfig);
+ }
@Override
- public TextEdit format(int kind, String source, int offset, int length,
- int indentationLevel, String lineSeparator) {
- return this.delegate.format(kind, source, offset, length, indentationLevel,
- lineSeparator);
+ public TextEdit format(int kind, String source, int offset, int length, int indentationLevel,
+ String lineSeparator) {
+ return this.delegate.format(kind, source, offset, length, indentationLevel, lineSeparator);
}
@Override
- public TextEdit format(int kind, String source, IRegion[] regions,
- int indentationLevel, String lineSeparator) {
- return this.delegate.format(kind, source, regions, indentationLevel,
- lineSeparator);
+ public TextEdit format(int kind, String source, IRegion[] regions, int indentationLevel, String lineSeparator) {
+ return this.delegate.format(kind, source, regions, indentationLevel, lineSeparator);
}
@Override
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java
new file mode 100644
index 00000000..d0682ff2
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Spaces.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.eclipse.formatter;
+
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Eclipse {@link CodeFormatter} for Spring formatting with spaces.
+ *
+ * @author Phillip Webb
+ */
+public class SpringCodeFormatterJdk17Spaces extends SpringCodeFormatter {
+
+ 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/SpringCodeFormatterJdk17Tabs.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Tabs.java
new file mode 100644
index 00000000..718e9846
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk17Tabs.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.eclipse.formatter;
+
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Eclipse {@link CodeFormatter} for Spring formatting with tabs.
+ *
+ * @author Phillip Webb
+ */
+public class SpringCodeFormatterJdk17Tabs extends SpringCodeFormatter {
+
+ public SpringCodeFormatterJdk17Tabs() {
+ super(JavaFormatConfig.of(JavaBaseline.V17, IndentationStyle.TABS));
+ }
+
+}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Spaces.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Spaces.java
new file mode 100644
index 00000000..536c85ef
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Spaces.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.eclipse.formatter;
+
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Eclipse {@link CodeFormatter} for Spring formatting with spaces.
+ *
+ * @author Phillip Webb
+ */
+public class SpringCodeFormatterJdk8Spaces extends SpringCodeFormatter {
+
+ public SpringCodeFormatterJdk8Spaces() {
+ super(JavaFormatConfig.of(JavaBaseline.V8, IndentationStyle.SPACES));
+ }
+
+}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Tabs.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Tabs.java
new file mode 100644
index 00000000..0750be23
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatterJdk8Tabs.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.eclipse.formatter;
+
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Eclipse {@link CodeFormatter} for Spring formatting with tabs.
+ *
+ * @author Phillip Webb
+ */
+public class SpringCodeFormatterJdk8Tabs extends SpringCodeFormatter {
+
+ public SpringCodeFormatterJdk8Tabs() {
+ super(JavaFormatConfig.of(JavaBaseline.V8, IndentationStyle.TABS));
+ }
+
+}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/GradleProjectSettingsConfigurator.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/GradleProjectSettingsConfigurator.java
new file mode 100644
index 00000000..9ab4bb69
--- /dev/null
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/GradleProjectSettingsConfigurator.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-present 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.eclipse.gradle;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.buildship.core.GradleBuild;
+import org.eclipse.buildship.core.InitializationContext;
+import org.eclipse.buildship.core.ProjectConfigurator;
+import org.eclipse.buildship.core.ProjectContext;
+import org.eclipse.buildship.core.internal.CorePlugin;
+import org.eclipse.buildship.core.internal.workspace.FetchStrategy;
+import org.eclipse.buildship.core.internal.workspace.InternalGradleBuild;
+import org.eclipse.buildship.core.internal.workspace.InternalGradleWorkspace;
+import org.eclipse.buildship.core.internal.workspace.ModelProvider;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.gradle.tooling.CancellationTokenSource;
+import org.gradle.tooling.GradleConnector;
+import org.gradle.tooling.model.GradleTask;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+
+import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFilesLocator;
+
+/**
+ * {@link ProjectConfigurator} to apply project-specific settings to Gradle projects.
+ *
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ */
+@SuppressWarnings("restriction")
+public class GradleProjectSettingsConfigurator implements ProjectConfigurator {
+
+ private static final Object TASK_NAME = "checkFormatMain";
+
+ private CancellationTokenSource tokenSource;
+
+ @Override
+ public void init(InitializationContext context, IProgressMonitor monitor) {
+ this.tokenSource = GradleConnector.newCancellationTokenSource();
+
+ }
+
+ @Override
+ public void configure(ProjectContext context, IProgressMonitor monitor) {
+ try {
+ configureProject(context.getProject(), monitor);
+ }
+ catch (Exception ex) {
+ context.error("Failed to apply project settings", ex);
+ }
+ }
+
+ private void configureProject(IProject project, IProgressMonitor monitor) throws CoreException, IOException {
+ InternalGradleWorkspace workspace = CorePlugin.internalGradleWorkspace();
+ Optional build = workspace.getBuild(project);
+ if (build.isPresent()) {
+ ModelProvider modelProvider = ((InternalGradleBuild) build.get()).getModelProvider();
+ Collection rootProjects = getRootProjects(monitor, modelProvider);
+ EclipseProject eclipseProject = findProjectByName(rootProjects, project.getName());
+ if (hasSpringFormatPlugin(eclipseProject)) {
+ ProjectSettingsFilesLocator locator = new ProjectSettingsFilesLocator(getSearchFolders(rootProjects));
+ locator.locateSettingsFiles().applyToProject(project, monitor);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Collection getRootProjects(IProgressMonitor monitor, ModelProvider modelProvider) {
+ Object models = modelProvider.fetchModels(EclipseProject.class, FetchStrategy.FORCE_RELOAD, this.tokenSource,
+ monitor);
+ return (Collection) ((models instanceof Map) ? ((Map, ?>) models).values() : models);
+ }
+
+ private EclipseProject findProjectByName(Iterable extends EclipseProject> candidates, String name) {
+ for (EclipseProject candidate : candidates) {
+ if (name.equals(candidate.getName())) {
+ return candidate;
+ }
+ EclipseProject childResult = findProjectByName(candidate.getChildren(), name);
+ if (childResult != null) {
+ return childResult;
+ }
+ }
+ return null;
+ }
+
+ private boolean hasSpringFormatPlugin(EclipseProject eclipseProject) {
+ if (eclipseProject != null) {
+ for (GradleTask task : eclipseProject.getGradleProject().getTasks()) {
+ if (isSpringFormatPlugin(task)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isSpringFormatPlugin(GradleTask task) {
+ return TASK_NAME.equals(task.getName());
+ }
+
+ private Set getSearchFolders(Collection projects) {
+ Set searchFolders = new LinkedHashSet<>();
+ for (EclipseProject project : projects) {
+ while (project != null) {
+ searchFolders.add(project.getProjectDirectory());
+ project = project.getParent();
+ }
+ }
+ return searchFolders;
+ }
+
+ @Override
+ public void unconfigure(ProjectContext context, IProgressMonitor monitor) {
+ }
+
+}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectSettingsListeners.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectSettingsListeners.java
deleted file mode 100644
index 7c122d77..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectSettingsListeners.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.javaformat.eclipse.gradle;
-
-import org.eclipse.buildship.core.CorePlugin;
-import org.eclipse.buildship.core.event.Event;
-import org.eclipse.buildship.core.event.EventListener;
-import org.eclipse.buildship.core.workspace.GradleNatureAddedEvent;
-import org.eclipse.buildship.core.workspace.ProjectCreatedEvent;
-import org.eclipse.core.commands.Command;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.IExecutionListener;
-import org.eclipse.core.commands.NotHandledException;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.commands.ICommandService;
-
-/**
- * Listeners used to trigger the {@link RefreshProjectsSettingsJob}.
- *
- * @author Phillip Webb
- */
-@SuppressWarnings("restriction")
-public final class RefreshProjectSettingsListeners {
-
- private RefreshProjectSettingsListeners() {
- }
-
- /**
- * Attach listeners to trigger the {@link RefreshProjectsSettingsJob}.
- */
- public static void attach() {
- try {
- ProjectListener.attach();
- CommandListener.attach();
- }
- catch (NoClassDefFoundError ex) {
- }
- }
-
- /**
- * Command listener that triggers an update after the "Refresh Gradle Project".
- */
- private static class CommandListener implements IExecutionListener {
-
- private static final String COMMAND_NAME = "org.eclipse.buildship.ui.commands.refreshproject"; //$NON-NLS-1$
-
- @Override
- public void notHandled(String commandId, NotHandledException exception) {
- }
-
- @Override
- public void postExecuteFailure(String commandId, ExecutionException exception) {
- }
-
- @Override
- public void postExecuteSuccess(String commandId, Object returnValue) {
- new RefreshProjectsSettingsJob().schedule();
- }
-
- @Override
- public void preExecute(String commandId, ExecutionEvent event) {
- }
-
- static void attach() {
- if (PlatformUI.isWorkbenchRunning()) {
- ICommandService commandService = PlatformUI.getWorkbench()
- .getAdapter(ICommandService.class);
- Command command = commandService.getCommand(COMMAND_NAME);
- if (command != null) {
- command.addExecutionListener(new CommandListener());
- }
- }
- }
-
- }
-
- /**
- * Event Listener to triger an update after a project import or gradle nature change.
- */
- private static class ProjectListener implements EventListener {
-
- @Override
- public void onEvent(Event event) {
- if (event instanceof ProjectCreatedEvent
- || event instanceof GradleNatureAddedEvent) {
- new RefreshProjectsSettingsJob().schedule();
- }
- }
-
- static void attach() {
- CorePlugin.listenerRegistry().addEventListener(new ProjectListener());
- }
-
- }
-
-}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectsSettingsJob.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectsSettingsJob.java
deleted file mode 100644
index 198006c2..00000000
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/RefreshProjectsSettingsJob.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.javaformat.eclipse.gradle;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import com.google.common.base.Optional;
-import com.gradleware.tooling.toolingmodel.OmniEclipseProject;
-import com.gradleware.tooling.toolingmodel.OmniProjectTask;
-import com.gradleware.tooling.toolingmodel.repository.FetchStrategy;
-import io.spring.javaformat.eclipse.Executor;
-import io.spring.javaformat.eclipse.Messages;
-import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFilesLocator;
-import org.eclipse.buildship.core.CorePlugin;
-import org.eclipse.buildship.core.workspace.GradleBuild;
-import org.eclipse.buildship.core.workspace.GradleWorkspaceManager;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.gradle.tooling.CancellationTokenSource;
-import org.gradle.tooling.GradleConnector;
-
-/**
- * Job to trigger refresh of project specific settings when the gradle plugin is used.
- *
- * @author Phillip Webb
- */
-@SuppressWarnings("restriction")
-public class RefreshProjectsSettingsJob extends Job {
-
- private static final Object TASK_NAME = "checkFormatMain";
-
- private final CancellationTokenSource tokenSource;
-
- public RefreshProjectsSettingsJob() {
- super("Refresh spring-javaformat project settings");
- this.tokenSource = GradleConnector.newCancellationTokenSource();
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- new Executor(Messages.springFormatSettingsImportError).run(() -> {
- configureProjects(monitor);
- });
- }
- catch (CoreException ex) {
- return ex.getStatus();
- }
- return Status.OK_STATUS;
- }
-
- private void configureProjects(IProgressMonitor monitor)
- throws CoreException, IOException {
- GradleWorkspaceManager manager = CorePlugin.gradleWorkspaceManager();
- for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
- Optional build = manager.getGradleBuild(project);
- if (build.isPresent()) {
- configureProject(project, build.get(), monitor);
- }
- }
- }
-
- private void configureProject(IProject project, GradleBuild build,
- IProgressMonitor monitor) throws CoreException, IOException {
- Set projects = build.getModelProvider()
- .fetchEclipseGradleProjects(FetchStrategy.FORCE_RELOAD,
- this.tokenSource.token(), monitor);
- if (hasSpringFormatPlugin(projects)) {
- ProjectSettingsFilesLocator locator = new ProjectSettingsFilesLocator(
- getSearchFolders(projects));
- locator.locateSettingsFiles().applyToProject(project, monitor);
- }
- }
-
- private boolean hasSpringFormatPlugin(Set projects) {
- for (OmniEclipseProject project : projects) {
- for (OmniProjectTask task : project.getGradleProject().getProjectTasks()) {
- if (isSpringFormatPlugin(task)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean isSpringFormatPlugin(OmniProjectTask task) {
- return TASK_NAME.equals(task.getName());
- }
-
- private Set getSearchFolders(Set projects) {
- Set searchFolders = new LinkedHashSet<>();
- for (OmniEclipseProject project : projects) {
- searchFolders.add(project.getProjectDirectory());
- searchFolders.add(project.getRoot().getProjectDirectory());
- }
- return searchFolders;
- }
-
-}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/ProjectSettingsConfigurator.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/MavenProjectSettingsConfigurator.java
similarity index 78%
rename from spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/ProjectSettingsConfigurator.java
rename to spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/MavenProjectSettingsConfigurator.java
index 69aca233..62e94e26 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/ProjectSettingsConfigurator.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/m2e/MavenProjectSettingsConfigurator.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -20,37 +20,36 @@
import java.util.ArrayList;
import java.util.List;
-import io.spring.javaformat.eclipse.Executor;
-import io.spring.javaformat.eclipse.Messages;
-import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFiles;
-import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFilesLocator;
import org.apache.maven.project.MavenProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest;
+import io.spring.javaformat.eclipse.Executor;
+import io.spring.javaformat.eclipse.Messages;
+import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFiles;
+import io.spring.javaformat.eclipse.projectsettings.ProjectSettingsFilesLocator;
+
/**
- * Configurator to apply project specific settings.
+ * Configurator to apply project-specific settings to Maven projects.
*
* @author Phillip Webb
*/
-public class ProjectSettingsConfigurator extends AbstractProjectConfigurator {
+public class MavenProjectSettingsConfigurator extends AbstractProjectConfigurator {
@Override
- public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor)
- throws CoreException {
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
new Executor(Messages.springFormatSettingsImportError).run(() -> {
List searchFolders = getSearchFolders(request);
- ProjectSettingsFiles settingsFiles = new ProjectSettingsFilesLocator(
- searchFolders).locateSettingsFiles();
- settingsFiles.applyToProject(request.getProject(), monitor);
+ ProjectSettingsFiles settingsFiles = new ProjectSettingsFilesLocator(searchFolders).locateSettingsFiles();
+ settingsFiles.applyToProject(request.mavenProjectFacade().getProject(), monitor);
});
}
private List getSearchFolders(ProjectConfigurationRequest request) {
List files = new ArrayList<>();
- MavenProject project = request.getMavenProject();
+ MavenProject project = request.mavenProject();
while (project != null && project.getBasedir() != null) {
files.add(project.getBasedir());
project = project.getParent();
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectProperties.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectProperties.java
index 880f8b2e..982777bd 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectProperties.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,14 +16,9 @@
package io.spring.javaformat.eclipse.projectsettings;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
@@ -31,7 +26,6 @@
import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
/**
* Eclipse properties used to modify setting files content.
@@ -42,8 +36,7 @@ class ProjectProperties {
private static final String COPYRIGHT_YEAR = "copyright-year";
- private static final DateTimeFormatter YEAR_FORMATTER = DateTimeFormatter
- .ofPattern("yyyy");
+ private static final DateTimeFormatter YEAR_FORMATTER = DateTimeFormatter.ofPattern("yyyy");
private static final Map> DEFAULTS;
static {
@@ -75,22 +68,13 @@ private void addFromProperties(Properties properties) {
});
}
- public InputStream getModifiedContent(ProjectSettingsFile file) throws IOException {
+ public ProjectSettingsFile getModifiedContent(ProjectSettingsFile file) throws IOException {
if (file.getName().equals("org.eclipse.jdt.ui.prefs")) {
- String content = loadContent(file);
- content = content.replace("Copyright the original author or authors",
- "Copyright " + get(COPYRIGHT_YEAR)
- + " the original author or authors");
- return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
- }
- return file.getContent();
- }
-
- private String loadContent(ProjectSettingsFile file) throws IOException {
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(file.getContent()))) {
- return reader.lines().collect(Collectors.joining("\n"));
+ return file.withUpdatedContent(
+ (javaFormatConfig, content) -> content.replace("Copyright the original author or authors",
+ "Copyright " + get(COPYRIGHT_YEAR) + " the original author or authors"));
}
+ return file;
}
String get(String name) {
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFile.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFile.java
index 75ea5790..ec7ef383 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFile.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFile.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,10 +16,18 @@
package io.spring.javaformat.eclipse.projectsettings;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.function.BiFunction;
+
+import io.spring.javaformat.config.JavaFormatConfig;
/**
* A project settings file that can be copied to the project {@code .settings} folder.
@@ -32,7 +40,7 @@ final class ProjectSettingsFile {
private final ContentSupplier contentSupplier;
- private ProjectSettingsFile(String name, ContentSupplier contentSupplier) {
+ ProjectSettingsFile(String name, ContentSupplier contentSupplier) {
this.name = name;
this.contentSupplier = contentSupplier;
}
@@ -48,11 +56,34 @@ public String getName() {
/**
* Return a new {@link InputStream} that can be used to access the content of the
* file.
+ * @param javaFormatConfig the java format config to apply
* @return the file contents
* @throws IOException if the file cannot be opened
*/
- public InputStream getContent() throws IOException {
- return this.contentSupplier.getContent();
+ public InputStream getContent(JavaFormatConfig javaFormatConfig) throws IOException {
+ return this.contentSupplier.getContent(javaFormatConfig);
+ }
+
+ /**
+ * Return a new {@link ProjectSettingsFile} where the original content is updated by
+ * the given operation.
+ * @param operation the operation to update the content
+ * @return a new {@link ProjectSettingsFile} instance
+ */
+ public ProjectSettingsFile withUpdatedContent(BiFunction operation) {
+ return new ProjectSettingsFile(this.name, (javaFormatConfig) -> {
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(this.contentSupplier.getContent(javaFormatConfig)))) {
+ StringWriter writer = new StringWriter();
+ char[] buffer = new char[4096];
+ int read = 0;
+ while ((read = reader.read(buffer)) >= 0) {
+ writer.write(buffer, 0, read);
+ }
+ String content = operation.apply(javaFormatConfig, writer.toString());
+ return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
+ }
+ });
}
/**
@@ -61,7 +92,7 @@ public InputStream getContent() throws IOException {
* @return a new {@link ProjectSettingsFile}
*/
public static ProjectSettingsFile fromFile(File file) {
- return new ProjectSettingsFile(file.getName(), () -> new FileInputStream(file));
+ return new ProjectSettingsFile(file.getName(), (javaFormatConfig) -> new FileInputStream(file));
}
/**
@@ -71,13 +102,13 @@ public static ProjectSettingsFile fromFile(File file) {
* @return a new {@link ProjectSettingsFile}
*/
public static ProjectSettingsFile fromClasspath(Class> sourceClass, String name) {
- return new ProjectSettingsFile(name, () -> sourceClass.getResourceAsStream(name));
+ return new ProjectSettingsFile(name, (javaFormatConfig) -> sourceClass.getResourceAsStream(name));
}
@FunctionalInterface
- private interface ContentSupplier {
+ interface ContentSupplier {
- InputStream getContent() throws IOException;
+ InputStream getContent(JavaFormatConfig javaFormatConfig) throws IOException;
}
diff --git a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFiles.java b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFiles.java
index 9338fa54..2b40f5ae 100644
--- a/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFiles.java
+++ b/spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFiles.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -17,18 +17,32 @@
package io.spring.javaformat.eclipse.projectsettings;
import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import io.spring.javaformat.config.JavaFormatConfig;
+
/**
* A collection of {@link ProjectSettingsFile project setting files}.
*
@@ -45,8 +59,7 @@ public class ProjectSettingsFiles implements Iterable {
* @param files the project settings files
* @param projectProperties project properties
*/
- public ProjectSettingsFiles(Collection files,
- ProjectProperties projectProperties) {
+ public ProjectSettingsFiles(Collection files, ProjectProperties projectProperties) {
this.files = new ArrayList<>(files);
this.projectProperties = projectProperties;
}
@@ -63,21 +76,73 @@ public Iterator iterator() {
* @throws IOException on IO error
* @throws CoreException on eclipse file creation failure
*/
- public void applyToProject(IProject project, IProgressMonitor monitor)
- throws IOException, CoreException {
+ public void applyToProject(IProject project, IProgressMonitor monitor) throws IOException, CoreException {
+ JavaFormatConfig javaFormatConfig = getJavaFormatConfig(project);
for (ProjectSettingsFile file : this) {
+ file = this.projectProperties.getModifiedContent(file);
IFile destination = project.getFile(".settings/" + file.getName());
- if (destination.exists()) {
- try {
- destination.delete(true, monitor);
+ try (InputStream content = file.getContent(javaFormatConfig)) {
+ if (!destination.exists()) {
+ destination.create(new BufferedInputStream(content), true, monitor);
}
- catch (CoreException ex) {
+ else {
+ Properties properties = new OrderedProperties();
+ try (InputStream existingContent = destination.getContents(true)) {
+ if (existingContent != null) {
+ properties.load(existingContent);
+ }
+ }
+ properties.load(content);
+ destination.setContents(
+ new ByteArrayInputStream(stripTimestamp(properties).getBytes(StandardCharsets.UTF_8)),
+ IResource.FORCE, monitor);
}
}
- try (InputStream content = this.projectProperties.getModifiedContent(file)) {
- destination.create(new BufferedInputStream(content), true, monitor);
- }
}
}
+ private String stripTimestamp(Properties properties) throws IOException {
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ properties.store(output, null);
+ String string = output.toString(StandardCharsets.UTF_8);
+ String separator = System.getProperty("line.separator");
+ return string.substring(string.indexOf(separator) + separator.length());
+ }
+ }
+
+ private JavaFormatConfig getJavaFormatConfig(IProject project) {
+ try {
+ IPath location = project.getLocation();
+ File file = (location != null) ? location.toFile() : null;
+ return JavaFormatConfig.findFrom(file);
+ }
+ catch (Exception ex) {
+ return JavaFormatConfig.DEFAULT;
+ }
+ }
+
+ static class OrderedProperties extends Properties {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Set> entrySet() {
+ Set> set = new TreeSet>(new MapEntryKeyComparator());
+ set.addAll(super.entrySet());
+ return set;
+ };
+
+ }
+
+ private static class MapEntryKeyComparator implements Comparator> {
+
+ @Override
+ public int compare(Entryspring-javaformat-gradle-plugin
+ io.spring.javaformat.gradle.plugin
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/build.gradle
index 062d9ec7..e088814b 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/build.gradle
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/build.gradle
@@ -1,5 +1,5 @@
plugins {
- id 'java'
+ id 'java-gradle-plugin'
id 'eclipse'
}
@@ -8,11 +8,9 @@ repositories {
}
dependencies {
- compile localGroovy()
- compile gradleApi()
- compile fileTree(dir: 'target/dependencies/compile', include: '*.jar')
- testCompile gradleTestKit()
- testCompile fileTree(dir: 'target/dependencies/test', include: '*.jar')
+ implementation fileTree(dir: 'target/dependencies/compile', include: '*.jar')
+ testImplementation gradleTestKit()
+ testImplementation fileTree(dir: 'target/dependencies/test', include: '*.jar')
}
jar {
@@ -22,11 +20,15 @@ jar {
}
test {
+ useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
eclipseJdt {
inputFile = rootProject.file('../../.eclipse/org.eclipse.jdt.core.prefs')
doLast {
@@ -59,4 +61,10 @@ artifacts {
archives javadocJar
}
-
+tasks.withType(JavaCompile) {
+ options.compilerArgs.add("-Werror")
+ options.compilerArgs.add("-Xlint:deprecation")
+ options.compilerArgs.add("-Xlint:rawtypes")
+ options.compilerArgs.add("-Xlint:unchecked")
+ options.compilerArgs.add("-Xlint:varargs")
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.jar b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.jar
index 91ca28c8..e708b1c0 100644
Binary files a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.jar and b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
index 16d28051..070cb702 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew
index cccdd3d5..22cf4de8 100755
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
+#
+# Copyright 2015-2023 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.
+#
+
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
- i=$((i+1))
+ i=`expr $i + 1`
done
case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
exec "$JAVACMD" "$@"
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew.bat b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew.bat
index e95643d6..18a320c0 100755
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew.bat
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015-2023 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
index 41381e09..3170b015 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/pom.xml
@@ -1,12 +1,12 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-gradle
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-gradle-pluginpom
@@ -32,6 +32,7 @@
falsecompile
+ true${project.build.directory}/dependencies/compile
@@ -111,19 +112,14 @@
io.spring.javaformat
- spring-javaformat-formatter
+ spring-javaformat-formatter-shaded${project.version}
+
io.spring.javaformat
- spring-javaformat-formatter-eclipse-runtime
+ spring-javaformat-checkstyle${project.version}
-
-
- *
- *
-
-
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatterTask.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatterTask.java
deleted file mode 100644
index 3388fe46..00000000
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatterTask.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.javaformat.gradle;
-
-import java.nio.charset.Charset;
-import java.util.stream.Stream;
-
-import io.spring.javaformat.formatter.FileEdit;
-import io.spring.javaformat.formatter.FileFormatter;
-import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.Optional;
-import org.gradle.api.tasks.SourceTask;
-
-/**
- * Abstract base class for formatter tasks.
- *
- * @author Phillip Webb
- */
-abstract class FormatterTask extends SourceTask {
-
- private String encoding;
-
- /**
- * Get the file encoding in use.
- * @return the encoding the file encoding
- */
- @Input
- @Optional
- public String getEncoding() {
- return this.encoding;
- }
-
- /**
- * Set the file encoding in use.
- * @param encoding the encoding to set
- */
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
-
- /**
- * Format the source files and provide a {@link Stream} of {@link FileEdit} instances.
- * @return the file edits
- */
- protected final Stream formatFiles() {
- FileFormatter formatter = new FileFormatter();
- Charset encoding = (getEncoding() != null ? Charset.forName(getEncoding())
- : Charset.defaultCharset());
- return formatter.formatFiles(getSource().getFiles(), encoding);
- }
-
-}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatExtension.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatExtension.java
new file mode 100644
index 00000000..2f173b99
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatExtension.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2017-present 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.gradle;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.inject.Inject;
+
+import org.gradle.api.Action;
+import org.gradle.api.Project;
+import org.gradle.api.plugins.quality.CheckstyleExtension;
+import org.gradle.api.provider.Property;
+import org.gradle.api.resources.TextResource;
+
+/**
+ * DSL extension for Spring Java Format.
+ *
+ * @author Andy Wilkinson
+ */
+public abstract class SpringJavaFormatExtension {
+
+ private final Checkstyle checkstyle;
+
+ @Inject
+ public SpringJavaFormatExtension(Project project) {
+ this.checkstyle = project.getObjects().newInstance(Checkstyle.class, project);
+ this.checkstyle.getConfigureDependencies().convention(true);
+ }
+
+ public Checkstyle getCheckstyle() {
+ return this.checkstyle;
+ }
+
+ public void checkstyle(Action action) {
+ action.execute(this.checkstyle);
+ }
+
+ public abstract static class Checkstyle {
+
+ private final Project project;
+
+ @Inject
+ public Checkstyle(Project project) {
+ this.project = project;
+ }
+
+ /**
+ * Property that controls whether Checkstyle's dependencies should be configured to
+ * use Spring Java Format's checks.
+ * @return the property
+ */
+ public abstract Property getConfigureDependencies();
+
+ /**
+ * Applies Spring Java Format's default Checkstyle config, enabling all Spring checks.
+ * @see CheckstyleExtension#setConfig(TextResource)
+ */
+ public void applyDefaultConfig() {
+ CheckstyleExtension extension = this.project.getExtensions().getByType(CheckstyleExtension.class);
+ StringWriter defaultConfig = new StringWriter();
+ PrintWriter writer = new PrintWriter(defaultConfig);
+ writer.println("");
+ writer.println("");
+ writer.println("");
+ writer.println(" ");
+ writer.println(" ");
+ writer.println("");
+ extension.setConfig(this.project.getResources().getText().fromString(defaultConfig.toString()));
+ }
+
+ }
+
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
index 98f802d0..4dc2f423 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,17 +16,34 @@
package io.spring.javaformat.gradle;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.plugins.JavaBasePlugin;
-import org.gradle.api.plugins.JavaPluginConvention;
+import org.gradle.api.plugins.JavaPluginExtension;
+import org.gradle.api.plugins.quality.CheckstyleExtension;
+import org.gradle.api.plugins.quality.CheckstylePlugin;
import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskContainer;
+import org.gradle.api.tasks.TaskProvider;
+
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.Formatter;
+import io.spring.javaformat.gradle.tasks.CheckFormat;
+import io.spring.javaformat.gradle.tasks.Format;
+import io.spring.javaformat.gradle.tasks.FormatterTask;
/**
* Spring Format Gradle Plugin.
*
* @author Phillip Webb
+ * @author Andy Wilkinson
*/
public class SpringJavaFormatPlugin implements Plugin {
@@ -36,39 +53,90 @@ public class SpringJavaFormatPlugin implements Plugin {
public void apply(Project project) {
this.project = project;
addSourceTasks();
+ SpringJavaFormatExtension extension = registerExtension();
+ new CheckstyleConfigurer(project, extension).apply();
+ }
+
+ private SpringJavaFormatExtension registerExtension() {
+ SpringJavaFormatExtension extension = this.project.getExtensions().create("springJavaFormat", SpringJavaFormatExtension.class);
+ return extension;
}
private void addSourceTasks() {
this.project.getPlugins().withType(JavaBasePlugin.class, (plugin) -> {
- Task formatAll = this.project.task(FormatTask.NAME);
- formatAll.setDescription(FormatTask.DESCRIPTION);
- Task checkAll = this.project.task(CheckTask.NAME);
- checkAll.setDescription(CheckTask.DESCRIPTION);
- this.project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME)
- .dependsOn(checkAll);
- this.project.getConvention().getPlugin(JavaPluginConvention.class)
- .getSourceSets()
- .all((sourceSet) -> addSourceTasks(sourceSet, checkAll, formatAll));
+ TaskContainer tasks = this.project.getTasks();
+ TaskProvider formatAllProvider = tasks.register(Format.NAME);
+ formatAllProvider.configure((formatAll) -> formatAll.setDescription(Format.DESCRIPTION));
+ TaskProvider checkAllProvider = tasks.register(CheckFormat.NAME);
+ checkAllProvider.configure((checkAll) -> checkAll.setDescription(CheckFormat.DESCRIPTION));
+ tasks.named(JavaBasePlugin.CHECK_TASK_NAME).configure((check) -> check.dependsOn(checkAllProvider));
+ this.project.getExtensions()
+ .getByType(JavaPluginExtension.class)
+ .getSourceSets()
+ .all((sourceSet) -> addSourceTasks(sourceSet, checkAllProvider, formatAllProvider));
});
}
- private void addSourceTasks(SourceSet sourceSet, Task checkAll, Task formatAll) {
- CheckTask checkTask = addSourceTask(sourceSet, CheckTask.class, CheckTask.NAME,
- CheckTask.DESCRIPTION);
- checkAll.dependsOn(checkTask);
- FormatTask formatSourceSet = addSourceTask(sourceSet, FormatTask.class,
- FormatTask.NAME, FormatTask.DESCRIPTION);
- formatSourceSet.conventionMapping("encoding", () -> "UTF-8");
- formatAll.dependsOn(formatSourceSet);
+ private void addSourceTasks(SourceSet sourceSet, TaskProvider checkAllProvider,
+ TaskProvider formatAllProvider) {
+ TaskProvider checkTaskProvider = addFormatterTask(sourceSet, CheckFormat.class, CheckFormat.NAME,
+ CheckFormat.DESCRIPTION);
+ checkTaskProvider.configure((checkTask) -> checkTask.setReportLocation(
+ new File(this.project.getBuildDir(), "reports/format/" + sourceSet.getName() + "/check-format.txt")));
+ checkAllProvider.configure((checkAll) -> checkAll.dependsOn(checkTaskProvider));
+ TaskProvider formatTaskProvider = addFormatterTask(sourceSet, Format.class, Format.NAME,
+ Format.DESCRIPTION);
+ formatTaskProvider.configure((format) -> format.conventionMapping("encoding", () -> "UTF-8"));
+ formatAllProvider.configure((formatAll) -> formatAll.dependsOn(formatTaskProvider));
}
- private T addSourceTask(SourceSet sourceSet,
- Class taskType, String name, String desc) {
+ private TaskProvider addFormatterTask(SourceSet sourceSet, Class taskType,
+ String name, String desc) {
String taskName = sourceSet.getTaskName(name, null);
- T task = this.project.getTasks().create(taskName, taskType);
- task.setDescription(desc + " for " + sourceSet.getName());
- task.setSource(sourceSet.getAllJava());
- return task;
+ TaskProvider provider = this.project.getTasks().register(taskName, taskType);
+ provider.configure((task) -> {
+ task.setDescription(desc + " for " + sourceSet.getName());
+ task.setSource(sourceSet.getAllJava());
+ JavaFormatConfig config = JavaFormatConfig.findFrom(this.project.getProjectDir());
+ task.getIndentationStyle().convention(config.getIndentationStyle());
+ task.getJavaBaseline().convention(config.getJavaBaseline());
+ });
+ return provider;
+ }
+
+ private static final class CheckstyleConfigurer {
+
+ private final Project project;
+
+ private final SpringJavaFormatExtension extension;
+
+ private CheckstyleConfigurer(Project project, SpringJavaFormatExtension extension) {
+ this.project = project;
+ this.extension = extension;
+ }
+
+ private void apply() {
+ this.project.getPlugins().withType(CheckstylePlugin.class).configureEach((checkstylePlugin) -> {
+ CheckstyleExtension checkstyle = this.project.getExtensions().getByType(CheckstyleExtension.class);
+ DependencySet checkstyleDependencies = this.project.getConfigurations().getByName("checkstyle").getDependencies();
+ checkstyleDependencies.addAllLater(this.project.provider(() -> checkstyleDependencies(checkstyle)));
+ });
+ }
+
+ private List checkstyleDependencies(CheckstyleExtension checkstyle) {
+ List dependencies = new ArrayList<>();
+ if (configuringCheckstyleDependencies()) {
+ dependencies.add(this.project.getDependencies().create("com.puppycrawl.tools:checkstyle:" + checkstyle.getToolVersion()));
+ dependencies.add(this.project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:"
+ + Formatter.class.getPackage().getImplementationVersion()));
+ }
+ return dependencies;
+ }
+
+ private boolean configuringCheckstyleDependencies() {
+ return Boolean.TRUE.equals(this.extension.getCheckstyle().getConfigureDependencies().get());
+ }
+
}
}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/CheckTask.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
similarity index 50%
rename from spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/CheckTask.java
rename to spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
index 34817517..d6504edf 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/CheckTask.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/CheckFormat.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,23 +14,30 @@
* limitations under the License.
*/
-package io.spring.javaformat.gradle;
+package io.spring.javaformat.gradle.tasks;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-import io.spring.javaformat.formatter.FileEdit;
-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;
/**
* {@link FormatterTask} to check formatting.
*
* @author Phillip Webb
*/
-public class CheckTask extends FormatterTask {
+@CacheableTask
+public class CheckFormat extends FormatterTask {
/**
* The name of the task.
@@ -42,17 +49,34 @@ public class CheckTask extends FormatterTask {
*/
public static final String DESCRIPTION = "Run Spring Java formatting checks";
+ private File reportLocation;
+
@TaskAction
public void checkFormatting() throws IOException, InterruptedException {
List problems = formatFiles().filter(FileEdit::hasEdits)
- .map(FileEdit::getFile).collect(Collectors.toList());
+ .map(FileEdit::getFile)
+ .collect(Collectors.toList());
+ this.reportLocation.getParentFile().mkdirs();
if (!problems.isEmpty()) {
- StringBuilder message = new StringBuilder(
- "Formatting violations found in the following files:\n");
- problems.stream().forEach((f) -> message.append(" * " + f + "\n"));
+ StringBuilder message = new StringBuilder("Formatting violations found in the following files:\n");
+ problems.stream().forEach((f) -> message.append(" * " + getProject().relativePath(f) + "\n"));
message.append("\nRun `format` to fix.");
- throw new GradleException(message.toString());
+ Files.write(this.reportLocation.toPath(), Collections.singletonList(message.toString()),
+ StandardOpenOption.CREATE);
+ throw new VerificationException(message.toString());
+ }
+ else {
+ this.reportLocation.createNewFile();
}
}
+ @OutputFile
+ public File getReportLocation() {
+ return this.reportLocation;
+ }
+
+ public void setReportLocation(File reportLocation) {
+ this.reportLocation = reportLocation;
+ }
+
}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatTask.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
similarity index 78%
rename from spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatTask.java
rename to spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
index 038289d9..b1f6b312 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/FormatTask.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,21 +14,24 @@
* limitations under the License.
*/
-package io.spring.javaformat.gradle;
+package io.spring.javaformat.gradle.tasks;
import java.io.IOException;
-import io.spring.javaformat.formatter.FileEdit;
-import io.spring.javaformat.formatter.FileFormatterException;
import org.gradle.api.GradleException;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.OutputFiles;
import org.gradle.api.tasks.TaskAction;
+import io.spring.javaformat.formatter.FileEdit;
+import io.spring.javaformat.formatter.FileFormatterException;
+
/**
* {@link FormatterTask} to apply formatting.
*
* @author Phillip Webb
*/
-public class FormatTask extends FormatterTask {
+public class Format extends FormatterTask {
/**
* The name of the task.
@@ -50,4 +53,9 @@ public void format() throws IOException, InterruptedException {
}
}
+ @OutputFiles
+ public FileTree getOutputFiles() {
+ return super.getSource();
+ }
+
}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java
new file mode 100644
index 00000000..b99ded44
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017-present 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.gradle.tasks;
+
+import java.nio.charset.Charset;
+import java.util.stream.Stream;
+
+import org.gradle.api.file.FileTree;
+import org.gradle.api.provider.Property;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Optional;
+import org.gradle.api.tasks.PathSensitive;
+import org.gradle.api.tasks.PathSensitivity;
+import org.gradle.api.tasks.SourceTask;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.FileEdit;
+import io.spring.javaformat.formatter.FileFormatter;
+
+/**
+ * Abstract base class for formatter tasks.
+ *
+ * @author Phillip Webb
+ */
+public abstract class FormatterTask extends SourceTask {
+
+ private String encoding;
+
+ private final Property indentationStyle;
+
+ private final Property javaBaseline;
+
+ FormatterTask() {
+ this.indentationStyle = getProject().getObjects().property(IndentationStyle.class);
+ this.javaBaseline = getProject().getObjects().property(JavaBaseline.class);
+ }
+
+ /**
+ * Get the file encoding in use.
+ * @return the encoding the file encoding
+ */
+ @Input
+ @Optional
+ public String getEncoding() {
+ return this.encoding;
+ }
+
+ /**
+ * Set the file encoding in use.
+ * @param encoding the encoding to set
+ */
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ /**
+ * The indentation style used for formatting.
+ * @return the indentation style
+ */
+ @Input
+ public Property getIndentationStyle() {
+ return this.indentationStyle;
+ }
+
+ /**
+ * The Java baseline used for formatting.
+ * @return the Java baseline
+ */
+ @Input
+ public Property getJavaBaseline() {
+ return this.javaBaseline;
+ }
+
+ @Override
+ @InputFiles
+ @PathSensitive(PathSensitivity.RELATIVE)
+ public FileTree getSource() {
+ return super.getSource();
+ }
+
+ /**
+ * Format the source files and provide a {@link Stream} of {@link FileEdit} instances.
+ * @return the file edits
+ */
+ protected final Stream formatFiles() {
+ JavaFormatConfig javaFormatConfig = JavaFormatConfig.of(this.javaBaseline.get(), this.indentationStyle.get());
+ FileFormatter formatter = new FileFormatter(javaFormatConfig);
+ Charset encoding = (getEncoding() != null ? Charset.forName(getEncoding()) : Charset.defaultCharset());
+ return formatter.formatFiles(getSource().getFiles(), encoding);
+ }
+
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckTaskTests.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckTaskTests.java
index 0d7a1949..3f413277 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckTaskTests.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckTaskTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,40 +16,136 @@
package io.spring.javaformat.gradle;
+import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
+import java.util.stream.Stream;
-import io.spring.javaformat.gradle.testkit.GradleBuild;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+
+import io.spring.javaformat.gradle.tasks.CheckFormat;
+import io.spring.javaformat.gradle.testkit.GradleBuild;
+import io.spring.javaformat.gradle.testkit.GradleBuildExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link CheckTask}.
+ * Tests for {@link CheckFormat}.
*
* @author Phillip Webb
*/
+@ExtendWith(GradleBuildExtension.class)
public class CheckTaskTests {
- @Rule
- public final GradleBuild gradleBuild = new GradleBuild();
+ private final GradleBuild gradleBuild = new GradleBuild();
+
+ @TempDir
+ public File temp;
+
+ @Test
+ void checkOk() throws IOException {
+ BuildResult result = this.gradleBuild.source("src/test/resources/check-ok").build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ }
+
+ @Test
+ void whenFirstInvocationSucceedsThenSecondInvocationIsUpToDate() throws IOException {
+ GradleBuild gradleBuild = this.gradleBuild.source("src/test/resources/check-ok");
+ BuildResult result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+ }
+
+ @Test
+ void whenFirstInvocationSucceedsAndSourceIsModifiedThenSecondInvocationSucceeds() throws IOException {
+ copyNormalizedFolder(new File("src/test/resources/check-ok").toPath(), this.temp.toPath());
+ GradleBuild gradleBuild = this.gradleBuild.source(this.temp);
+ BuildResult result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ Files.write(new File(this.temp, "src/main/java/simple/Simple.java").toPath(),
+ "// A change to the file\n".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
+ result = gradleBuild.build("--debug", "check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ }
+
+ @Test
+ void whenFirstInvocationSucceedsAndIndentationStyleIsChangedThenSecondInvocationFails() throws IOException {
+ GradleBuild gradleBuild = this.gradleBuild.source("src/test/resources/check-ok");
+ BuildResult result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ Files.write(new File(this.gradleBuild.getProjectDir(), ".springjavaformatconfig").toPath(),
+ Arrays.asList("indentation-style=spaces"));
+ result = gradleBuild.buildAndFail("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.FAILED);
+ }
+
+ @Test
+ void whenFirstInvocationFailsAndIndentationStyleIsChangedThenSecondInvocationSucceeds() throws IOException {
+ GradleBuild gradleBuild = this.gradleBuild.source("src/test/resources/check-spaces");
+ BuildResult result = gradleBuild.buildAndFail("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.FAILED);
+ Files.write(new File(this.gradleBuild.getProjectDir(), ".springjavaformatconfig").toPath(),
+ Arrays.asList("indentation-style=spaces"));
+ result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ }
+
+ @Test
+ void whenFirstInvocationSucceedsAndJavaBaselineIsChangedThenSecondInvocationSucceedsAndThirdIsUpToDate()
+ throws IOException {
+ GradleBuild gradleBuild = this.gradleBuild.source("src/test/resources/check-ok");
+ BuildResult result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ Files.write(new File(this.gradleBuild.getProjectDir(), ".springjavaformatconfig").toPath(),
+ Arrays.asList("java-baseline=8"));
+ result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ result = gradleBuild.build("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+ }
@Test
- public void checkOk() throws IOException {
- BuildResult result = this.gradleBuild.source("src/test/resources/check-ok")
- .build("check");
- assertThat(result.task(":checkFormatMain").getOutcome())
- .isEqualTo(TaskOutcome.SUCCESS);
+ void checkBad() throws IOException {
+ BuildResult result = this.gradleBuild.source("src/test/resources/check-bad").buildAndFail("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.FAILED);
}
@Test
- public void checkBad() throws IOException {
- BuildResult result = this.gradleBuild.source("src/test/resources/check-bad")
- .buildAndFail("check");
- assertThat(result.task(":checkFormatMain").getOutcome())
- .isEqualTo(TaskOutcome.FAILED);
+ void whenFirstInvocationFailsThenSecondInvocationFails() throws IOException {
+ GradleBuild gradleBuild = this.gradleBuild.source("src/test/resources/check-bad");
+ BuildResult result = gradleBuild.buildAndFail("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.FAILED);
+ result = gradleBuild.buildAndFail("check");
+ assertThat(result.task(":checkFormatMain").getOutcome()).isEqualTo(TaskOutcome.FAILED);
+ }
+
+ private void copyNormalizedFolder(Path source, Path target) throws IOException {
+ try (Stream stream = Files.walk(source)) {
+ stream.forEach((child) -> {
+ try {
+ Path relative = source.relativize(child);
+ Path destination = target.resolve(relative);
+ if (!Files.isDirectory(child)) {
+ String content = new String(Files.readAllBytes(child), StandardCharsets.UTF_8);
+ String normalized = content.replace("\n\r", "\n").replace('\r', '\n');
+ Files.createDirectories(destination.getParent());
+ Files.write(destination, normalized.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ });
+ }
}
}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckstyleTests.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckstyleTests.java
new file mode 100644
index 00000000..8995edad
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/CheckstyleTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017-present 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.gradle;
+
+import org.gradle.testkit.runner.BuildResult;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import io.spring.javaformat.gradle.testkit.GradleBuild;
+import io.spring.javaformat.gradle.testkit.GradleBuildExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@ExtendWith(GradleBuildExtension.class)
+class CheckstyleTests {
+
+ private final GradleBuild gradleBuild = new GradleBuild();
+
+ @Test
+ void configureCheckstyle() {
+ BuildResult result = this.gradleBuild.source("src/test/resources/checkstyle-configure").build("checkstyleDependencies");
+ assertThat(result.getOutput()).contains("io.spring.javaformat:spring-javaformat-checkstyle:");
+ assertThat(result.getOutput()).contains("com.puppycrawl.tools:checkstyle:8.45.1");
+ }
+
+ @Test
+ void configureCheckstyleWithCustomToolVersion() {
+ BuildResult result = this.gradleBuild.source("src/test/resources/checkstyle-configure-with-custom-tool-version").build("checkstyleDependencies");
+ assertThat(result.getOutput()).contains("io.spring.javaformat:spring-javaformat-checkstyle:");
+ assertThat(result.getOutput()).contains("com.puppycrawl.tools:checkstyle:10.26.1");
+ }
+
+ @Test
+ void doNotConfigureCheckstyle() {
+ BuildResult result = this.gradleBuild.source("src/test/resources/checkstyle-do-not-configure").build("checkstyleDependencies");
+ assertThat(result.getOutput()).doesNotContain("spring-javaformat-checkstyle");
+ }
+
+ @Test
+ void applyDefaultConfigToCheckstyle() {
+ BuildResult result = this.gradleBuild.source("src/test/resources/checkstyle-apply-default-config").build("checkstyleConfig");
+ assertThat(result.getOutput()).contains("");
+ }
+
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
index dc752dc0..e3d29e16 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -19,35 +19,85 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.util.Arrays;
-import io.spring.javaformat.gradle.testkit.GradleBuild;
import org.gradle.testkit.runner.BuildResult;
+import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.TaskOutcome;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import io.spring.javaformat.gradle.tasks.Format;
+import io.spring.javaformat.gradle.testkit.GradleBuild;
+import io.spring.javaformat.gradle.testkit.GradleBuildExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link FormatTask}.
+ * Tests for {@link Format}.
*
* @author Phillip Webb
*/
+@ExtendWith(GradleBuildExtension.class)
public class FormatTaskTests {
- @Rule
- public final GradleBuild gradleBuild = new GradleBuild();
+ private final GradleBuild gradleBuild = new GradleBuild();
+
+ @Test
+ void checkOk() throws IOException {
+ BuildResult result = this.gradleBuild.source("src/test/resources/format").build("format");
+ assertThat(result.task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ File formattedFile = new File(this.gradleBuild.getProjectDir(), "src/main/java/simple/Simple.java");
+ String formattedContent = new String(Files.readAllBytes(formattedFile.toPath()));
+ assertThat(formattedContent).contains("class Simple {").contains(" public static void main");
+ }
+
+ @Test
+ void checkUpToDate() throws IOException {
+ GradleRunner runner = this.gradleBuild.source("src/test/resources/format").prepareRunner("format");
+ // Format that changes files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Format of already formatted files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Up-to-date
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+ }
+
+ @Test
+ void notUpToDateWhenJavaBaselineChanges() throws IOException {
+ GradleRunner runner = this.gradleBuild.source("src/test/resources/format").prepareRunner("format");
+ // Format that changes files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Format of already formatted files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Up-to-date
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+ Files.write(new File(this.gradleBuild.getProjectDir(), ".springjavaformatconfig").toPath(),
+ Arrays.asList("java-baseline=8"));
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ }
+
+ @Test
+ void notUpToDateWhenIndentationStyleChanges() throws IOException {
+ GradleRunner runner = this.gradleBuild.source("src/test/resources/format").prepareRunner("format");
+ // Format that changes files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Format of already formatted files
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ // Up-to-date
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+ Files.write(new File(this.gradleBuild.getProjectDir(), ".springjavaformatconfig").toPath(),
+ Arrays.asList("indentation-style=spaces"));
+ assertThat(runner.build().task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ }
@Test
- public void checkOk() throws IOException {
- BuildResult result = this.gradleBuild.source("src/test/resources/format")
- .build("format");
- assertThat(result.task(":formatMain").getOutcome())
- .isEqualTo(TaskOutcome.SUCCESS);
- File formattedFile = new File(this.gradleBuild.getProjectDir(),
- "src/main/java/simple/Simple.java");
+ void checkSpacesOk() throws IOException {
+ BuildResult result = this.gradleBuild.source("src/test/resources/format-spaces").build("format");
+ assertThat(result.task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+ File formattedFile = new File(this.gradleBuild.getProjectDir(), "src/main/java/simple/Simple.java");
String formattedContent = new String(Files.readAllBytes(formattedFile.toPath()));
- assertThat(formattedContent).contains("class Simple {");
+ assertThat(formattedContent).contains("class Simple {").contains(" public static void main");
}
}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuild.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuild.java
index 3403ddb4..1414da78 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuild.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuild.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -19,11 +19,13 @@
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
@@ -31,27 +33,23 @@
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
-import io.spring.javaformat.formatter.Formatter;
-import io.spring.javaformat.formatter.eclipse.Preparator;
-import org.eclipse.jdt.core.formatter.CodeFormatter;
-import org.gradle.internal.impldep.com.google.common.base.Charsets;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
-import org.junit.rules.TemporaryFolder;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
+import org.gradle.util.GradleVersion;
import org.xml.sax.InputSource;
+import io.spring.javaformat.formatter.Formatter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
/**
- * A {@link TestRule} for running a Gradle build using {@link GradleRunner}.
+ * A {@code GradleBuild} is used to run a Gradle build using {@link GradleRunner}.
*
* @author Andy Wilkinson
+ * @author Scott Frederick
* @author Phillip Webb
*/
-public class GradleBuild implements TestRule {
-
- private final TemporaryFolder temp = new TemporaryFolder();
+public class GradleBuild {
private File source;
@@ -59,46 +57,15 @@ public class GradleBuild implements TestRule {
private String gradleVersion;
- @Override
- public Statement apply(Statement base, Description description) {
- return this.temp.apply(new Statement() {
-
- @Override
- public void evaluate() throws Throwable {
- before();
- try {
- base.evaluate();
- }
- finally {
- after();
- }
- }
-
- }, description);
- }
+ private GradleVersion expectDeprecationWarnings;
- private void before() throws IOException {
- this.projectDir = this.temp.newFolder();
+ void before() throws IOException {
+ this.projectDir = Files.createTempDirectory("gradle-").toFile();
}
- private void after() {
- GradleBuild.this.source = null;
- }
-
- private String getPluginClasspath() {
- return absolutePath("build/classes/java/main") + ","
- + absolutePath("build/resources/main") + ","
- + pathOfJarContaining(Formatter.class) + ","
- + pathOfJarContaining(Preparator.class) + ","
- + pathOfJarContaining(CodeFormatter.class);
- }
-
- private String absolutePath(String path) {
- return new File(path).getAbsolutePath();
- }
-
- private String pathOfJarContaining(Class> type) {
- return type.getProtectionDomain().getCodeSource().getLocation().getPath();
+ void after() throws IOException {
+ this.source = null;
+ Files.walk(this.projectDir.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
public GradleBuild source(String source) {
@@ -115,7 +82,12 @@ public GradleBuild source(File source) {
public BuildResult build(String... arguments) {
try {
- return prepareRunner(arguments).build();
+ BuildResult result = prepareRunner(arguments).build();
+ if (this.expectDeprecationWarnings == null || (this.gradleVersion != null
+ && this.expectDeprecationWarnings.compareTo(GradleVersion.version(this.gradleVersion)) > 0)) {
+ assertThat(result.getOutput()).doesNotContain("Deprecated").doesNotContain("deprecated");
+ }
+ return result;
}
catch (Exception ex) {
throw new RuntimeException(ex);
@@ -134,11 +106,10 @@ public BuildResult buildAndFail(String... arguments) {
public GradleRunner prepareRunner(String... arguments) throws IOException {
copyFolder(this.source.getAbsoluteFile().toPath(), this.projectDir.toPath());
File buildFile = new File(this.projectDir, "build.gradle");
- String scriptContent = new String(Files.readAllBytes(buildFile.toPath()))
- .replace("{version}", getSpringFormatVersion());
- Files.write(buildFile.toPath(), scriptContent.getBytes(Charsets.UTF_8));
- GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir)
- .withDebug(true);
+ String scriptContent = new String(Files.readAllBytes(buildFile.toPath())).replace("{version}",
+ getSpringFormatVersion());
+ Files.write(buildFile.toPath(), scriptContent.getBytes(StandardCharsets.UTF_8));
+ GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir).withDebug(true);
if (this.gradleVersion != null) {
gradleRunner.withGradleVersion(this.gradleVersion);
}
@@ -150,13 +121,28 @@ public GradleRunner prepareRunner(String... arguments) throws IOException {
return gradleRunner.withArguments(allArguments);
}
+ private String getPluginClasspath() {
+ return absolutePath("build/classes/java/main") + "," + absolutePath("build/resources/main") + ","
+ + pathOfJarContaining(Formatter.class);
+ }
+
+ private String absolutePath(String path) {
+ return new File(path).getAbsolutePath();
+ }
+
+ private String pathOfJarContaining(Class> type) {
+ return type.getProtectionDomain().getCodeSource().getLocation().getPath();
+ }
+
private void copyFolder(Path source, Path target) throws IOException {
try (Stream stream = Files.walk(source)) {
stream.forEach((child) -> {
try {
Path relative = source.relativize(child);
Path destination = target.resolve(relative);
- Files.copy(child, destination, StandardCopyOption.REPLACE_EXISTING);
+ if (!destination.toFile().isDirectory()) {
+ Files.copy(child, destination, StandardCopyOption.REPLACE_EXISTING);
+ }
}
catch (Exception ex) {
throw new IllegalStateException(ex);
@@ -184,8 +170,7 @@ public String getGradleVersion() {
private String getSpringFormatVersion() {
return evaluateExpression(
- "/*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']"
- + "/text()");
+ "/*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']" + "/text()");
}
private String evaluateExpression(String expression) {
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuildExtension.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuildExtension.java
new file mode 100644
index 00000000..bb5b8a6d
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/testkit/GradleBuildExtension.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present 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.gradle.testkit;
+
+import java.lang.reflect.Field;
+
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.Extension;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+/**
+ * An {@link Extension} for managing the lifecycle of a {@link GradleBuild} stored in a
+ * field named {@code gradleBuild}.
+ *
+ * @author Andy Wilkinson
+ * @author Scott Frederick
+ * @author Phillip Webb
+ */
+public class GradleBuildExtension implements BeforeEachCallback, AfterEachCallback {
+
+ @Override
+ public void beforeEach(ExtensionContext context) throws Exception {
+ extractGradleBuild(context).before();
+ }
+
+ @Override
+ public void afterEach(ExtensionContext context) throws Exception {
+ extractGradleBuild(context).after();
+ }
+
+ private GradleBuild extractGradleBuild(ExtensionContext context) throws Exception {
+ Object testInstance = context.getRequiredTestInstance();
+ Field gradleBuildField = testInstance.getClass().getDeclaredField("gradleBuild");
+ gradleBuildField.setAccessible(true);
+ GradleBuild gradleBuild = (GradleBuild) gradleBuildField.get(testInstance);
+ return gradleBuild;
+ }
+
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-ok/src/main/java/simple/package-info.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-ok/src/main/java/simple/package-info.java
new file mode 100644
index 00000000..35b32be0
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-ok/src/main/java/simple/package-info.java
@@ -0,0 +1 @@
+package simple;
\ No newline at end of file
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/build.gradle
new file mode 100644
index 00000000..d6ca2f32
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/build.gradle
@@ -0,0 +1,10 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/src/main/java/simple/Simple.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..cd5523a6
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/check-spaces/src/main/java/simple/Simple.java
@@ -0,0 +1,15 @@
+package simple;
+
+/**
+ * Simple indented with spaces.
+ *
+ * @author Andy Wilkinson
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-apply-default-config/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-apply-default-config/build.gradle
new file mode 100644
index 00000000..302352be
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-apply-default-config/build.gradle
@@ -0,0 +1,27 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'checkstyle'
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
+
+repositories {
+ mavenCentral()
+}
+
+springJavaFormat {
+ checkstyle {
+ applyDefaultConfig()
+ }
+}
+
+tasks.register("checkstyleConfig") {
+ doFirst {
+ println checkstyle.config.asString()
+ }
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure-with-custom-tool-version/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure-with-custom-tool-version/build.gradle
new file mode 100644
index 00000000..cc42d068
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure-with-custom-tool-version/build.gradle
@@ -0,0 +1,25 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'checkstyle'
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
+
+repositories {
+ mavenCentral()
+}
+
+checkstyle {
+ toolVersion = "10.26.1"
+}
+
+tasks.register("checkstyleDependencies") {
+ doFirst {
+ configurations.checkstyle.dependencies.each { println "${it.group}:${it.name}:${it.version}" }
+ }
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure/build.gradle
new file mode 100644
index 00000000..08207b88
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-configure/build.gradle
@@ -0,0 +1,21 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'checkstyle'
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
+
+repositories {
+ mavenCentral()
+}
+
+tasks.register("checkstyleDependencies") {
+ doFirst {
+ configurations.checkstyle.dependencies.each { println "${it.group}:${it.name}:${it.version}" }
+ }
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-do-not-configure/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-do-not-configure/build.gradle
new file mode 100644
index 00000000..561ffa61
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/checkstyle-do-not-configure/build.gradle
@@ -0,0 +1,23 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'checkstyle'
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
+
+springJavaFormat {
+ checkstyle {
+ configureDependencies = false
+ }
+}
+
+tasks.register("checkstyleDependencies") {
+ doFirst {
+ configurations.checkstyle.dependencies.each { println "${it.group}:${it.name}:${it.version}" }
+ }
+}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/.springjavaformatconfig b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/.springjavaformatconfig
new file mode 100644
index 00000000..881903b2
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/.springjavaformatconfig
@@ -0,0 +1 @@
+indentation-style=spaces
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/build.gradle b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/build.gradle
new file mode 100644
index 00000000..d6ca2f32
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/build.gradle
@@ -0,0 +1,10 @@
+buildscript {
+ dependencies {
+ classpath files(pluginClasspath.split(','))
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'io.spring.javaformat'
+
+sourceCompatibility = 1.8
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/src/main/java/simple/Simple.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..83b618ce
--- /dev/null
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/resources/format-spaces/src/main/java/simple/Simple.java
@@ -0,0 +1,15 @@
+package simple;
+
+/**
+ * Simple.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-intellij/pom.xml b/spring-javaformat-intellij-idea/pom.xml
similarity index 67%
rename from spring-javaformat-intellij/pom.xml
rename to spring-javaformat-intellij-idea/pom.xml
index c05c2a24..9de7cec6 100644
--- a/spring-javaformat-intellij/pom.xml
+++ b/spring-javaformat-intellij-idea/pom.xml
@@ -1,15 +1,15 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-build
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOT
- spring-javaformat-intellij
+ spring-javaformat-intellij-ideapom
- Spring JavaFormat IntelliJ
+ Spring JavaFormat IntelliJ IDEA${basedir}/..
@@ -30,7 +30,7 @@
- spring-javaformat-intellij-runtime
- spring-javaformat-intellij-plugin
+ spring-javaformat-intellij-idea-runtime
+ spring-javaformat-intellij-idea-plugin
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/pom.xml b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
similarity index 54%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/pom.xml
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
index f3ceee80..7915af9f 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/pom.xml
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/pom.xml
@@ -1,24 +1,21 @@
-
+4.0.0io.spring.javaformat
- spring-javaformat-intellij
- 0.0.7-SNAPSHOT
+ spring-javaformat-intellij-idea
+ 0.0.48-SNAPSHOT
- spring-javaformat-intellij-plugin
- Spring JavaFormat IntelliJ Plugin
+ spring-javaformat-intellij-idea-plugin
+ Spring JavaFormat IntelliJ IDEA Plugin${basedir}/../..
+ 17
-
- io.spring.javaformat
- spring-javaformat-formatter
- ${project.version}
- io.spring.javaformatspring-javaformat-formatter-eclipse-runtime
@@ -30,64 +27,75 @@
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ ${project.version}
+ io.spring.javaformat
- spring-javaformat-intellij-runtime
+ spring-javaformat-intellij-idea-runtime${project.version}pomprovided
- io.spring.javaformat.intellij
- extensions
+ org.jetbrains
+ annotations
+ 13.0
+ provided
+
+
+ io.spring.javaformat.intellij.idea
+ app${project.version}provided
- io.spring.javaformat.intellij
- platform-api
+ io.spring.javaformat.intellij.idea
+ jps-model${project.version}provided
- io.spring.javaformat.intellij
+ io.spring.javaformat.intellij.ideautil${project.version}provided
- io.spring.javaformat.intellij
- idea
+ io.spring.javaformat.intellij.idea
+ util_rt${project.version}provided
- io.spring.javaformat.intellij
+ io.spring.javaformat.intellij.ideamaven${project.version}provided
- io.spring.javaformat.intellij
- maven-server-api
+ io.spring.javaformat.intellij.idea
+ maven-server${project.version}provided
- io.spring.javaformat.intellij
+ io.spring.javaformat.intellij.ideagradle${project.version}provided
- io.spring.javaformat.intellij
+ io.spring.javaformat.intellij.ideagradle-tooling-extension-api${project.version}provided
- io.spring.javaformat.intellij
+ io.spring.javaformat.intellij.ideagradle-tooling-extension-impl${project.version}provided
@@ -102,9 +110,45 @@
picocontainerprovided
+
+ org.jetbrains.kotlinx
+ kotlinx-coroutines-core
+ 1.6.4
+ provided
+
+
+ it.unimi.dsi
+ fastutil
+ 8.5.11
+ provided
+
+
+
+ ${basedir}/src/main/resources
+ true
+
+ META-INF/plugin.xml
+
+
+
+ ${basedir}/src/main/resources
+
+ META-INF/plugin.xml
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+ 11
+ false
+ -Xdoclint:none
+
+ org.apache.maven.pluginsmaven-shade-plugin
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapter.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapter.java
similarity index 85%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapter.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapter.java
index 5363413f..255a72f1 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapter.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle;
+package io.spring.format.formatter.intellij.formatting;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
@@ -35,8 +35,7 @@ class EclipseDocumentAdapter extends Document {
}
@Override
- public void replace(int pos, int length, String text, long modificationStamp)
- throws BadLocationException {
+ public void replace(int pos, int length, String text, long modificationStamp) throws BadLocationException {
super.replace(pos, length, text, modificationStamp);
this.intellijDocument.replaceString(pos, pos + length, text);
}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapter.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapter.java
similarity index 76%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapter.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapter.java
index 53428476..1b1fdc9e 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapter.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle;
+package io.spring.format.formatter.intellij.formatting;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import com.intellij.openapi.util.TextRange;
@@ -29,15 +28,15 @@
*
* @author Phillip Webb
*/
-public class EclipseRegionAdapter extends Region {
+class EclipseRegionAdapter extends Region {
private static final IRegion[] NO_REGIONS = {};
- public EclipseRegionAdapter(TextRange range) {
+ EclipseRegionAdapter(TextRange range) {
super(range.getStartOffset(), range.getLength());
}
- public static IRegion[] asArray(Collection extends TextRange> ranges) {
+ static IRegion[] asArray(List ranges) {
if (ranges == null) {
return NO_REGIONS;
}
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingService.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingService.java
new file mode 100644
index 00000000..70bb51e9
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017-present 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.format.formatter.intellij.formatting;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+import com.intellij.formatting.FormattingContext;
+import com.intellij.formatting.service.AbstractDocumentFormattingService;
+import com.intellij.formatting.service.FormattingService;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.text.edits.TextEdit;
+import org.jetbrains.annotations.NotNull;
+
+import io.spring.format.formatter.intellij.state.State;
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.Formatter;
+
+/**
+ * {@link FormattingService} to apply Spring formatting conventions.
+ *
+ * @author Phillip Webb
+ */
+public class SpringJavaFormatFormattingService extends AbstractDocumentFormattingService {
+
+ private static final String NORMALIZED_LINE_SEPARATOR = "\n";
+
+ private static final Set FEATURES = Set.of(Feature.FORMAT_FRAGMENTS);
+
+ private static final FileType JAVA_FILE_TYPE = FileTypeManager.getInstance().getStdFileType("JAVA");
+
+ private final BiConsumer runAction;
+
+ public SpringJavaFormatFormattingService() {
+ this(WriteCommandAction::runWriteCommandAction);
+ }
+
+ SpringJavaFormatFormattingService(BiConsumer runAction) {
+ this.runAction = runAction;
+ }
+
+ @Override
+ public @NotNull Set getFeatures() {
+ return FEATURES;
+ }
+
+ @Override
+ public boolean canFormat(@NotNull PsiFile file) {
+ return JAVA_FILE_TYPE.equals(file.getFileType()) && State.get(file.getProject()) == State.ACTIVE;
+ }
+
+ @Override
+ public void formatDocument(@NotNull Document document, @NotNull List formattingRanges,
+ @NotNull FormattingContext formattingContext, boolean canChangeWhiteSpaceOnly, boolean quickFormat) {
+ VirtualFile file = formattingContext.getVirtualFile();
+ Path path = (file != null) ? file.getFileSystem().getNioPath(file) : null;
+ JavaFormatConfig config = JavaFormatConfig.findFrom(path);
+ Formatter formatter = new Formatter(config);
+ String source = document.getText();
+ formattingRanges = (!formattingRanges.isEmpty()) ? formattingRanges : List.of(TextRange.allOf(source));
+ IRegion[] regions = EclipseRegionAdapter.asArray(formattingRanges);
+ TextEdit edit = formatter.format(source, regions, NORMALIZED_LINE_SEPARATOR);
+ applyEdit(formattingContext.getProject(), document, edit);
+ }
+
+ private void applyEdit(Project project, Document document, TextEdit textEdit) {
+ this.runAction.accept(project, () -> {
+ try {
+ IDocument adapted = new EclipseDocumentAdapter(document);
+ textEdit.apply(adapted);
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ });
+ }
+
+}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/FileMonitor.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/FileMonitor.java
similarity index 81%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/FileMonitor.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/FileMonitor.java
index 372b8742..84128c15 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/FileMonitor.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/FileMonitor.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -23,16 +23,17 @@
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileMoveEvent;
import com.intellij.openapi.vfs.VirtualFilePropertyEvent;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
+
+import io.spring.format.formatter.intellij.state.State;
/**
- * {@link Monitor} that looks for a {@literal .springformat} file.
+ * {@link Monitor} that looks for a {@literal .springjavaformatconfig} file.
*
* @author Phillip Webb
*/
public class FileMonitor extends Monitor {
- private static final String TRIGGER_FILE = ".springformat";
+ private static final String TRIGGER_FILE = ".springjavaformatconfig";
private final VirtualFileManager fileManager;
@@ -55,8 +56,7 @@ public void stop() {
private void check() {
VirtualFile baseDir = getProject().getBaseDir();
- VirtualFile triggerFile = (baseDir == null ? null
- : baseDir.findChild(TRIGGER_FILE));
+ VirtualFile triggerFile = (baseDir == null ? null : baseDir.findChild(TRIGGER_FILE));
State currentState = (triggerFile == null ? State.NOT_ACTIVE : State.ACTIVE);
if (!currentState.equals(this.state)) {
getTrigger().updateState(currentState);
@@ -65,8 +65,7 @@ private void check() {
}
public static Factory factory() {
- return (project, trigger) -> new FileMonitor(project, trigger,
- VirtualFileManager.getInstance());
+ return (project, trigger) -> new FileMonitor(project, trigger, VirtualFileManager.getInstance());
}
/**
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/GradleMonitor.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/GradleMonitor.java
similarity index 71%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/GradleMonitor.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/GradleMonitor.java
index 050596af..8a41e441 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/GradleMonitor.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/GradleMonitor.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
import java.util.Collection;
-import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.task.TaskData;
@@ -26,9 +26,11 @@
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener;
import com.intellij.openapi.project.Project;
import com.intellij.util.messages.MessageBusConnection;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
+import io.spring.format.formatter.intellij.state.State;
+
/**
* {@link Monitor} that looks for a {@code spring-javaformat-gradle-plugin} declaration in
* the build.gradle file.
@@ -37,25 +39,35 @@
*/
public class GradleMonitor extends Monitor {
- private static final String FORMAT_TASK = "io.spring.javaformat.gradle.FormatTask";
+ private static final Logger logger = Logger.getInstance(GradleMonitor.class);
+
+ private static final String FORMAT_TASK = "io.spring.javaformat.gradle.tasks.Format";
public GradleMonitor(Project project, Trigger trigger) {
super(project, trigger);
MessageBusConnection messageBus = project.getMessageBus().connect();
- messageBus.subscribe(ProjectDataImportListener.TOPIC, (path) -> check());
+ messageBus.subscribe(ProjectDataImportListener.TOPIC, new ProjectDataImportListener() {
+
+ @Override
+ public void onImportFinished(@Nullable String projectPath) {
+ check();
+ }
+
+ });
}
private void check() {
- ProjectDataManager projectDataManager = ServiceManager
- .getService(ProjectDataManager.class);
- boolean hasFormatPlugin = hasFormatPlugin(projectDataManager
- .getExternalProjectsData(getProject(), GradleConstants.SYSTEM_ID));
+ logger.info("Checking " + getProject().getName() + " for use of Spring Java Format");
+ ProjectDataManager projectDataManager = ProjectDataManager.getInstance();
+ boolean hasFormatPlugin = hasFormatPlugin(
+ projectDataManager.getExternalProjectsData(getProject(), GradleConstants.SYSTEM_ID));
getTrigger().updateState(hasFormatPlugin ? State.ACTIVE : State.NOT_ACTIVE);
}
private boolean hasFormatPlugin(Collection projectInfos) {
for (ExternalProjectInfo projectInfo : projectInfos) {
if (hasFormatPlugin(projectInfo.getExternalProjectStructure())) {
+ logger.info(projectInfo + " uses Spring Java Format");
return true;
}
}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/MavenMonitor.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/MavenMonitor.java
similarity index 78%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/MavenMonitor.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/MavenMonitor.java
index bf358518..6ddb20e8 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/MavenMonitor.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/MavenMonitor.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,19 +14,20 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
import java.util.List;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectChanges;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.MavenProjectsTree.Listener;
import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
+import io.spring.format.formatter.intellij.state.State;
+
/**
* {@link Monitor} that looks for a {@code spring-javaformat-maven-plugin} declaration in
* the POM.xml file.
@@ -41,8 +42,7 @@ public class MavenMonitor extends Monitor {
private final MavenProjectsManager mavenProjectsManager;
- public MavenMonitor(Project project, Trigger trigger,
- MavenProjectsManager mavenProjectsManager) {
+ public MavenMonitor(Project project, Trigger trigger, MavenProjectsManager mavenProjectsManager) {
super(project, trigger);
this.mavenProjectsManager = mavenProjectsManager;
attachListener(mavenProjectsManager);
@@ -53,15 +53,13 @@ private void attachListener(MavenProjectsManager mavenProjectsManager) {
mavenProjectsManager.addProjectsTreeListener(new Listener() {
@Override
- public void projectsUpdated(
- List> updated,
+ public void projectsUpdated(List> updated,
List deleted) {
check();
}
@Override
- public void projectResolved(
- Pair projectWithChanges,
+ public void projectResolved(Pair projectWithChanges,
NativeMavenProjectHolder nativeMavenProject) {
check();
}
@@ -94,10 +92,8 @@ private boolean hasSpringFormatPlugin(List projects) {
public static Factory factory() {
return (project, trigger) -> {
- MavenProjectsManager mavenProjectsManager = MavenProjectsManager
- .getInstance(project);
- return (mavenProjectsManager == null ? null
- : new MavenMonitor(project, trigger, mavenProjectsManager));
+ MavenProjectsManager mavenProjectsManager = MavenProjectsManager.getInstance(project);
+ return (mavenProjectsManager == null ? null : new MavenMonitor(project, trigger, mavenProjectsManager));
};
}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitor.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitor.java
similarity index 90%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitor.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitor.java
index 527e6a75..d0663c86 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitor.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitor.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
import com.intellij.openapi.project.Project;
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitors.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitors.java
similarity index 86%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitors.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitors.java
index 4faf26d0..cfe8dc4a 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Monitors.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Monitors.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -23,7 +23,8 @@
import java.util.function.Consumer;
import com.intellij.openapi.project.Project;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
+
+import io.spring.format.formatter.intellij.state.State;
/**
* Utility class used to manage a collection of {@link Monitors}. Creates and manages
@@ -46,8 +47,7 @@ public class Monitors {
* @param stateChangeConsumer consumer called whenever the ultimate state changes
* @param monitorFactories factories used to create the monitors
*/
- public Monitors(Project project, Consumer stateChangeConsumer,
- Monitor.Factory... monitorFactories) {
+ public Monitors(Project project, Consumer stateChangeConsumer, Monitor.Factory... monitorFactories) {
this(project, stateChangeConsumer, Arrays.asList(monitorFactories));
}
@@ -57,8 +57,7 @@ public Monitors(Project project, Consumer stateChangeConsumer,
* @param stateChangeConsumer consumer called whenever the ultimate state changes
* @param monitorFactories factories used to create the monitors
*/
- public Monitors(Project project, Consumer stateChangeConsumer,
- List monitorFactories) {
+ public Monitors(Project project, Consumer stateChangeConsumer, List monitorFactories) {
this.stateChangeConsumer = stateChangeConsumer;
List monitors = new ArrayList<>(monitorFactories.size());
for (Monitor.Factory factory : monitorFactories) {
@@ -81,8 +80,7 @@ private Trigger addTrigger() {
activeAfter = containsActiveState(this.states);
}
if (activeBefore != activeAfter) {
- this.stateChangeConsumer
- .accept(activeAfter ? State.ACTIVE : State.NOT_ACTIVE);
+ this.stateChangeConsumer.accept(activeAfter ? State.ACTIVE : State.NOT_ACTIVE);
}
};
}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Trigger.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Trigger.java
similarity index 69%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Trigger.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Trigger.java
index ab68bc0b..f1c7d223 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/monitor/Trigger.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/monitor/Trigger.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle.monitor;
+package io.spring.format.formatter.intellij.monitor;
+
+import io.spring.format.formatter.intellij.state.State;
/**
* Trigger used to to update the state for this monitor. Triggers are thread safe and can
@@ -30,21 +32,4 @@ public interface Trigger {
*/
void updateState(State state);
- /**
- * The desired state of the plugin for this monitor.
- */
- enum State {
-
- /**
- * The plugin should be active.
- */
- ACTIVE,
-
- /**
- * The plugin need not be active.
- */
- NOT_ACTIVE
-
- }
-
}
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/ManagedSpringJavaFormatProject.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/ManagedSpringJavaFormatProject.java
new file mode 100644
index 00000000..2b87dd56
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/ManagedSpringJavaFormatProject.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017-present 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.format.formatter.intellij.startup;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+
+import io.spring.format.formatter.intellij.monitor.FileMonitor;
+import io.spring.format.formatter.intellij.monitor.GradleMonitor;
+import io.spring.format.formatter.intellij.monitor.MavenMonitor;
+import io.spring.format.formatter.intellij.monitor.Monitors;
+import io.spring.format.formatter.intellij.state.State;
+import io.spring.format.formatter.intellij.ui.StatusIndicator;
+
+/**
+ * Spring Java Format IntelliJ support added to a {@link Project}.
+ *
+ * @author Phillip Webb
+ */
+class ManagedSpringJavaFormatProject {
+
+ private static final String ACTIVE_PROPERTY = ManagedSpringJavaFormatProject.class.getName() + ".ACTIVE";
+
+ private static final Logger logger = Logger.getInstance(ManagedSpringJavaFormatProject.class);
+
+ private final Project project;
+
+ private final StatusIndicator statusIndicator;
+
+ private final Lock lock = new ReentrantLock();
+
+ private Monitors monitors;
+
+ private PropertiesComponent properties;
+
+ protected ManagedSpringJavaFormatProject(Project project) {
+ logger.info("Initializing Spring Format for project " + project.getName());
+ this.project = project;
+ this.statusIndicator = new StatusIndicator(project);
+ this.properties = PropertiesComponent.getInstance(project);
+ if (this.properties.getBoolean(ACTIVE_PROPERTY, false)) {
+ update(State.ACTIVE);
+ }
+ this.monitors = new Monitors(this.project, this::update, FileMonitor.factory(), MavenMonitor.factory(),
+ GradleMonitor.factory());
+ Disposer.register(project, this::dispose);
+ }
+
+ private void dispose() {
+ if (this.monitors != null) {
+ logger.info("Stopping monitors for " + this.project.getName());
+ this.monitors.stop();
+ this.monitors = null;
+ }
+ }
+
+ private void update(State state) {
+ logger.info("Updating state of " + this.project.getName() + " to " + state);
+ this.lock.lock();
+ try {
+ state.put(this.project);
+ ApplicationManager.getApplication().invokeLater(() -> this.statusIndicator.update(state));
+ }
+ finally {
+ this.lock.unlock();
+ }
+ }
+
+}
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/SpringJavaFormatStartupActivity.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/SpringJavaFormatStartupActivity.java
new file mode 100644
index 00000000..f11e345c
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/startup/SpringJavaFormatStartupActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present 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.format.formatter.intellij.startup;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.startup.StartupActivity;
+
+/**
+ * {@link StartupActivity} hook for {@link ManagedSpringJavaFormatProject}.
+ *
+ * @author Phillip Webb
+ */
+public class SpringJavaFormatStartupActivity implements StartupActivity {
+
+ @Override
+ public void runActivity(Project project) {
+ new ManagedSpringJavaFormatProject(project);
+ }
+
+}
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/state/State.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/state/State.java
new file mode 100644
index 00000000..6d8fe7c1
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/state/State.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017-present 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.format.formatter.intellij.state;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+
+/**
+ * The state of the plugin.
+ *
+ * @author Phillip Webb
+ */
+public enum State {
+
+ /**
+ * The plugin is active.
+ */
+ ACTIVE,
+
+ /**
+ * The plugin is not active.
+ */
+ NOT_ACTIVE;
+
+ private static final Key KEY = Key.create(State.class.getName());
+
+ /**
+ * Put this state to the given project.
+ * @param project the project that should save the state
+ */
+ public void put(Project project) {
+ project.putUserData(KEY, this);
+ }
+
+ /**
+ * Return the state from the given project.
+ * @param project the project to check
+ * @return the state of the project
+ */
+ public static State get(Project project) {
+ State state = (project != null) ? project.getUserData(KEY) : null;
+ return (state != null) ? state : NOT_ACTIVE;
+ }
+
+}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/StatusIndicator.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/ui/StatusIndicator.java
similarity index 63%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/StatusIndicator.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/ui/StatusIndicator.java
index c6b53547..935b738e 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/StatusIndicator.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/java/io/spring/format/formatter/intellij/ui/StatusIndicator.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,43 +14,44 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij;
+package io.spring.format.formatter.intellij.ui;
import java.awt.event.MouseEvent;
+import java.util.concurrent.TimeUnit;
import javax.swing.Icon;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
-import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.openapi.wm.WindowManager;
-import com.intellij.openapi.wm.WindowManagerListener;
import com.intellij.util.Consumer;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
+import com.intellij.util.concurrency.AppExecutorUtil;
+
+import io.spring.format.formatter.intellij.state.State;
/**
* Indicator used to show when Spring Formatting is active.
*
* @author Phillip Webb
*/
-class StatusIndicator {
+public class StatusIndicator {
private final Project project;
private Widget widget;
- StatusIndicator(Project project) {
+ public StatusIndicator(Project project) {
this.project = project;
}
public void update(State state) {
WindowManager windowManager = WindowManager.getInstance();
- final StatusBar statusBar = windowManager.getStatusBar(this.project);
+ StatusBar statusBar = windowManager.getStatusBar(this.project);
if (statusBar == null) {
- windowManager.addListener(new UpdateOnFrameCreateListener(state));
+ AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> retryUpdate(state), 1, TimeUnit.SECONDS);
return;
}
if (state == State.ACTIVE) {
@@ -61,6 +62,10 @@ public void update(State state) {
}
}
+ private void retryUpdate(State state) {
+ ApplicationManager.getApplication().invokeLater(() -> update(state));
+ }
+
private void show(StatusBar statusBar) {
if (this.widget == null) {
this.widget = new Widget();
@@ -75,38 +80,12 @@ private void hide(final StatusBar statusBar) {
}
}
- /**
- * {@link WindowManagerListener} used to defer setting the status if the IDE frame
- * isn't available.
- */
- private class UpdateOnFrameCreateListener implements WindowManagerListener {
-
- private final State state;
-
- UpdateOnFrameCreateListener(State state) {
- this.state = state;
- }
-
- @Override
- public void frameCreated(IdeFrame frame) {
- WindowManager.getInstance().removeListener(this);
- ApplicationManager.getApplication().invokeLater(() -> update(this.state));
- }
-
- @Override
- public void beforeFrameReleased(IdeFrame frame) {
- }
-
- }
-
/**
* The {@link StatusBarWidget} component for the status.
*/
- private static class Widget
- implements StatusBarWidget, StatusBarWidget.IconPresentation {
+ private static class Widget implements StatusBarWidget, StatusBarWidget.IconPresentation {
- public static final Icon ICON = IconLoader
- .getIcon("/spring-javaformat/formatOn.png");
+ public static final Icon ICON = IconLoader.getIcon("/spring-javaformat/formatOn.png");
@Override
public String ID() {
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/META-INF/plugin.xml b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/META-INF/plugin.xml
new file mode 100644
index 00000000..21c74b0f
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/META-INF/plugin.xml
@@ -0,0 +1,15 @@
+
+ spring-javaformat
+ Spring Javaformat
+ A source formatter that applies wrapping and whitespace conventions to
+ provide a consistent “Spring” style.
+
+ ${project.version}
+ Spring Team
+ org.jetbrains.idea.maven
+ org.jetbrains.plugins.gradle
+
+
+
+
+
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/spring-javaformat/formatOn.png b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/spring-javaformat/formatOn.png
similarity index 100%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/spring-javaformat/formatOn.png
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/main/resources/spring-javaformat/formatOn.png
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapterTests.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapterTests.java
similarity index 79%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapterTests.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapterTests.java
index 9d9cb1b6..4fe90665 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseDocumentAdapterTests.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseDocumentAdapterTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle;
+package io.spring.format.formatter.intellij.formatting;
import com.intellij.openapi.editor.Document;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@@ -29,10 +29,10 @@
*
* @author Phillip Webb
*/
-public class EclipseDocumentAdapterTests {
+class EclipseDocumentAdapterTests {
@Test
- public void createShouldUseDocumentText() throws Exception {
+ void createUsesDocumentText() throws Exception {
Document intellijDocument = mock(Document.class);
given(intellijDocument.getText()).willReturn("hello");
EclipseDocumentAdapter adapter = new EclipseDocumentAdapter(intellijDocument);
@@ -40,7 +40,7 @@ public void createShouldUseDocumentText() throws Exception {
}
@Test
- public void replaceShouldApplyToIntellijDocument() throws Exception {
+ void replaceAppliesToIntellijDocument() throws Exception {
Document intellijDocument = mock(Document.class);
given(intellijDocument.getText()).willReturn("hello");
EclipseDocumentAdapter adapter = new EclipseDocumentAdapter(intellijDocument);
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapterTests.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapterTests.java
similarity index 73%
rename from spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapterTests.java
rename to spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapterTests.java
index a56ebaaa..f4c2d2a4 100644
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/EclipseRegionAdapterTests.java
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/EclipseRegionAdapterTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package io.spring.format.formatter.intellij.codestyle;
+package io.spring.format.formatter.intellij.formatting;
import java.util.Arrays;
import java.util.List;
import com.intellij.openapi.util.TextRange;
import org.eclipse.jface.text.IRegion;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,27 +33,26 @@
public class EclipseRegionAdapterTests {
@Test
- public void getOffsetShouldReturnStartOffset() throws Exception {
+ void getOffsetReturnsStartOffset() throws Exception {
IRegion region = new EclipseRegionAdapter(new TextRange(10, 20));
assertThat(region.getOffset()).isEqualTo(10);
}
@Test
- public void getLengthShouldReturnLength() throws Exception {
+ void getLengthReturnsLength() throws Exception {
IRegion region = new EclipseRegionAdapter(new TextRange(10, 20));
assertThat(region.getLength()).isEqualTo(10);
}
@Test
- public void asArrayWhenCollectionIsNullShouldReturnEmptyArray() throws Exception {
+ void asArrayWhenCollectionIsNullReturnsEmptyArray() throws Exception {
IRegion[] regions = EclipseRegionAdapter.asArray(null);
assertThat(regions).isNotNull().isEmpty();
}
@Test
- public void asArrayShouldReturnArray() throws Exception {
- List ranges = Arrays.asList(new TextRange(10, 20),
- new TextRange(30, 35));
+ void asArrayReturnsArray() throws Exception {
+ List ranges = Arrays.asList(new TextRange(10, 20), new TextRange(30, 35));
IRegion[] regions = EclipseRegionAdapter.asArray(ranges);
assertThat(regions).hasSize(2);
assertThat(regions[0].getOffset()).isEqualTo(10);
diff --git a/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingServiceTests.java b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingServiceTests.java
new file mode 100644
index 00000000..6524e10d
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-plugin/src/test/java/io/spring/format/formatter/intellij/formatting/SpringJavaFormatFormattingServiceTests.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017-present 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.format.formatter.intellij.formatting;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+
+import com.intellij.formatting.FormattingContext;
+import com.intellij.formatting.service.FormattingService.Feature;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.local.CoreLocalFileSystem;
+import com.intellij.openapi.vfs.local.CoreLocalVirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.LightVirtualFile;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import io.spring.format.formatter.intellij.state.State;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.willAnswer;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link SpringJavaFormatFormattingService}.
+ *
+ * @author Phillip Webb
+ */
+class SpringJavaFormatFormattingServiceTests {
+
+ private SpringJavaFormatFormattingService service = new SpringJavaFormatFormattingService(
+ (project, runnable) -> runnable.run());
+
+ @Test
+ void getFeaturesReturnsFormatFragments() {
+ assertThat(this.service.getFeatures()).containsExactly(Feature.FORMAT_FRAGMENTS);
+ }
+
+ @Test
+ void canFormatWhenNotJavaReturnsFalse() {
+ FileType fileType = PlainTextFileType.INSTANCE;
+ PsiFile file = mockFile(fileType, State.ACTIVE);
+ assertThat(this.service.canFormat(file)).isFalse();
+ }
+
+ @Test
+ void canFormatWhenJavaFileAndNotActiveReturnsFalse() {
+ FileType fileType = FileTypeManager.getInstance().getStdFileType("JAVA");
+ PsiFile file = mockFile(fileType, State.NOT_ACTIVE);
+ assertThat(this.service.canFormat(file)).isFalse();
+ }
+
+ @Test
+ void canFormatWhenJavaFileAndActiveReturnsTrue() {
+ FileType fileType = FileTypeManager.getInstance().getStdFileType("JAVA");
+ PsiFile file = mockFile(fileType, State.ACTIVE);
+ assertThat(this.service.canFormat(file)).isTrue();
+ }
+
+ @Test
+ void formatDocumentAppliesFormatting(@TempDir Path projectDir) throws Exception {
+ Files.writeString(projectDir.resolve(".springjavaformatconfig"), "indentation-style=spaces");
+ Document document = mockDocument("public class Hello{"
+ + "\tpublic void hello() {"
+ + "\tString value =\t\"Hello World\";}}");
+ FormattingContext formattingContext = mock(FormattingContext.class);
+ VirtualFile virtualFile = new CoreLocalVirtualFile(new CoreLocalFileSystem(), projectDir.resolve("Hello.java"));
+ given(formattingContext.getVirtualFile()).willReturn(virtualFile);
+ this.service.formatDocument(document, Collections.emptyList(), formattingContext, false, false);
+ assertThat(document.getText()).isEqualTo("public class Hello {\n\n"
+ + " public void hello() {\n"
+ + " String value = \"Hello World\";\n"
+ + " }\n\n"
+ + "}");
+ }
+
+ @Test
+ void formatDocumentAppliesFormatting() {
+ Document document = mockDocument("public class Hello{"
+ + "\tpublic void hello() {"
+ + "\tString value =\t\"Hello World\";}}");
+ FormattingContext formattingContext = mock(FormattingContext.class);
+ VirtualFile virtualFile = new LightVirtualFile("Hello.java", document.getText());
+ given(formattingContext.getVirtualFile()).willReturn(virtualFile);
+ this.service.formatDocument(document, Collections.emptyList(), formattingContext, false, false);
+ assertThat(document.getText()).isEqualTo("public class Hello {\n\n"
+ + "\tpublic void hello() {\n"
+ + "\t\tString value = \"Hello World\";\n"
+ + "\t}\n\n"
+ + "}");
+ }
+
+
+ private Document mockDocument(String text) {
+ Document document = mock(Document.class);
+ StringBuilder documentText = new StringBuilder(text);
+ willAnswer((invocation) -> {
+ documentText.replace(invocation.getArgument(0), invocation.getArgument(1), invocation.getArgument(2));
+ return null;
+ }).given(document).replaceString(any(Integer.class), any(Integer.class), any(CharSequence.class));
+ given(document.getText()).willAnswer((invocation) -> documentText.toString());
+ return document;
+ }
+
+ private PsiFile mockFile(FileType fileType, State state) {
+ PsiFile file = mock(PsiFile.class);
+ given(file.getFileType()).willReturn(fileType);
+ Project project = mock(Project.class);
+ given(project.getUserData(any())).willReturn(state);
+ given(file.getProject()).willReturn(project);
+ return file;
+ }
+
+}
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
new file mode 100644
index 00000000..b6202b0d
--- /dev/null
+++ b/spring-javaformat-intellij-idea/spring-javaformat-intellij-idea-runtime/pom.xml
@@ -0,0 +1,301 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat-intellij-idea
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-intellij-idea-runtime
+ pom
+ Spring JavaFormat IntelliJ IDEA Runtime
+
+ ${basedir}/../..
+ https://download.jetbrains.com/idea/ideaIC-2022.3.2.tar.gz
+ https://github.com/JetBrains/intellij-community/archive/idea/223.8617.56.zip
+ ${project.build.directory}/intellij-source
+ idea-IC-223.8617.56
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+ com.googlecode.maven-download-plugin
+ download-maven-plugin
+
+
+ download-intellij-binary
+ validate
+
+ wget
+
+
+ ${intellij.binary}
+ intellij.tar.gz
+
+
+
+ download-intellij-source
+ install
+
+ wget
+
+
+ ${intellij.source}
+ intellij-source.zip
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ prepare-intellij
+ install
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+
+
+ install-intellij-util
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/util.jar
+ ${intellij.source.directory}/util-sources.zip
+ io.spring.javaformat.intellij.idea
+ util
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-util_rt
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/util_rt.jar
+ ${intellij.source.directory}/util_rt-sources.zip
+ io.spring.javaformat.intellij.idea
+ util_rt
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-app
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/app.jar
+ ${intellij.source.directory}/app-sources.zip
+ io.spring.javaformat.intellij.idea
+ app
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-maven
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/maven.jar
+ ${intellij.source.directory}/maven-sources.zip
+ io.spring.javaformat.intellij.idea
+ maven
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-maven-server
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/maven-server.jar
+ ${intellij.source.directory}/maven-server-sources.zip
+ io.spring.javaformat.intellij.idea
+ maven-server
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-gradle
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/gradle.jar
+ ${intellij.source.directory}/gradle-sources.zip
+ io.spring.javaformat.intellij.idea
+ gradle
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-gradle-tooling-extension-api
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/gradle-tooling-extension-api.jar
+ ${intellij.source.directory}/gradle-tooling-extension-api-sources.zip
+ io.spring.javaformat.intellij.idea
+ gradle-tooling-extension-api
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-jps-model
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/jps-model.jar
+ ${intellij.source.directory}/jps-model-sources.zip
+ io.spring.javaformat.intellij.idea
+ jps-model
+ ${project.version}
+ jar
+ true
+
+
+
+ install-intellij-gradle-tooling-extension-impl
+ install
+ false
+
+ install-file
+
+
+ ${project.build.directory}/intellij/gradle-tooling-extension-impl.jar
+ ${intellij.source.directory}/gradle-tooling-extension-impl-sources.zip
+ io.spring.javaformat.intellij.idea
+ gradle-tooling-extension-impl
+ ${project.version}
+ jar
+ true
+
+
+
+
+
+
+
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/SpringFormatComponent.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/SpringFormatComponent.java
deleted file mode 100644
index 3afb96e8..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/SpringFormatComponent.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij;
-
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import com.intellij.designer.designSurface.ScalableComponent;
-import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.AbstractProjectComponent;
-import com.intellij.openapi.components.ProjectComponent;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import io.spring.format.formatter.intellij.codestyle.SpringCodeStyleManager;
-import io.spring.format.formatter.intellij.codestyle.monitor.FileMonitor;
-import io.spring.format.formatter.intellij.codestyle.monitor.GradleMonitor;
-import io.spring.format.formatter.intellij.codestyle.monitor.MavenMonitor;
-import io.spring.format.formatter.intellij.codestyle.monitor.Monitors;
-import io.spring.format.formatter.intellij.codestyle.monitor.Trigger.State;
-import org.picocontainer.MutablePicoContainer;
-
-/**
- * {@link ProjectComponent} to add Spring Java Format IntelliJ support.
- *
- * @author Phillip Webb
- */
-public class SpringFormatComponent extends AbstractProjectComponent {
-
- private static final String CODE_STYLE_MANAGER_KEY = CodeStyleManager.class.getName();
-
- private static final String ACTIVE_PROPERTY = ScalableComponent.class.getName()
- + ".ACTIVE";
-
- private final StatusIndicator statusIndicator;
-
- private final Lock lock = new ReentrantLock();
-
- private Monitors monitors;
-
- private static final Logger logger = Logger.getInstance(SpringFormatComponent.class);
-
- private PropertiesComponent properties;
-
- protected SpringFormatComponent(Project project) {
- super(project);
- this.statusIndicator = new StatusIndicator(project);
- this.properties = PropertiesComponent.getInstance(project);
- }
-
- @Override
- public void initComponent() {
- if (this.properties.getBoolean(ACTIVE_PROPERTY, false)) {
- update(State.ACTIVE);
- }
- this.monitors = new Monitors(this.myProject, this::update, FileMonitor.factory(),
- MavenMonitor.factory(), GradleMonitor.factory());
- }
-
- @Override
- public void disposeComponent() {
- if (this.monitors != null) {
- this.monitors.stop();
- this.monitors = null;
- }
- }
-
- private void update(State state) {
- this.lock.lock();
- try {
- CodeStyleManager manager = CodeStyleManager.getInstance(this.myProject);
- if (manager == null) {
- logger.warn("Unable to find exiting CodeStyleManager");
- return;
- }
- if (state == State.ACTIVE && !(manager instanceof SpringCodeStyleManager)) {
- logger.debug("Enabling SpringCodeStyleManager");
- reregisterComponent(new SpringCodeStyleManager(manager));
- this.properties.setValue(ACTIVE_PROPERTY, true);
- }
- if (state == State.NOT_ACTIVE
- && (manager instanceof SpringCodeStyleManager)) {
- logger.debug("Disabling SpringCodeStyleManager");
- reregisterComponent(((SpringCodeStyleManager) manager).getDelegate());
- this.properties.setValue(ACTIVE_PROPERTY, false);
- }
- ApplicationManager.getApplication()
- .invokeLater(() -> this.statusIndicator.update(state));
- }
- finally {
- this.lock.unlock();
- }
- }
-
- private void reregisterComponent(CodeStyleManager manager) {
- MutablePicoContainer container = (MutablePicoContainer) this.myProject
- .getPicoContainer();
- container.unregisterComponent(CODE_STYLE_MANAGER_KEY);
- container.registerComponentInstance(CODE_STYLE_MANAGER_KEY, manager);
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManager.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManager.java
deleted file mode 100644
index 98035623..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManager.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Collection;
-
-import com.intellij.formatting.FormattingMode;
-import com.intellij.lang.ASTNode;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.ChangedRangesInfo;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.codeStyle.DocCommentSettings;
-import com.intellij.psi.codeStyle.FormattingModeAwareIndentAdjuster;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ThrowableRunnable;
-
-/**
- * {@link CodeStyleManager} implementation that delegates all calls.
- *
- * @author Phillip Webb
- */
-public class DelegatingCodeStyleManager extends CodeStyleManager
- implements FormattingModeAwareIndentAdjuster {
-
- private final CodeStyleManager delegate;
-
- public DelegatingCodeStyleManager(CodeStyleManager delegate) {
- this.delegate = delegate;
- }
-
- public CodeStyleManager getDelegate() {
- return this.delegate;
- }
-
- @Override
- public int getSpacing(PsiFile file, int offset) {
- return this.delegate.getSpacing(file, offset);
- }
-
- @Override
- public int getMinLineFeeds(PsiFile file, int offset) {
- return this.delegate.getMinLineFeeds(file, offset);
- }
-
- @Override
- public void runWithDocCommentFormattingDisabled(PsiFile file, Runnable runnable) {
- this.delegate.runWithDocCommentFormattingDisabled(file, runnable);
- }
-
- @Override
- public DocCommentSettings getDocCommentSettings(PsiFile file) {
- return this.delegate.getDocCommentSettings(file);
- }
-
- @Override
- public Project getProject() {
- return this.delegate.getProject();
- }
-
- @Override
- public PsiElement reformat(PsiElement element) throws IncorrectOperationException {
- return this.delegate.reformat(element);
- }
-
- @Override
- public PsiElement reformat(PsiElement element, boolean canChangeWhiteSpacesOnly)
- throws IncorrectOperationException {
- return this.delegate.reformat(element, canChangeWhiteSpacesOnly);
- }
-
- @Override
- public PsiElement reformatRange(PsiElement element, int startOffset, int endOffset)
- throws IncorrectOperationException {
- return this.delegate.reformatRange(element, startOffset, endOffset);
- }
-
- @Override
- public PsiElement reformatRange(PsiElement element, int startOffset, int endOffset,
- boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException {
- return this.delegate.reformatRange(element, startOffset, endOffset,
- canChangeWhiteSpacesOnly);
- }
-
- @Override
- public void reformatText(PsiFile file, int startOffset, int endOffset)
- throws IncorrectOperationException {
- this.delegate.reformatText(file, startOffset, endOffset);
- }
-
- @Override
- public void reformatText(PsiFile file, Collection ranges)
- throws IncorrectOperationException {
- this.delegate.reformatText(file, ranges);
- }
-
- @Override
- public void reformatTextWithContext(PsiFile file, Collection ranges)
- throws IncorrectOperationException {
- this.delegate.reformatTextWithContext(file, ranges);
- }
-
- @Override
- public void reformatTextWithContext(PsiFile file, ChangedRangesInfo info)
- throws IncorrectOperationException {
- this.delegate.reformatTextWithContext(file, info);
- }
-
- @Override
- public void adjustLineIndent(PsiFile file, TextRange rangeToAdjust)
- throws IncorrectOperationException {
- this.delegate.adjustLineIndent(file, rangeToAdjust);
- }
-
- @Override
- public int adjustLineIndent(PsiFile file, int offset)
- throws IncorrectOperationException {
- return this.delegate.adjustLineIndent(file, offset);
- }
-
- @Override
- public int adjustLineIndent(Document document, int offset) {
- return this.delegate.adjustLineIndent(document, offset);
- }
-
- @Override
- @Deprecated
- public boolean isLineToBeIndented(PsiFile file, int offset) {
- return this.delegate.isLineToBeIndented(file, offset);
- }
-
- @Override
- public String getLineIndent(PsiFile file, int offset) {
- return this.delegate.getLineIndent(file, offset);
- }
-
- @Override
- public String getLineIndent(Document document, int offset) {
- return this.delegate.getLineIndent(document, offset);
- }
-
- @Override
- @Deprecated
- public com.intellij.psi.codeStyle.Indent getIndent(String text, FileType fileType) {
- return this.delegate.getIndent(text, fileType);
- }
-
- @Override
- @Deprecated
- public String fillIndent(com.intellij.psi.codeStyle.Indent indent,
- FileType fileType) {
- return this.delegate.fillIndent(indent, fileType);
- }
-
- @Override
- @Deprecated
- public com.intellij.psi.codeStyle.Indent zeroIndent() {
- return this.delegate.zeroIndent();
- }
-
- @Override
- public void reformatNewlyAddedElement(ASTNode block, ASTNode addedElement)
- throws IncorrectOperationException {
- this.delegate.reformatNewlyAddedElement(block, addedElement);
- }
-
- @Override
- public boolean isSequentialProcessingAllowed() {
- return this.delegate.isSequentialProcessingAllowed();
- }
-
- @Override
- public void performActionWithFormatterDisabled(Runnable r) {
- this.delegate.performActionWithFormatterDisabled(r);
- }
-
- @Override
- public void performActionWithFormatterDisabled(
- ThrowableRunnable r) throws T {
- this.delegate.performActionWithFormatterDisabled(r);
- }
-
- @Override
- public T performActionWithFormatterDisabled(Computable r) {
- return this.delegate.performActionWithFormatterDisabled(r);
- }
-
- @Override
- public int adjustLineIndent(Document document, int offset, FormattingMode mode) {
- if (this.delegate instanceof FormattingModeAwareIndentAdjuster) {
- return ((FormattingModeAwareIndentAdjuster) this.delegate)
- .adjustLineIndent(document, offset, mode);
- }
- return offset;
- }
-
- @Override
- public FormattingMode getCurrentFormattingMode() {
- if (this.delegate instanceof FormattingModeAwareIndentAdjuster) {
- return ((FormattingModeAwareIndentAdjuster) this.delegate)
- .getCurrentFormattingMode();
- }
- return FormattingMode.REFORMAT;
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManager.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManager.java
deleted file mode 100644
index 7b4d0919..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManager.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.function.Supplier;
-
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.util.IncorrectOperationException;
-
-/**
- * {@link CodeStyleManager} to apply Spring Formatting conventions.
- *
- * @author Phillip Webb
- */
-public class SpringCodeStyleManager extends DelegatingCodeStyleManager {
-
- private final SpringReformatter springReformatter;
-
- public SpringCodeStyleManager(CodeStyleManager delegate) {
- super(delegate);
- this.springReformatter = new SpringReformatter(() -> getProject());
- }
-
- SpringCodeStyleManager(CodeStyleManager delegate,
- SpringReformatter springReformatter) {
- super(delegate);
- this.springReformatter = springReformatter;
- }
-
- @Override
- public void reformatText(PsiFile file, int startOffset, int endOffset)
- throws IncorrectOperationException {
- reformat(file, () -> Collections.singleton(new TextRange(startOffset, endOffset)),
- () -> super.reformatText(file, startOffset, endOffset));
- }
-
- @Override
- public void reformatText(PsiFile file, Collection ranges)
- throws IncorrectOperationException {
- reformat(file, () -> ranges, () -> super.reformatText(file, ranges));
- }
-
- @Override
- public void reformatTextWithContext(PsiFile file, Collection ranges)
- throws IncorrectOperationException {
- reformat(file, () -> ranges, () -> super.reformatTextWithContext(file, ranges));
- }
-
- private void reformat(PsiFile file, Supplier> ranges,
- Runnable delegate) {
- if (this.springReformatter.canReformat(file)) {
- this.springReformatter.reformat(file, ranges.get());
- }
- else {
- delegate.run();
- }
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringReformatter.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringReformatter.java
deleted file mode 100644
index cb40baa7..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/java/io/spring/format/formatter/intellij/codestyle/SpringReformatter.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Collection;
-import java.util.function.Supplier;
-
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiBundle;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import io.spring.javaformat.formatter.Formatter;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.text.edits.TextEdit;
-
-/**
- * Reformatter used by {@link SpringCodeStyleManager} to determine when formatting can
- * apply and to perform the actual formatting.
- *
- * @author Phillip Webb
- */
-class SpringReformatter {
-
- private final Supplier project;
-
- private final Supplier application;
-
- private final Supplier documentManager;
-
- SpringReformatter(Supplier project) {
- this.project = project;
- this.application = () -> ApplicationManager.getApplication();
- this.documentManager = () -> PsiDocumentManager.getInstance(project.get());
- }
-
- SpringReformatter(Supplier project, Supplier application,
- Supplier documentManager) {
- this.project = project;
- this.application = application;
- this.documentManager = documentManager;
- }
-
- public boolean canReformat(PsiFile file) {
- return StdFileTypes.JAVA.equals(file.getFileType());
- }
-
- public void reformat(PsiFile file, Collection ranges) {
- this.application.get().assertWriteAccessAllowed();
- this.documentManager.get().commitAllDocuments();
- if (!file.isWritable()) {
- throwNotWritableException(file);
- }
- reformat(file, ranges, this.documentManager.get().getDocument(file));
- }
-
- private void throwNotWritableException(PsiElement element)
- throws IncorrectOperationException {
- if (element instanceof PsiDirectory) {
- String url = ((PsiDirectory) element).getVirtualFile().getPresentableUrl();
- throw new IncorrectOperationException(
- PsiBundle.message("cannot.modify.a.read.only.directory", url));
- }
- PsiFile file = element.getContainingFile();
- if (file == null) {
- throw new IncorrectOperationException();
- }
- VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null) {
- throw new IncorrectOperationException();
- }
- throw new IncorrectOperationException(PsiBundle.message(
- "cannot.modify.a.read.only.file", virtualFile.getPresentableUrl()));
- }
-
- private void reformat(PsiFile file, Collection ranges, Document document) {
- if (document != null) {
- Formatter formatter = new Formatter();
- String source = document.getText();
- IRegion[] regions = EclipseRegionAdapter.asArray(ranges);
- TextEdit edit = formatter.format(source, regions);
- applyEdit(document, edit);
- }
- }
-
- private void applyEdit(Document document, TextEdit textEdit) {
- runWriteCommandAction(() -> {
- try {
- EclipseDocumentAdapter adapter = new EclipseDocumentAdapter(document);
- textEdit.apply(adapter);
- this.documentManager.get().commitDocument(document);
- }
- catch (Exception ex) {
- throw new IllegalStateException(ex);
- }
- });
- }
-
- protected void runWriteCommandAction(Runnable runnable) {
- WriteCommandAction.runWriteCommandAction(this.project.get(), runnable);
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/META-INF/plugin.xml b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/META-INF/plugin.xml
deleted file mode 100644
index 5f8225c8..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/main/resources/META-INF/plugin.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
- spring-javaformat
- spring-javaformat
- 1.0
- Spring
-
-
- org.jetbrains.idea.maven
- org.jetbrains.plugins.gradle
-
-
- io.spring.format.formatter.intellij.SpringFormatComponent
-
-
-
-
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManagerTests.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManagerTests.java
deleted file mode 100644
index 11d03da5..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/DelegatingCodeStyleManagerTests.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.ChangedRangesInfo;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.util.ThrowableRunnable;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-/**
- * Tests for {@link DelegatingCodeStyleManager}.
- *
- * @author Phillip Webb
- */
-public class DelegatingCodeStyleManagerTests {
-
- @Mock
- private CodeStyleManager delegate;
-
- private DelegatingCodeStyleManager delegating;
-
- @Mock
- private PsiElement element;
-
- @Mock
- private PsiFile file;
-
- @Mock
- private TextRange range;
-
- private Collection ranges;
-
- @Mock
- private Document document;
-
- @Mock
- private FileType fileType;
-
- @Mock
- private ASTNode block;
-
- @Mock
- private ASTNode node;
-
- @Mock
- private ChangedRangesInfo changedRangesInfo;
-
- @Before
- @Test
- public void setup() {
- MockitoAnnotations.initMocks(this);
- this.delegating = new DelegatingCodeStyleManager(this.delegate);
- this.ranges = Collections.singleton(mock(TextRange.class));
- }
-
- @Test
- public void getDelegateShouldGetDelegate() throws Exception {
- assertThat(this.delegating.getDelegate()).isEqualTo(this.delegate);
- }
-
- @Test
- public void getProjectShouldCallDelegate() throws Exception {
- this.delegating.getProject();
- verify(this.delegate).getProject();
- }
-
- @Test
- public void reformatShouldCallDelegate() throws Exception {
- this.delegating.reformat(this.element);
- verify(this.delegate).reformat(this.element);
- }
-
- @Test
- public void reformatWithCanChangeWhiteSpacesOnlyShouldCallDelegate()
- throws Exception {
- this.delegating.reformat(this.element, true);
- verify(this.delegate).reformat(this.element, true);
- }
-
- @Test
- public void reformatRangeShouldCallDelegate() throws Exception {
- this.delegating.reformatRange(this.element, 12, 34);
- verify(this.delegate).reformatRange(this.element, 12, 34);
- }
-
- @Test
- public void reformatRangeWithCanChangeWhiteSpacesOnlyShouldCallDelegate()
- throws Exception {
- this.delegating.reformatRange(this.element, 12, 34, true);
- verify(this.delegate).reformatRange(this.element, 12, 34, true);
- }
-
- @Test
- public void reformatTextShouldCallDelegate() throws Exception {
- this.delegating.reformatText(this.file, 12, 34);
- verify(this.delegate).reformatText(this.file, 12, 34);
- }
-
- @Test
- public void reformatTextWithRangeCollectionShouldCallDelegate() throws Exception {
- this.delegating.reformatText(this.file, this.ranges);
- verify(this.delegate).reformatText(this.file, this.ranges);
- }
-
- @Test
- public void reformatTextWithContextShouldCallDelegate() throws Exception {
- this.delegating.reformatTextWithContext(this.file, this.ranges);
- verify(this.delegate).reformatTextWithContext(this.file, this.ranges);
- }
-
- @Test
- public void reformatTextWithContextInfoShouldCallDelegate() throws Exception {
- this.delegating.reformatTextWithContext(this.file, this.changedRangesInfo);
- verify(this.delegate).reformatTextWithContext(this.file, this.changedRangesInfo);
- }
-
- @Test
- public void adjustLineIndentForFileWithRangeShouldCallDelegate() throws Exception {
- this.delegating.adjustLineIndent(this.file, this.range);
- verify(this.delegate).adjustLineIndent(this.file, this.range);
- }
-
- @Test
- public void adjustLineIndentForFileShouldCallDelegate() throws Exception {
- this.delegating.adjustLineIndent(this.file, 123);
- verify(this.delegate).adjustLineIndent(this.file, 123);
- }
-
- @Test
- public void adjustLineIndentForDocumentShouldCallDelegate() throws Exception {
- this.delegating.adjustLineIndent(this.document, 123);
- verify(this.delegate).adjustLineIndent(this.document, 123);
- }
-
- @Test
- @Deprecated
- public void isLineToBeIndentedShouldCallDelegate() throws Exception {
- this.delegating.isLineToBeIndented(this.file, 123);
- verify(this.delegate).isLineToBeIndented(this.file, 123);
- }
-
- @Test
- public void getLineIndentForFileShouldCallDelegate() throws Exception {
- this.delegating.getLineIndent(this.file, 123);
- verify(this.delegate).getLineIndent(this.file, 123);
- }
-
- @Test
- public void getLineIndentForDocumentShouldCallDelegate() throws Exception {
- this.delegating.getLineIndent(this.document, 123);
- verify(this.delegate).getLineIndent(this.document, 123);
- }
-
- @Test
- @Deprecated
- public void getIndentShouldCallDelegate() throws Exception {
- this.delegating.getIndent("hello", this.fileType);
- verify(this.delegate).getIndent("hello", this.fileType);
- }
-
- @Test
- @Deprecated
- public void fillIndentShouldCallDelegate() throws Exception {
- com.intellij.psi.codeStyle.Indent indent = mock(
- com.intellij.psi.codeStyle.Indent.class);
- this.delegating.fillIndent(indent, this.fileType);
- verify(this.delegate).fillIndent(indent, this.fileType);
- }
-
- @Test
- @Deprecated
- public void zeroIndentShouldCallDelegate() throws Exception {
- this.delegating.zeroIndent();
- verify(this.delegate).zeroIndent();
- }
-
- @Test
- public void reformatNewlyAddedElementShouldCallDelegate() throws Exception {
- this.delegating.reformatNewlyAddedElement(this.block, this.node);
- verify(this.delegate).reformatNewlyAddedElement(this.block, this.node);
- }
-
- @Test
- public void isSequentialProcessingAllowedShouldCallDelegate() throws Exception {
- this.delegating.isSequentialProcessingAllowed();
- verify(this.delegate).isSequentialProcessingAllowed();
- }
-
- @Test
- public void performActionWithFormatterDisabledWithRunnableShouldCallDelegate()
- throws Exception {
- Runnable runnable = mock(Runnable.class);
- this.delegating.performActionWithFormatterDisabled(runnable);
- verify(this.delegate).performActionWithFormatterDisabled(runnable);
- }
-
- @Test
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void performActionWithFormatterDisabledWithThrowableRunnableShouldCallDelegate()
- throws Throwable {
- ThrowableRunnable runnable = mock(ThrowableRunnable.class);
- this.delegating.performActionWithFormatterDisabled(runnable);
- verify(this.delegate).performActionWithFormatterDisabled(runnable);
- }
-
- @Test
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void performActionWithFormatterDisabledWithComputableShouldCallDelegate()
- throws Exception {
- Computable computable = mock(Computable.class);
- this.delegating.performActionWithFormatterDisabled(computable);
- verify(this.delegate).performActionWithFormatterDisabled(computable);
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManagerTests.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManagerTests.java
deleted file mode 100644
index 9efa32a1..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringCodeStyleManagerTests.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-/**
- * Tests for {@link SpringCodeStyleManager}.
- *
- * @author Phillip Webb
- */
-public class SpringCodeStyleManagerTests {
-
- @Mock
- private CodeStyleManager delegate;
-
- @Mock
- private SpringReformatter springReformatter;
-
- private SpringCodeStyleManager styleManager;
-
- @Mock
- private PsiFile file;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- this.styleManager = new SpringCodeStyleManager(this.delegate,
- this.springReformatter);
- }
-
- @Test
- public void reformatTextWithOffsetWhenCantFormatShouldCallDelegate() {
- given(this.springReformatter.canReformat(any())).willReturn(false);
- this.styleManager.reformatText(this.file, 10, 20);
- verify(this.delegate).reformatText(this.file, 10, 20);
- }
-
- @Test
- public void reformatTextWithOffsetWhenCanFormatShouldCallFormatter() {
- given(this.springReformatter.canReformat(any())).willReturn(true);
- Set ranges = new HashSet<>(Arrays.asList(new TextRange(10, 20)));
- this.styleManager.reformatText(this.file, 10, 20);
- verify(this.springReformatter).reformat(this.file, ranges);
- verifyZeroInteractions(this.delegate);
- }
-
- @Test
- public void reformatTextWithRangeWhenCantFormatShouldCallDelegate() {
- given(this.springReformatter.canReformat(any())).willReturn(false);
- Collection ranges = Arrays.asList(new TextRange(10, 20));
- this.styleManager.reformatText(this.file, ranges);
- verify(this.delegate).reformatText(this.file, ranges);
- }
-
- @Test
- public void reformatTextWithRangeWhenCanFormatShouldCallFormatter() {
- given(this.springReformatter.canReformat(any())).willReturn(true);
- Collection ranges = Arrays.asList(new TextRange(10, 20));
- this.styleManager.reformatText(this.file, ranges);
- verify(this.springReformatter).reformat(this.file, ranges);
- verifyZeroInteractions(this.delegate);
- }
-
- @Test
- public void reformatTextWithContextWhenCantFormatShouldCallDelegate() {
- given(this.springReformatter.canReformat(any())).willReturn(false);
- Collection ranges = Arrays.asList(new TextRange(10, 20));
- this.styleManager.reformatTextWithContext(this.file, ranges);
- verify(this.delegate).reformatTextWithContext(this.file, ranges);
- }
-
- @Test
- public void reformatTextWithContextWhenCanFormatShouldCallFormatter() {
- given(this.springReformatter.canReformat(any())).willReturn(true);
- Collection ranges = Arrays.asList(new TextRange(10, 20));
- this.styleManager.reformatTextWithContext(this.file, ranges);
- verify(this.springReformatter).reformat(this.file, ranges);
- verifyZeroInteractions(this.delegate);
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringReformatterTests.java b/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringReformatterTests.java
deleted file mode 100644
index c2896c6f..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-plugin/src/test/java/io/spring/format/formatter/intellij/codestyle/SpringReformatterTests.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.spring.format.formatter.intellij.codestyle;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.function.Supplier;
-
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-/**
- * Tests for {@link SpringReformatter}.
- *
- * @author Phillip Webb
- */
-public class SpringReformatterTests {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Mock
- private Project project;
-
- @Mock
- private Application application;
-
- @Mock
- private PsiDocumentManager documentManager;
-
- private SpringReformatter reformatter;
-
- @Mock
- private PsiFile file;
-
- private Collection ranges = Arrays.asList(new TextRange(10, 20));
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- this.reformatter = new TestSpringReformatter(() -> this.project,
- () -> this.application, () -> this.documentManager);
- }
-
- @Test
- public void reformatShouldAssertWriteAccess() throws Exception {
- given(this.file.isWritable()).willReturn(true);
- this.reformatter.reformat(this.file, this.ranges);
- verify(this.application).assertWriteAccessAllowed();
- }
-
- @Test
- public void reformatShouldCommitAllDocuments() throws Exception {
- given(this.file.isWritable()).willReturn(true);
- this.reformatter.reformat(this.file, this.ranges);
- verify(this.documentManager).commitAllDocuments();
- }
-
- @Test
- public void reformatWhenFileIsNotWriteableShouldThrow() throws Exception {
- this.thrown.expect(IncorrectOperationException.class);
- this.reformatter.reformat(this.file, this.ranges);
- }
-
- @Test
- public void reformatShouldReformatDocument() throws Exception {
- given(this.file.isWritable()).willReturn(true);
- Document document = mock(Document.class);
- String text = "public class Hello {}";
- given(document.getText()).willReturn(text);
- given(this.documentManager.getDocument(this.file)).willReturn(document);
- this.reformatter.reformat(this.file,
- Arrays.asList(new TextRange(0, text.length())));
- verify(document).replaceString(20, 20, "\n\n");
- verify(this.documentManager).commitDocument(document);
- }
-
- static class TestSpringReformatter extends SpringReformatter {
-
- TestSpringReformatter(Supplier project,
- Supplier application,
- Supplier documentManager) {
- super(project, application, documentManager);
- }
-
- @Override
- protected void runWriteCommandAction(Runnable runnable) {
- runnable.run();
- }
-
- }
-
-}
diff --git a/spring-javaformat-intellij/spring-javaformat-intellij-runtime/pom.xml b/spring-javaformat-intellij/spring-javaformat-intellij-runtime/pom.xml
deleted file mode 100644
index dfab70ae..00000000
--- a/spring-javaformat-intellij/spring-javaformat-intellij-runtime/pom.xml
+++ /dev/null
@@ -1,285 +0,0 @@
-
-
- 4.0.0
-
- io.spring.javaformat
- spring-javaformat-intellij
- 0.0.7-SNAPSHOT
-
- spring-javaformat-intellij-runtime
- pom
- Spring JavaFormat IntelliJ Runtime
-
- ${basedir}/../..
- https://download.jetbrains.com/idea/ideaIC-2018.2-no-jdk.tar.gz
- 528c3e895fb1d20a5fef2a212667d00861204ff9
- https://github.com/JetBrains/intellij-community/archive/182.3684.zip
- intellij-community-182.3684
-
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
-
- true
-
-
-
- com.googlecode.maven-download-plugin
- download-maven-plugin
-
-
- download-intellij-binary
- validate
-
- wget
-
-
- ${intellij.binary}
- ${intellij.binary.sha1}
- intellij.tgz
-
-
-
- download-intellij-source
- install
-
- wget
-
-
- ${intellij.source}
- intellij-source.zip
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
- prepare-intellij
- install
-
- run
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-install-plugin
-
-
- install-intellij-platform-api
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/platform-api.jar
- ${project.build.directory}/intellij-source/platform-api-sources.zip
- io.spring.javaformat.intellij
- platform-api
- ${project.version}
- jar
- true
-
-
-
- install-intellij-util
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/util.jar
- ${project.build.directory}/intellij-source/util-sources.zip
- io.spring.javaformat.intellij
- util
- ${project.version}
- jar
- true
-
-
-
- install-intellij-extensions
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/extensions.jar
- ${project.build.directory}/intellij-source/extensions-sources.zip
- io.spring.javaformat.intellij
- extensions
- ${project.version}
- jar
- true
-
-
-
- install-intellij-idea
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/idea.jar
- io.spring.javaformat.intellij
- idea
- ${project.version}
- jar
- true
-
-
-
- install-intellij-maven
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/maven.jar
- ${project.build.directory}/intellij-source/maven-sources.zip
- io.spring.javaformat.intellij
- maven
- ${project.version}
- jar
- true
-
-
-
- install-intellij-maven-server-api
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/maven-server-api.jar
- io.spring.javaformat.intellij
- maven-server-api
- ${project.version}
- jar
- true
-
-
-
- install-intellij-gradle
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/gradle-common.jar
- ${project.build.directory}/intellij-source/gradle-sources.zip
- io.spring.javaformat.intellij
- gradle
- ${project.version}
- jar
- true
-
-
-
- install-intellij-gradle-tooling-extension-api
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/gradle-tooling-extension-api.jar
- ${project.build.directory}/intellij-source/gradle-tooling-extension-api-sources.zip
- io.spring.javaformat.intellij
- gradle-tooling-extension-api
- ${project.version}
- jar
- true
-
-
-
- install-intellij-gradle-tooling-extension-impl
- install
- false
-
- install-file
-
-
- ${project.build.directory}/intellij/gradle-tooling-extension-impl.jar
- ${project.build.directory}/intellij-source/gradle-tooling-extension-impl-sources.zip
- io.spring.javaformat.intellij
- gradle-tooling-extension-impl
- ${project.version}
- jar
- true
-
-
-
-
-
-
-
diff --git a/spring-javaformat-maven/pom.xml b/spring-javaformat-maven/pom.xml
index 44014f42..61cb5d27 100644
--- a/spring-javaformat-maven/pom.xml
+++ b/spring-javaformat-maven/pom.xml
@@ -1,12 +1,12 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-build
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-mavenpom
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
index 5354af86..af8474d3 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/pom.xml
@@ -1,11 +1,11 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-maven
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-maven-pluginmaven-plugin
@@ -15,6 +15,16 @@
+
+ maven-clean-plugin
+
+
+
+ out
+
+
+
+ org.apache.maven.pluginsmaven-invoker-plugin
@@ -91,15 +101,21 @@
+
+ org.codehaus.plexus
+ plexus-utils
+
+
org.apache.mavenmaven-core
+ providedorg.apache.mavenmaven-plugin-api
+ provided
-
org.apache.maven.plugin-toolsmaven-plugin-annotations
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/pom.xml
new file mode 100644
index 00000000..b71be82c
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+ io.spring.javaformat
+ apply-line-separator
+ 0.0.1.BUILD-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
+ apply
+
+
+ CR
+
+
+
+
+
+
+
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/src/main/java/simple/Simple.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..10016e5d
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/src/main/java/simple/Simple.java
@@ -0,0 +1,14 @@
+package simple;
+
+/**
+ * Simple.
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/verify.groovy b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/verify.groovy
new file mode 100644
index 00000000..21927be4
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-line-separator/verify.groovy
@@ -0,0 +1 @@
+new io.spring.format.maven.VerifyApply().verify(basedir, "\r")
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/pom.xml
new file mode 100644
index 00000000..213305b9
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+ io.spring.javaformat
+ apply-skip
+ 0.0.1.BUILD-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
+ apply
+
+
+ true
+
+
+
+
+
+
+
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/src/main/java/simple/Simple.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..10016e5d
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/src/main/java/simple/Simple.java
@@ -0,0 +1,14 @@
+package simple;
+
+/**
+ * Simple.
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/verify.groovy b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/verify.groovy
new file mode 100644
index 00000000..5ffd403d
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-skip/verify.groovy
@@ -0,0 +1 @@
+new io.spring.format.maven.VerifyApply().verifyNoApply(basedir)
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/.springjavaformatconfig b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/.springjavaformatconfig
new file mode 100644
index 00000000..881903b2
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/.springjavaformatconfig
@@ -0,0 +1 @@
+indentation-style=spaces
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/pom.xml
new file mode 100644
index 00000000..252e99b8
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ io.spring.javaformat
+ apply
+ 0.0.1.BUILD-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
+ apply
+
+
+
+
+
+
+
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/src/main/java/simple/Simple.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..10016e5d
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/src/main/java/simple/Simple.java
@@ -0,0 +1,14 @@
+package simple;
+
+/**
+ * Simple.
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/verify.groovy b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/verify.groovy
new file mode 100644
index 00000000..644be98b
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply-spaces/verify.groovy
@@ -0,0 +1 @@
+new io.spring.format.maven.VerifyApply().verify(basedir, true)
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply/pom.xml
index 8d63de00..252e99b8 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/apply/pom.xml
@@ -1,12 +1,14 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatapply0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-bad/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-bad/pom.xml
index 3cefcbad..7c23eaf4 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-bad/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-bad/pom.xml
@@ -1,12 +1,15 @@
-
+4.0.0io.spring.javaformatvalidate-bad0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-exclude/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-exclude/pom.xml
index 4d3a011a..d213bc7b 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-exclude/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-exclude/pom.xml
@@ -1,13 +1,15 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatvalidate-gensource-exclude0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-include/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-include/pom.xml
index ee8948fb..820f2c24 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-include/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-gensource-include/pom.xml
@@ -1,13 +1,15 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatvalidate-gensource-include0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-ok/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-ok/pom.xml
index af50bc98..61fde7ba 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-ok/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-ok/pom.xml
@@ -1,12 +1,14 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatvalidate-ok0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/pom.xml
new file mode 100644
index 00000000..d05c8e80
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+ io.spring.javaformat
+ validate-skip-global-property
+ 0.0.1.BUILD-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+ true
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
+ validate
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter/bin/src/test/resources/source/simple.txt b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/src/main/java/simple/Simple.java
similarity index 78%
rename from spring-javaformat/spring-javaformat-formatter/bin/src/test/resources/source/simple.txt
rename to spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/src/main/java/simple/Simple.java
index a12ac39e..14f14516 100644
--- a/spring-javaformat/spring-javaformat-formatter/bin/src/test/resources/source/simple.txt
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-global-property/src/main/java/simple/Simple.java
@@ -6,10 +6,10 @@
* @author Phillip Webb
* @since 1.0.0
*/
-public class Simple {
+public class Simple {
public static void main(String[] args) throws Exception {
- // FIXME
+ // Main method
}
}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/pom.xml
new file mode 100644
index 00000000..e0319c25
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+ io.spring.javaformat
+ validate-skip-property
+ 0.0.1.BUILD-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+ true
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+
+
+ validate
+
+
+
+
+
+
+
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/src/main/java/simple/Simple.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/src/main/java/simple/Simple.java
new file mode 100644
index 00000000..14f14516
--- /dev/null
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip-property/src/main/java/simple/Simple.java
@@ -0,0 +1,15 @@
+package simple;
+
+/**
+ * Simple.
+ *
+ * @author Phillip Webb
+ * @since 1.0.0
+ */
+public class Simple {
+
+ public static void main(String[] args) throws Exception {
+ // Main method
+ }
+
+}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip/pom.xml b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip/pom.xml
index 4da63f70..84c27feb 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip/pom.xml
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/it/validate-skip/pom.xml
@@ -1,12 +1,14 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatvalidate-skip0.0.1.BUILD-SNAPSHOTUTF-8
+ 1.8
+ 1.8
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ApplyMojo.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ApplyMojo.java
index d8de0e5a..3d8bdc6d 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ApplyMojo.java
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ApplyMojo.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -20,29 +20,38 @@
import java.nio.charset.Charset;
import java.util.List;
-import io.spring.javaformat.formatter.FileEdit;
-import io.spring.javaformat.formatter.FileFormatter;
-import io.spring.javaformat.formatter.FileFormatterException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import io.spring.javaformat.formatter.FileEdit;
+import io.spring.javaformat.formatter.FileFormatterException;
/**
* Applies source formatting to the codebase.
*
* @author Phillip Webb
*/
-@Mojo(name = "apply", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
+@Mojo(name = "apply", defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true)
public class ApplyMojo extends FormatMojo {
+ /**
+ * Skip the execution.
+ */
+ @Parameter(property = "spring-javaformat.apply.skip", defaultValue = "false")
+ private boolean skip;
+
@Override
- protected void execute(List files, Charset encoding)
+ protected void execute(List files, Charset encoding, String lineSeparator)
throws MojoExecutionException, MojoFailureException {
+ if (this.skip || skipGlobally()) {
+ getLog().info("skipping format apply as per configuration.");
+ return;
+ }
try {
- FileFormatter formatter = new FileFormatter();
- formatter.formatFiles(files, encoding).filter(FileEdit::hasEdits)
- .forEach(this::save);
+ getFormatter().formatFiles(files, encoding, lineSeparator).filter(FileEdit::hasEdits).forEach(this::save);
}
catch (FileFormatterException ex) {
throw new MojoExecutionException("Unable to format file " + ex.getFile(), ex);
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/FormatMojo.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/FormatMojo.java
index 7bd528dd..6270b549 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/FormatMojo.java
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/FormatMojo.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -22,10 +22,15 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -34,6 +39,9 @@
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.FileFormatter;
+
/**
* Base class for formatter Mojo.
*
@@ -43,8 +51,18 @@ public abstract class FormatMojo extends AbstractMojo {
private static final String[] DEFAULT_INCLUDES = new String[] { "**/*.java" };
- private static final String GENERATED_SOURCE = File.separator + "generated-sources"
- + File.separator;
+ private static final String GENERATED_SOURCES = File.separator + "generated-sources" + File.separator;
+
+ private static final String GENERATED_TEST_SOURCES = File.separator + "generated-test-sources" + File.separator;
+
+ private static final Map LINE_SEPARATOR;
+ static {
+ Map lineSeparator = new LinkedHashMap<>();
+ lineSeparator.put("cr", "\r");
+ lineSeparator.put("lf", "\n");
+ lineSeparator.put("crlf", "\r\n");
+ LINE_SEPARATOR = Collections.unmodifiableMap(lineSeparator);
+ }
/**
* The Maven Project Object.
@@ -52,6 +70,12 @@ public abstract class FormatMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true, required = true)
protected MavenProject project;
+ /**
+ * The Maven Session Object.
+ */
+ @Parameter(defaultValue = "${session}", readonly = true, required = true)
+ protected MavenSession session;
+
/**
* Specifies the location of the source directories to use.
*/
@@ -87,6 +111,12 @@ public abstract class FormatMojo extends AbstractMojo {
@Parameter(property = "spring-javaformat.includeGeneratedSource", defaultValue = "false")
private boolean includeGeneratedSource;
+ /**
+ * Specifies the line separator to use when formatting.
+ */
+ @Parameter(property = "spring-javaformat.lineSeparator")
+ private String lineSeparator;
+
@Override
public final void execute() throws MojoExecutionException, MojoFailureException {
List directories = new ArrayList<>();
@@ -96,15 +126,21 @@ public final void execute() throws MojoExecutionException, MojoFailureException
for (File directory : directories) {
files.addAll(scan(directory));
}
- Charset encoding = (this.encoding == null ? StandardCharsets.UTF_8
- : Charset.forName(this.encoding));
- execute(files, encoding);
+ Charset encoding = (this.encoding == null ? StandardCharsets.UTF_8 : Charset.forName(this.encoding));
+ String lineSeparator = null;
+ if (this.lineSeparator != null) {
+ lineSeparator = LINE_SEPARATOR.get(this.lineSeparator.toLowerCase());
+ if (lineSeparator == null) {
+ throw new MojoExecutionException("Unknown lineSeparator " + this.lineSeparator);
+ }
+ }
+ execute(files, encoding, this.lineSeparator != null ? lineSeparator : null);
}
private Stream resolve(List directories) {
- return directories.stream().map(
- directory -> FileUtils.resolveFile(this.project.getBasedir(), directory))
- .filter(this::include);
+ return directories.stream()
+ .map(directory -> FileUtils.resolveFile(this.project.getBasedir(), directory))
+ .filter(this::include);
}
private boolean include(File file) {
@@ -124,7 +160,8 @@ private boolean isGeneratedSource(File file) {
try {
String path = file.getCanonicalPath() + File.separator;
String projectPath = this.project.getBasedir().getCanonicalPath();
- return path.startsWith(projectPath) && path.contains(GENERATED_SOURCE);
+ return path.startsWith(projectPath)
+ && (path.contains(GENERATED_SOURCES) || path.contains(GENERATED_TEST_SOURCES));
}
catch (IOException ex) {
return false;
@@ -140,8 +177,10 @@ private List scan(File directory) {
scanner.setCaseSensitive(false);
scanner.setFollowSymlinks(false);
scanner.scan();
- return Arrays.asList(scanner.getIncludedFiles()).stream()
- .map(name -> new File(directory, name)).collect(Collectors.toList());
+ return Arrays.asList(scanner.getIncludedFiles())
+ .stream()
+ .map(name -> new File(directory, name))
+ .collect(Collectors.toList());
}
private boolean hasLength(Object[] array) {
@@ -152,10 +191,28 @@ private boolean hasLength(Object[] array) {
* Perform the formatting build-process behavior this {@code Mojo} implements.
* @param files the files to process
* @param encoding the encoding
+ * @param lineSeparator the line separator
* @throws MojoExecutionException on execution error
* @throws MojoFailureException on failure
*/
- protected abstract void execute(List files, Charset encoding)
+ protected abstract void execute(List files, Charset encoding, String lineSeparator)
throws MojoExecutionException, MojoFailureException;
+ protected final FileFormatter getFormatter() {
+ JavaFormatConfig javaFormatConfig = JavaFormatConfig.findFrom(this.project.getBasedir());
+ return new FileFormatter(javaFormatConfig);
+ }
+
+ protected boolean skipGlobally() {
+ boolean result = false;
+ result = result || skipGlobally(this.session.getUserProperties());
+ result = result || skipGlobally(this.session.getSystemProperties());
+ result = result || skipGlobally(this.project.getProperties());
+ return result;
+ }
+
+ private boolean skipGlobally(Properties properties) {
+ return Boolean.valueOf(properties.getProperty("spring-javaformat.skip"));
+ }
+
}
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ValidateMojo.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ValidateMojo.java
index 1cc1e64d..c9a77b81 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ValidateMojo.java
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/main/java/io/spring/format/maven/ValidateMojo.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,42 +21,41 @@
import java.util.List;
import java.util.stream.Collectors;
-import io.spring.javaformat.formatter.FileEdit;
-import io.spring.javaformat.formatter.FileFormatter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
+import io.spring.javaformat.formatter.FileEdit;
+
/**
* Validates that source formatting matches the required style.
*
* @author Phillip Webb
*/
-@Mojo(name = "validate", defaultPhase = LifecyclePhase.VALIDATE)
+@Mojo(name = "validate", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true)
public class ValidateMojo extends FormatMojo {
/**
* Skip the execution.
*/
- @Parameter(property = "spring-javaformat.skip", defaultValue = "false")
+ @Parameter(property = "spring-javaformat.validate.skip", defaultValue = "false")
private boolean skip;
@Override
- protected void execute(List files, Charset encoding)
+ protected void execute(List files, Charset encoding, String lineSeparator)
throws MojoExecutionException, MojoFailureException {
- if (this.skip) {
- getLog().debug("skipping validation as per configuration.");
+ if (this.skip || skipGlobally()) {
+ getLog().info("skipping format validate as per configuration.");
return;
}
- FileFormatter formatter = new FileFormatter();
- List problems = formatter.formatFiles(files, encoding)
- .filter(FileEdit::hasEdits).map(FileEdit::getFile)
- .collect(Collectors.toList());
+ List problems = getFormatter().formatFiles(files, encoding, lineSeparator)
+ .filter(FileEdit::hasEdits)
+ .map(FileEdit::getFile)
+ .collect(Collectors.toList());
if (!problems.isEmpty()) {
- StringBuilder message = new StringBuilder(
- "Formatting violations found in the following files:\n");
+ StringBuilder message = new StringBuilder("Formatting violations found in the following files:\n");
problems.stream().forEach((f) -> message.append(" * " + f + "\n"));
message.append("\nRun `spring-javaformat:apply` to fix.");
throw new MojoFailureException(message.toString());
diff --git a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/test/java/io/spring/format/maven/VerifyApply.java b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/test/java/io/spring/format/maven/VerifyApply.java
index d857633b..4338b633 100644
--- a/spring-javaformat-maven/spring-javaformat-maven-plugin/src/test/java/io/spring/format/maven/VerifyApply.java
+++ b/spring-javaformat-maven/spring-javaformat-maven-plugin/src/test/java/io/spring/format/maven/VerifyApply.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -33,10 +33,33 @@ public class VerifyApply {
private static final String JAVA_FILE = "src/main/java/simple/Simple.java";
public void verify(File base) throws IOException {
- String formated = new String(Files.readAllBytes(base.toPath().resolve(JAVA_FILE)),
- StandardCharsets.UTF_8);
- assertThat(formated).contains("Simple.\n *\n * @author")
- .contains("public class Simple {");
+ verify(base, null);
+ }
+
+ public void verify(File base, boolean spaces) throws IOException {
+ verify(base, null, spaces);
+ }
+
+ public void verify(File base, String lineSeparator) throws IOException {
+ verify(base, lineSeparator, false);
+ }
+
+ public void verify(File base, String lineSeparator, boolean spaces) throws IOException {
+ String formated = new String(Files.readAllBytes(base.toPath().resolve(JAVA_FILE)), StandardCharsets.UTF_8);
+ if (lineSeparator == null) {
+ formated = formated.replace("\r\n", "\n").replace('\r', '\n');
+ lineSeparator = "\n";
+ }
+ String indent = (!spaces) ? " " : " ";
+ assertThat(formated).contains("Simple." + lineSeparator + " *" + lineSeparator + " * @author")
+ .contains("public class Simple {")
+ .contains(indent + "public static void main");
+ }
+
+ public void verifyNoApply(File base) throws IOException {
+ String formated = new String(Files.readAllBytes(base.toPath().resolve(JAVA_FILE)), StandardCharsets.UTF_8);
+ formated = formated.replace("\r\n", "\n").replace('\r', '\n');
+ assertThat(formated).contains("Simple {");
}
}
diff --git a/spring-javaformat-vscode/README.md b/spring-javaformat-vscode/README.md
new file mode 100644
index 00000000..e6dea6c9
--- /dev/null
+++ b/spring-javaformat-vscode/README.md
@@ -0,0 +1,19 @@
+# spring-javaformat-vscode
+
+`spring-javaformat` extension for visual studio code.
+
+
+
+## Prerequisites
+
+* Install [node.js](https://nodejs.org/en/download/)
+* Install [yarn](https://yarnpkg.com/en/docs/install)
+* Install [vsce](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce)
+
+## Generate extension
+
+Just `mvn clean package`
+
+
+> `spring-javaformat-1.0.0.vsix` will be generated there
+
diff --git a/spring-javaformat-vscode/format.gif b/spring-javaformat-vscode/format.gif
new file mode 100644
index 00000000..fd1fdacd
Binary files /dev/null and b/spring-javaformat-vscode/format.gif differ
diff --git a/spring-javaformat-vscode/pom.xml b/spring-javaformat-vscode/pom.xml
new file mode 100644
index 00000000..f42bc4bb
--- /dev/null
+++ b/spring-javaformat-vscode/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat-build
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-vscode
+ pom
+ Spring JavaFormat Visual Studio Code
+
+ ${basedir}/..
+
+
+ spring-javaformat-vscode-extension
+
+
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.gitignore b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.gitignore
new file mode 100644
index 00000000..2c32c547
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.gitignore
@@ -0,0 +1,7 @@
+out
+runtime
+dist
+node
+node_modules
+.vscode-test/
+*.vsix
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierignore b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierignore
new file mode 100644
index 00000000..717380fe
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierignore
@@ -0,0 +1,5 @@
+out
+target
+node
+.vscode
+.vscode-test
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierrc b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierrc
new file mode 100644
index 00000000..995d5360
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "tabWidth": 2,
+ "semi": false,
+ "singleQuote": true,
+ "printWidth": 120
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/extensions.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/extensions.json
new file mode 100644
index 00000000..c0a2258b
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": ["dbaeumer.vscode-eslint"]
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/launch.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/launch.json
new file mode 100644
index 00000000..3baae646
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/launch.json
@@ -0,0 +1,31 @@
+// A launch configuration that compiles the extension and then opens it inside a new window
+// Use IntelliSense to learn about possible attributes.
+// Hover to view descriptions of existing attributes.
+// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Run Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
+ "outFiles": ["${workspaceFolder}/out/**/*.js"],
+ "preLaunchTask": "build"
+ },
+ {
+ "name": "Extension Tests",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": [
+ "--disable-extensions",
+ "--extensionDevelopmentPath=${workspaceFolder}",
+ "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
+ ],
+ "outFiles": ["${workspaceFolder}/out/test/**/*.js"],
+ "preLaunchTask": "build"
+ }
+ ]
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/settings.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/settings.json
new file mode 100644
index 00000000..5c3ffd3c
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/settings.json
@@ -0,0 +1,12 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+ "files.exclude": {
+ "out": false // set this to true to hide the "out" folder with the compiled JS files
+ },
+ "search.exclude": {
+ "out": true // set this to false to include "out" folder in search results
+ },
+ // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
+ "typescript.tsc.autoDetect": "off",
+ "java.configuration.updateBuildConfiguration": "interactive"
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/tasks.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/tasks.json
new file mode 100644
index 00000000..0a101bd2
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscode/tasks.json
@@ -0,0 +1,21 @@
+// See https://go.microsoft.com/fwlink/?LinkId=733558
+// for the documentation about the tasks.json format
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "type": "npm",
+ "script": "watch",
+ "problemMatcher": "$tsc-watch",
+ "isBackground": true,
+ "presentation": {
+ "reveal": "never"
+ },
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscodeignore b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscodeignore
new file mode 100644
index 00000000..4b30b77f
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/.vscodeignore
@@ -0,0 +1,17 @@
+.gitignore
+.prettierrc
+.project
+.classpath
+.vscode/**
+.vscode-test/**
+.settings/**
+out/test/**
+**/tsconfig.json
+**/tslint.json
+**/*.map
+**/*.ts
+target/**
+node/**
+src/**
+README.md
+**pom.xml
\ No newline at end of file
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/LICENSE.txt b/spring-javaformat-vscode/spring-javaformat-vscode-extension/LICENSE.txt
new file mode 100644
index 00000000..ff773796
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ https://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json
new file mode 100644
index 00000000..5da1cec7
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package-lock.json
@@ -0,0 +1,3756 @@
+{
+ "name": "spring-javaformat-vscode-extension",
+ "version": "0.0.48-SNAPSHOT",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "spring-javaformat-vscode-extension",
+ "version": "0.0.48-SNAPSHOT",
+ "devDependencies": {
+ "@types/glob": "^8.0.1",
+ "@types/mocha": "^10.0.1",
+ "@types/node": "16.x",
+ "@types/vscode": "^1.75.0",
+ "@typescript-eslint/eslint-plugin": "^5.52.0",
+ "@vscode/test-electron": "^2.2.2",
+ "@vscode/vsce": "^2.19.0",
+ "eslint": "^8.33.0",
+ "glob": "8.1.0",
+ "mocha": "10.2.0",
+ "prettier": "3.0.3",
+ "typescript": "^4.9.4"
+ },
+ "engines": {
+ "vscode": "^1.75.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
+ "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.4.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
+ "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.0.1.tgz",
+ "integrity": "sha512-8bVUjXZvJacUFkJXHdyZ9iH1Eaj5V7I8c4NdH5sQJsdXkqT4CA5Dhb4yb4VE/3asyx4L9ayZr1NIhTsWHczmMw==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true
+ },
+ "node_modules/@types/mocha": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz",
+ "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "16.18.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz",
+ "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==",
+ "dev": true
+ },
+ "node_modules/@types/semver": {
+ "version": "7.3.13",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+ "dev": true
+ },
+ "node_modules/@types/vscode": {
+ "version": "1.75.1",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.1.tgz",
+ "integrity": "sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz",
+ "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.52.0",
+ "@typescript-eslint/type-utils": "5.52.0",
+ "@typescript-eslint/utils": "5.52.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "regexpp": "^3.2.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz",
+ "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.52.0",
+ "@typescript-eslint/types": "5.52.0",
+ "@typescript-eslint/typescript-estree": "5.52.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz",
+ "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.52.0",
+ "@typescript-eslint/visitor-keys": "5.52.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz",
+ "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.52.0",
+ "@typescript-eslint/utils": "5.52.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz",
+ "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz",
+ "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.52.0",
+ "@typescript-eslint/visitor-keys": "5.52.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz",
+ "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.52.0",
+ "@typescript-eslint/types": "5.52.0",
+ "@typescript-eslint/typescript-estree": "5.52.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.52.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz",
+ "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.52.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vscode/test-electron": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.2.3.tgz",
+ "integrity": "sha512-7DmdGYQTqRNaLHKG3j56buc9DkstriY4aV0S3Zj32u0U9/T0L8vwWAC9QGCh1meu1VXDEla1ze27TkqysHGP0Q==",
+ "dev": true,
+ "dependencies": {
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "rimraf": "^3.0.2",
+ "unzipper": "^0.10.11"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@vscode/vsce": {
+ "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",
+ "chalk": "^2.4.2",
+ "cheerio": "^1.0.0-rc.9",
+ "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",
+ "minimatch": "^3.0.3",
+ "parse-semver": "^1.1.1",
+ "read": "^1.0.7",
+ "semver": "^5.1.0",
+ "tmp": "^0.2.1",
+ "typed-rest-client": "^1.8.4",
+ "url-join": "^4.0.1",
+ "xml2js": "^0.5.0",
+ "yauzl": "^2.3.1",
+ "yazl": "^2.2.2"
+ },
+ "bin": {
+ "vsce": "vsce"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "optionalDependencies": {
+ "keytar": "^7.7.0"
+ }
+ },
+ "node_modules/@vscode/vsce/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@vscode/vsce/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/azure-devops-node-api": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz",
+ "integrity": "sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==",
+ "dev": true,
+ "dependencies": {
+ "tunnel": "0.0.6",
+ "typed-rest-client": "^1.8.4"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "optional": true
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/binary": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
+ "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
+ "dev": true,
+ "dependencies": {
+ "buffers": "~0.1.1",
+ "chainsaw": "~0.1.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
+ "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
+ "dev": true
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "optional": true,
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-indexof-polyfill": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+ "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/buffers": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
+ "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.2.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chainsaw": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
+ "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
+ "dev": true,
+ "dependencies": {
+ "traverse": ">=0.3.0 <0.4"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
+ "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
+ "dev": true,
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "htmlparser2": "^8.0.1",
+ "parse5": "^7.0.0",
+ "parse5-htmlparser2-tree-adapter": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+ "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+ "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/duplexer2/node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/duplexer2/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/duplexer2/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz",
+ "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/eslintrc": "^1.4.1",
+ "@humanwhocodes/config-array": "^0.11.8",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.4.0",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-sdsl": "^4.1.4",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
+ "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dev": true,
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/fstream": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
+ },
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/fstream/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fstream/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
+ "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
+ "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "entities": "^4.3.0"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "optional": true
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-sdsl": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
+ "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "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",
+ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "node-addon-api": "^4.3.0",
+ "prebuild-install": "^7.0.1"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/linkify-it": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
+ "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+ "dev": true,
+ "dependencies": {
+ "uc.micro": "^1.0.1"
+ }
+ },
+ "node_modules/listenercount": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
+ "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
+ "dev": true
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/log-symbols/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/log-symbols/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/markdown-it": {
+ "version": "12.3.2",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
+ "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
+ "linkify-it": "^3.0.1",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.js"
+ }
+ },
+ "node_modules/markdown-it/node_modules/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/mocha": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mocha/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/node-abi": {
+ "version": "3.33.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.33.0.tgz",
+ "integrity": "sha512-7GGVawqyHF4pfd0YFybhv/eM9JwTtPqx0mAanQ146O3FlSh3pA24zf9IRQTOsfTSqXTNzPSP5iagAJ94jjuVog==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-semver": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
+ "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^5.1.0"
+ }
+ },
+ "node_modules/parse-semver/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
+ "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
+ "dev": true,
+ "dependencies": {
+ "domhandler": "^5.0.2",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+ "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dev": true,
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/read": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+ "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
+ "dev": true,
+ "dependencies": {
+ "mute-stream": "~0.0.4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ },
+ "node_modules/semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "dev": true
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "optional": true
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "optional": true,
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "dependencies": {
+ "rimraf": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.17.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/traverse": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
+ "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tunnel": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-rest-client": {
+ "version": "1.8.9",
+ "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.9.tgz",
+ "integrity": "sha512-uSmjE38B80wjL85UFX3sTYEUlvZ1JgCRhsWj/fJ4rZ0FqDUFoIuodtiVeE+cUqiVTOKPdKrp/sdftD15MDek6g==",
+ "dev": true,
+ "dependencies": {
+ "qs": "^6.9.1",
+ "tunnel": "0.0.6",
+ "underscore": "^1.12.1"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+ "dev": true
+ },
+ "node_modules/underscore": {
+ "version": "1.13.6",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
+ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
+ "dev": true
+ },
+ "node_modules/unzipper": {
+ "version": "0.10.11",
+ "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
+ "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
+ "dev": true,
+ "dependencies": {
+ "big-integer": "^1.6.17",
+ "binary": "~0.3.0",
+ "bluebird": "~3.4.1",
+ "buffer-indexof-polyfill": "~1.0.0",
+ "duplexer2": "~0.1.4",
+ "fstream": "^1.0.12",
+ "graceful-fs": "^4.2.2",
+ "listenercount": "~1.0.1",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "~1.0.4"
+ }
+ },
+ "node_modules/unzipper/node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/unzipper/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/unzipper/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+ "dev": true
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/xml2js": {
+ "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",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dev": true,
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/yazl": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
+ "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
+ "dev": true,
+ "dependencies": {
+ "buffer-crc32": "~0.2.3"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json
new file mode 100644
index 00000000..c10d286e
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "spring-javaformat-vscode-extension",
+ "description": "Spring JavaFormat Visual Studio Code Extension",
+ "displayName": "Spring JavaFormat",
+ "version": "0.0.48-SNAPSHOT",
+ "publisher": "io.spring.javaformat",
+ "engines": {
+ "vscode": "^1.75.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/spring-io/spring-javaformat.git"
+ },
+ "categories": [
+ "Formatters"
+ ],
+ "activationEvents": [
+ "onLanguage:java"
+ ],
+ "main": "./out/extension.js",
+ "scripts": {
+ "vscode:prepublish": "npm run compile",
+ "compile": "tsc -b ./",
+ "watch": "tsc -b ./ -watch",
+ "pretest": "npm run compile",
+ "test": "node ./out/test/runTest.js",
+ "package": "vsce package --out ./target/spring-javaformat.vsix"
+ },
+ "devDependencies": {
+ "@types/glob": "^8.0.1",
+ "@types/mocha": "^10.0.1",
+ "@types/node": "16.x",
+ "@types/vscode": "^1.75.0",
+ "@typescript-eslint/eslint-plugin": "^5.52.0",
+ "@vscode/test-electron": "^2.2.2",
+ "@vscode/vsce": "^2.19.0",
+ "eslint": "^8.33.0",
+ "glob": "8.1.0",
+ "mocha": "10.2.0",
+ "prettier": "3.0.3",
+ "typescript": "^4.9.4"
+ }
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml b/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml
new file mode 100644
index 00000000..7891d15d
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/pom.xml
@@ -0,0 +1,177 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat-vscode
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-vscode-extension
+ Spring JavaFormat Visual Studio Code Extension
+
+ ${basedir}/../..
+
+
+
+
+ maven-clean-plugin
+
+
+
+ out
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ ${basedir}/runtime/spring-java-format.jar
+ false
+
+
+ *:*
+
+ META-INF/MANIFEST.MF
+
+
+
+
+
+ io.spring.format.vscode.VisualStudioCodeFormatter
+
+
+
+
+
+
+
+ com.github.eirslett
+ frontend-maven-plugin
+
+
+ install-node-and-npm
+ initialize
+
+ install-node-and-npm
+
+
+
+ npm-install
+ initialize
+
+ npm
+
+
+
+ prettier-check
+ compile
+
+ npx
+
+
+ prettier --check .
+
+
+
+ vsce-package
+ package
+
+ npm
+
+
+ run package
+
+
+
+ update-package-lock
+
+ npm
+
+
+ install --package-lock-only
+
+
+
+
+ v19.6.0
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-source
+ generate-sources
+
+ attach-artifact
+
+
+
+
+ ${project.build.directory}/spring-javaformat.vsix
+ vsix
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ update-version
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+ formatter-dependencies
+
+ true
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-shaded
+ ${project.version}
+
+
+
+
+
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/java/io/spring/format/vscode/VisualStudioCodeFormatter.java b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/java/io/spring/format/vscode/VisualStudioCodeFormatter.java
new file mode 100644
index 00000000..1c4178f5
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/java/io/spring/format/vscode/VisualStudioCodeFormatter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present 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.format.vscode;
+
+import java.io.File;
+
+import io.spring.javaformat.config.JavaFormatConfig;
+import io.spring.javaformat.formatter.StreamsFormatter;
+
+/**
+ * Called from the Visual Studio Code extension to format source code.
+ *
+ * @author Howard Zuo
+ * @author Phillip Webb
+ */
+public final class VisualStudioCodeFormatter {
+
+ private VisualStudioCodeFormatter() {
+ }
+
+ private void run(String[] args) throws Exception {
+ File location = new File(".").getAbsoluteFile();
+ log(String.format("Loading formatter from location '%s'", location));
+ JavaFormatConfig config = JavaFormatConfig.findFrom(location);
+ StreamsFormatter formatter = new StreamsFormatter(config);
+ formatter.format(System.in).writeTo((Appendable) System.out);
+ }
+
+ private void log(String message) {
+ System.err.println(message);
+ }
+
+ public static void main(String[] args) {
+ try {
+ new VisualStudioCodeFormatter().run(args);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/SpringDocumentFormattingEditProvider.ts b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/SpringDocumentFormattingEditProvider.ts
new file mode 100644
index 00000000..cd26b056
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/SpringDocumentFormattingEditProvider.ts
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-2023 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 path = require('path')
+import vscode = require('vscode')
+import childprocess = require('child_process')
+
+const JAR_PATH = path.resolve(__dirname, '..', 'runtime', 'spring-java-format.jar')
+
+export default class SpringDocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
+ provideDocumentFormattingEdits(
+ document: vscode.TextDocument,
+ options: vscode.FormattingOptions,
+ token: vscode.CancellationToken,
+ ): vscode.ProviderResult {
+ if (vscode.window.visibleTextEditors.every((editor) => editor.document.fileName !== document.fileName)) {
+ return []
+ }
+ return this.runFormatter(document, token).then(
+ (edits) => edits,
+ (err) => {
+ if (err) {
+ console.log(err)
+ return Promise.reject(`Check the console in dev tools to find errors when formatting spring-javaformat`)
+ }
+ },
+ )
+ }
+
+ private runFormatter(document: vscode.TextDocument, token: vscode.CancellationToken): Promise {
+ return new Promise((resolve, reject) => {
+ console.log(`formatting ${document.uri} using spring-javaformat`)
+ let stdout = ''
+ let stderr = ''
+ const cwd = path.dirname(document.fileName)
+ const args = ['-jar', JAR_PATH]
+ const process = childprocess.spawn('java', args, { cwd })
+ token.onCancellationRequested(() => !process.killed && process.kill())
+ process.stdout.setEncoding('utf8')
+ process.stdout.on('data', (data) => (stdout += data))
+ process.stderr.on('data', (data) => (stderr += data))
+ process.on('error', (err) => {
+ console.log(`spring-javaformat returned error ${err}`)
+ if (err && (err).code === 'ENOENT') {
+ return reject(`failed to find run spring-javaformat due to missing 'java' executable`)
+ }
+ })
+ process.on('close', (code) => {
+ if (code !== 0) {
+ console.log(`spring-javaformat returned error code ${code}`)
+ return reject(stderr)
+ }
+ console.log('spring-javaformat returned without error')
+ const fileStart = new vscode.Position(0, 0)
+ const fileEnd = document.lineAt(document.lineCount - 1).range.end
+ const textEdits: vscode.TextEdit[] = [new vscode.TextEdit(new vscode.Range(fileStart, fileEnd), stdout)]
+ return resolve(textEdits)
+ })
+ if (process.pid) {
+ console.log('sending document data to spring-javaformat')
+ process.stdin.end(document.getText())
+ }
+ })
+ }
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/extension.ts b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/extension.ts
new file mode 100644
index 00000000..3b4fb826
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/extension.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-2023 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 * as vscode from 'vscode'
+import SpringDocumentFormattingEditProvider from './SpringDocumentFormattingEditProvider'
+
+export function activate(context: vscode.ExtensionContext) {
+ console.log('Activated spring-javaformat extension')
+ context.subscriptions.push(
+ vscode.languages.registerDocumentFormattingEditProvider(
+ [
+ {
+ language: 'java',
+ scheme: 'file',
+ },
+ ],
+ new SpringDocumentFormattingEditProvider(),
+ ),
+ )
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/tsconfig.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/tsconfig.json
new file mode 100644
index 00000000..431716b1
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/main/typescript/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../../../out",
+ "rootDir": "."
+ }
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/runTest.ts b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/runTest.ts
new file mode 100644
index 00000000..19b689c6
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/runTest.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-2023 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 * as path from 'path'
+
+import { runTests } from '@vscode/test-electron'
+
+async function main() {
+ try {
+ const extensionDevelopmentPath = path.resolve(__dirname, '../../../../')
+ const extensionTestsPath = path.resolve(__dirname, './suite/index')
+ await runTests({ extensionDevelopmentPath, extensionTestsPath, launchArgs: ['--disable-extensions'] })
+ } catch (err) {
+ console.error('Failed to run tests')
+ process.exit(1)
+ }
+}
+
+main()
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/extension.test.ts b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/extension.test.ts
new file mode 100644
index 00000000..e73b4c89
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/extension.test.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017-2023 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 * as assert from 'assert'
+import * as vscode from 'vscode'
+import * as path from 'path'
+import * as fs from 'fs'
+
+export const WORKSPACE_PATH = path.resolve(__dirname, '..', '..', '..', 'test-workspace')
+export const FILE_PATH = path.resolve(WORKSPACE_PATH, 'Test.java')
+
+suite('Extension Test Suite', () => {
+ test('Format file', async () => {
+ const initial = 'public static class Test {public static void main(String[] args){}}\n'
+ const expected = 'public static class Test {\n\n\tpublic static void main(String[] args) {\n\t}\n\n}\n'
+ if (!fs.existsSync(WORKSPACE_PATH)) {
+ fs.mkdirSync(WORKSPACE_PATH)
+ }
+ fs.closeSync(fs.openSync(FILE_PATH, 'w'))
+ const document = await vscode.workspace.openTextDocument(vscode.Uri.file(FILE_PATH))
+ const editor = await vscode.window.showTextDocument(document)
+ await editor.edit((builder) => {
+ builder.delete(new vscode.Range(new vscode.Position(0, 0), document.positionAt(document.getText().length)))
+ builder.insert(new vscode.Position(0, 0), initial)
+ })
+ editor.selection = new vscode.Selection(0, 0, 0, 0)
+ await vscode.commands.executeCommand('editor.action.formatDocument')
+ const actual = document.getText()
+ assert.deepEqual(actual, expected)
+ })
+})
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/index.ts b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/index.ts
new file mode 100644
index 00000000..3301b793
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/suite/index.ts
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017-2023 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 * as path from 'path'
+import * as Mocha from 'mocha'
+import * as glob from 'glob'
+
+export function run(): Promise {
+ const mocha = new Mocha({
+ ui: 'tdd',
+ })
+ const testsRoot = path.resolve(__dirname, '..')
+ return new Promise((resolve, reject) => {
+ glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
+ console.log(files)
+ if (err) {
+ return reject(err)
+ }
+ files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)))
+ try {
+ mocha.run((failures) => {
+ if (failures > 0) {
+ reject(new Error(`${failures} tests failed.`))
+ } else {
+ resolve()
+ }
+ })
+ } catch (err) {
+ console.error(err)
+ reject(err)
+ }
+ })
+ })
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/tsconfig.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/tsconfig.json
new file mode 100644
index 00000000..7412944e
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/src/test/typescript/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../../../out/test",
+ "rootDirs": ["../../main/typescript", "."]
+ }
+}
diff --git a/samples/spring-javaformat-maven-sample/.springformat b/spring-javaformat-vscode/spring-javaformat-vscode-extension/test-workspace/Test.java
similarity index 100%
rename from samples/spring-javaformat-maven-sample/.springformat
rename to spring-javaformat-vscode/spring-javaformat-vscode-extension/test-workspace/Test.java
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig-base.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig-base.json
new file mode 100644
index 00000000..7c273362
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig-base.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "ES2020",
+ "lib": ["ES2020"],
+ "sourceMap": true,
+ "strict": true
+ }
+}
diff --git a/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig.json b/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig.json
new file mode 100644
index 00000000..a6df75bd
--- /dev/null
+++ b/spring-javaformat-vscode/spring-javaformat-vscode-extension/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [], // this root tsconfig just exists to compose sub-projects
+ "references": [
+ {
+ "path": "./src/main/typescript"
+ },
+ {
+ "path": "./src/test/typescript"
+ }
+ ]
+}
diff --git a/spring-javaformat/pom.xml b/spring-javaformat/pom.xml
index 0e0b747c..849cefc1 100644
--- a/spring-javaformat/pom.xml
+++ b/spring-javaformat/pom.xml
@@ -1,12 +1,12 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat-build
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformatpom
@@ -31,10 +31,18 @@
+ spring-javaformat-configspring-javaformat-checkstyle
+ spring-javaformat-formatter
+ spring-javaformat-formatter-test-support
+ spring-javaformat-formatter-testsspring-javaformat-formatter-eclipse-rewriter
+ spring-javaformat-formatter-eclipse-jdk8
+ spring-javaformat-formatter-eclipse-jdk17
+ spring-javaformat-formatter-eclipse-jdt-jdk8
+ spring-javaformat-formatter-eclipse-jdt-jdk17spring-javaformat-formatter-eclipse-runtime
- spring-javaformat-formatter-eclipse
- spring-javaformat-formatter
+ 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 53820f79..5605577e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/pom.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/pom.xml
@@ -1,11 +1,11 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-checkstyleSpring JavaFormat CheckStyle
@@ -14,6 +14,11 @@
+
+ io.spring.javaformat
+ spring-javaformat-config
+ ${project.version}
+ com.puppycrawl.toolscheckstyle
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/FilteredModuleFactory.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/FilteredModuleFactory.java
new file mode 100644
index 00000000..e595863f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/FilteredModuleFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.util.Set;
+
+import com.puppycrawl.tools.checkstyle.ModuleFactory;
+import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
+import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
+
+class FilteredModuleFactory implements ModuleFactory {
+
+ static final TreeWalkerFilter FILTERED = new TreeWalkerFilter() {
+
+ @Override
+ public boolean accept(TreeWalkerAuditEvent treeWalkerAuditEvent) {
+ return true;
+ }
+
+ };
+
+ private final ModuleFactory moduleFactory;
+
+ private final Set excludes;
+
+ FilteredModuleFactory(ModuleFactory moduleFactory, Set excludes) {
+ this.moduleFactory = moduleFactory;
+ this.excludes = excludes;
+ }
+
+ @Override
+ public Object createModule(String name) throws CheckstyleException {
+ Object module = this.moduleFactory.createModule(name);
+ if (isFiltered(module)) {
+ if (module instanceof AbstractCheck) {
+ return FILTERED;
+ }
+ throw new IllegalStateException("Unable to filter module " + module.getClass().getName());
+ }
+ return module;
+ }
+
+ boolean nonFiltered(Configuration configuration) {
+ return !isFiltered(configuration.getName());
+ }
+
+ private boolean isFiltered(Object module) {
+ return isFiltered(module.getClass().getName());
+ }
+
+ private boolean isFiltered(String name) {
+ return this.excludes != null && this.excludes.contains(name);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringChecks.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringChecks.java
index dff22639..244b7edf 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringChecks.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/SpringChecks.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -17,12 +17,16 @@
package io.spring.javaformat.checkstyle;
import java.io.File;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.stream.Collectors;
import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.DefaultContext;
@@ -34,9 +38,11 @@
import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
import com.puppycrawl.tools.checkstyle.api.FileText;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
-import com.puppycrawl.tools.checkstyle.filters.SuppressElement;
+import com.puppycrawl.tools.checkstyle.api.Violation;
+import com.puppycrawl.tools.checkstyle.filters.SuppressFilterElement;
+
import io.spring.javaformat.checkstyle.check.SpringHeaderCheck;
+import io.spring.javaformat.checkstyle.check.SpringImportOrderCheck;
/**
* {@link FileSetCheck} that applies Spring checkstype rules.
@@ -45,10 +51,6 @@
*/
public class SpringChecks extends AbstractFileSetCheck implements ExternalResourceHolder {
- private static final int DEFAULT_TAB_WIDTH = 8;
-
- private int tabWidth = DEFAULT_TAB_WIDTH;
-
private ClassLoader classLoader;
private ModuleFactory moduleFactory;
@@ -59,13 +61,13 @@ public class SpringChecks extends AbstractFileSetCheck implements ExternalResour
private String headerCopyrightPattern = SpringHeaderCheck.DEFAULT_HEADER_COPYRIGHT_PATTERN;
- /**
- * Sets tab width.
- * @param tabWidth the distance between tab stops
- */
- public void setTabWidth(int tabWidth) {
- this.tabWidth = tabWidth;
- }
+ private String headerFile;
+
+ private Set avoidStaticImportExcludes = Collections.emptySet();
+
+ private String projectRootPackage = SpringImportOrderCheck.DEFAULT_PROJECT_ROOT_PACKAGE;
+
+ private Set excludes;
/**
* Sets classLoader to load class.
@@ -85,16 +87,26 @@ public void setModuleFactory(ModuleFactory moduleFactory) {
@Override
public void finishLocalSetup() {
+ FilteredModuleFactory moduleFactory = new FilteredModuleFactory(this.moduleFactory, this.excludes);
DefaultContext context = new DefaultContext();
context.add("classLoader", this.classLoader);
context.add("severity", getSeverity());
- context.add("tabWidth", String.valueOf(this.tabWidth));
- context.add("moduleFactory", this.moduleFactory);
+ context.add("tabWidth", String.valueOf(getTabWidth()));
+ context.add("moduleFactory", moduleFactory);
Properties properties = new Properties();
- properties.put("headerType", this.headerType);
- properties.put("headerCopyrightPattern", this.headerCopyrightPattern);
- this.checks = new SpringConfigurationLoader(context, this.moduleFactory)
- .load(new PropertiesExpander(properties));
+ put(properties, "headerType", this.headerType);
+ put(properties, "headerCopyrightPattern", this.headerCopyrightPattern);
+ put(properties, "headerFile", this.headerFile);
+ put(properties, "projectRootPackage", this.projectRootPackage);
+ put(properties, "avoidStaticImportExcludes",
+ this.avoidStaticImportExcludes.stream().collect(Collectors.joining(",")));
+ this.checks = new SpringConfigurationLoader(context, moduleFactory).load(new PropertiesExpander(properties));
+ }
+
+ private void put(Properties properties, String name, Object value) {
+ if (value != null) {
+ properties.put(name, value);
+ }
}
@Override
@@ -102,8 +114,7 @@ public Set getExternalResourceLocations() {
Set locations = new LinkedHashSet<>();
for (FileSetCheck check : this.checks) {
if (check instanceof ExternalResourceHolder) {
- locations.addAll(
- ((ExternalResourceHolder) check).getExternalResourceLocations());
+ locations.addAll(((ExternalResourceHolder) check).getExternalResourceLocations());
}
}
return locations;
@@ -113,9 +124,8 @@ public Set getExternalResourceLocations() {
public void beginProcessing(String charset) {
super.beginProcessing(charset);
try {
- SuppressElement filter = new SuppressElement(
- "[\\\\/]src[\\\\/]test[\\\\/]java[\\\\/]", "Javadoc*", null, null,
- null, null);
+ SuppressFilterElement filter = new SuppressFilterElement("[\\\\/]src[\\\\/]test[\\\\/]java[\\\\/]",
+ "Javadoc*", null, null, null, null);
((Checker) getMessageDispatcher()).addFilter(filter);
}
catch (Exception ex) {
@@ -124,19 +134,17 @@ public void beginProcessing(String charset) {
}
@Override
- protected void processFiltered(File file, FileText fileText)
- throws CheckstyleException {
- SortedSet messages = new TreeSet<>();
+ protected void processFiltered(File file, FileText fileText) throws CheckstyleException {
+ SortedSet violations = new TreeSet<>();
for (FileSetCheck check : this.checks) {
- messages.addAll(check.process(file, fileText));
+ violations.addAll(check.process(file, fileText));
}
- addMessages(messages);
+ addViolations(violations);
}
@Override
public void setupChild(Configuration configuration) throws CheckstyleException {
- throw new CheckstyleException(
- "SpringChecks is not allowed as a parent of " + configuration.getName());
+ throw new CheckstyleException("SpringChecks is not allowed as a parent of " + configuration.getName());
}
public void setHeaderType(String headerType) {
@@ -147,4 +155,20 @@ public void setHeaderCopyrightPattern(String headerCopyrightPattern) {
this.headerCopyrightPattern = headerCopyrightPattern;
}
+ public void setHeaderFile(String headerFile) {
+ this.headerFile = headerFile;
+ }
+
+ public void setAvoidStaticImportExcludes(String[] avoidStaticImportExcludes) {
+ this.avoidStaticImportExcludes = new LinkedHashSet<>(Arrays.asList(avoidStaticImportExcludes));
+ }
+
+ public void setProjectRootPackage(String projectRootPackage) {
+ this.projectRootPackage = projectRootPackage;
+ }
+
+ public void setExcludes(String... excludes) {
+ this.excludes = new HashSet<>(Arrays.asList(excludes));
+ }
+
}
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 f2d7eb89..0be1ecc6 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,20 +16,26 @@
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;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader.IgnoredModulesOptions;
-import com.puppycrawl.tools.checkstyle.ModuleFactory;
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;
/**
@@ -42,27 +48,54 @@ class SpringConfigurationLoader {
private final Context context;
- private final ModuleFactory moduleFactory;
+ private final FilteredModuleFactory moduleFactory;
- SpringConfigurationLoader(Context context, ModuleFactory moduleFactory) {
+ SpringConfigurationLoader(Context context, FilteredModuleFactory moduleFactory) {
this.context = context;
this.moduleFactory = moduleFactory;
}
public Collection load(PropertyResolver propertyResolver) {
- Configuration config = loadConfiguration(
- getClass().getResourceAsStream("spring-checkstyle.xml"),
- propertyResolver);
- return Arrays.stream(config.getChildren()).map(this::load)
- .collect(Collectors.toList());
+ 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);
- return ConfigurationLoader.loadConfiguration(inputSource, propertyResolver,
- IgnoredModulesOptions.EXECUTE);
+ 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) {
throw new IllegalStateException(ex);
@@ -81,21 +114,21 @@ 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) {
- throw new IllegalStateException(
- "cannot initialize module " + name + " - " + ex.getMessage(), ex);
+ throw new IllegalStateException("cannot initialize module " + name + " - " + ex.getMessage(), ex);
}
}
- 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/AbstractSpringCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/AbstractSpringCheck.java
index 0f0743d0..af4511d2 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/AbstractSpringCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/AbstractSpringCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -36,4 +36,5 @@ public int[] getDefaultTokens() {
public int[] getRequiredTokens() {
return NO_REQUIRED_TOKENS;
}
+
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationAttributeConciseValueCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationAttributeConciseValueCheck.java
new file mode 100644
index 00000000..b8b0ad81
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationAttributeConciseValueCheck.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2017-present 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Spring-specific check of the concision of an annotation's attribute values.
+ *
+ * @author Andy Wilkinson
+ */
+public class SpringAnnotationAttributeConciseValueCheck extends AbstractCheck {
+
+ private final List imports = new ArrayList<>();
+
+ @Override
+ public int[] getDefaultTokens() {
+ return getRequiredTokens();
+ }
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return getRequiredTokens();
+ }
+
+ @Override
+ public int[] getRequiredTokens() {
+ return new int[] { TokenTypes.ANNOTATION, TokenTypes.IMPORT };
+ }
+
+ @Override
+ public void init() {
+ this.imports.clear();
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ if (ast.getType() == TokenTypes.IMPORT) {
+ visitImport(ast);
+ }
+ else if (ast.getType() == TokenTypes.ANNOTATION) {
+ visitAnnotation(ast);
+ }
+ }
+
+ private void visitImport(DetailAST importNode) {
+ List components = dotSeparatedComponents(importNode.getFirstChild());
+ if (components != null) {
+ this.imports.add(new ImportStatement(components));
+ }
+ }
+
+ private void visitAnnotation(DetailAST annotation) {
+ int valuePairCount = annotation.getChildCount(TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR);
+ if (valuePairCount == 0) {
+ DetailAST valueExpression = annotation.findFirstToken(TokenTypes.EXPR);
+ visitValueExpression(valueExpression, annotation, "value");
+ }
+ else {
+ DetailAST candidate = annotation.getFirstChild();
+ while (candidate != null) {
+ if (candidate.getType() == TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR) {
+ visitMemberValuePair(candidate);
+ }
+ candidate = candidate.getNextSibling();
+ }
+ }
+ }
+
+ private void visitMemberValuePair(DetailAST annotationValue) {
+ DetailAST annotation = annotationValue.getParent();
+ DetailAST attribute = annotationValue.findFirstToken(TokenTypes.IDENT);
+ DetailAST valueExpression = annotationValue.findFirstToken(TokenTypes.EXPR);
+ visitValueExpression(valueExpression, annotation, attribute.getText());
+ }
+
+ private void visitValueExpression(DetailAST valueExpression, DetailAST annotation, String attributeName) {
+ if (valueExpression == null || valueExpression.getChildCount() != 1) {
+ return;
+ }
+ List expressionComponents = dotSeparatedComponents(valueExpression.getFirstChild());
+ if (expressionComponents == null || expressionComponents.size() <= 2) {
+ return;
+ }
+ String outerTypeName = expressionComponents.get(0);
+ DetailAST annotationIdent = annotation.findFirstToken(TokenTypes.IDENT);
+ if (annotationIdent == null) {
+ return;
+ }
+ String annotationName = annotationIdent.getText();
+ if (outerTypeName.equals(annotationName)) {
+ String innerTypeName = expressionComponents.get(1);
+ if (!existingClashingImport(outerTypeName, innerTypeName)) {
+ String toImport = outerTypeName + "." + innerTypeName;
+ String replacement = String.join(".", expressionComponents.subList(1, expressionComponents.size()));
+ log(valueExpression.getLineNo(), valueExpression.getColumnNo(),
+ "annotation.attribute.overlyVerboseValue", attributeName, toImport, replacement);
+ }
+ }
+ }
+
+ private List dotSeparatedComponents(DetailAST ast) {
+ if (ast.getType() == TokenTypes.IDENT) {
+ return Collections.singletonList(ast.getText());
+ }
+ if (ast.getType() == TokenTypes.DOT) {
+ List left = dotSeparatedComponents(ast.getFirstChild());
+ List right = dotSeparatedComponents(ast.getLastChild());
+ if (left != null && right != null) {
+ List components = new ArrayList<>();
+ components.addAll(left);
+ components.addAll(right);
+ return components;
+ }
+ }
+ return null;
+ }
+
+ private boolean existingClashingImport(String outer, String inner) {
+ return this.imports.stream().filter((imported) -> imported.clashesWith(outer, inner)).findFirst().isPresent();
+ }
+
+ static class ImportStatement {
+
+ private final String imported;
+
+ ImportStatement(List components) {
+ this.imported = String.join(".", components);
+ }
+
+ boolean clashesWith(String outer, String inner) {
+ return this.imported.endsWith("." + inner) && !this.imported.endsWith("." + outer + "." + inner);
+ }
+
+ }
+
+}
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..c697521f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAnnotationLocationCheck.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017-present 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
new file mode 100644
index 00000000..b9b3c3e4
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringAvoidStaticImportCheck.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-present 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.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck;
+import com.puppycrawl.tools.checkstyle.checks.imports.AvoidStaticImportCheck;
+
+/**
+ * Spring variant of {@link AvoidStarImportCheck}.
+ *
+ * @author Phillip Webb
+ */
+public class SpringAvoidStaticImportCheck extends AvoidStaticImportCheck {
+
+ private static final Set ALWAYS_EXCLUDED;
+ static {
+ Set excludes = new LinkedHashSet<>();
+ 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.*");
+ excludes.add("org.hamcrest.Matchers.*");
+ excludes.add("org.junit.Assert.*");
+ excludes.add("org.junit.Assume.*");
+ excludes.add("org.junit.internal.matchers.ThrowableMessageMatcher.*");
+ excludes.add("org.junit.jupiter.api.Assertions.*");
+ excludes.add("org.junit.jupiter.api.Assumptions.*");
+ excludes.add("org.mockito.AdditionalMatchers.*");
+ excludes.add("org.mockito.ArgumentMatchers.*");
+ excludes.add("org.mockito.BDDMockito.*");
+ excludes.add("org.mockito.Matchers.*");
+ excludes.add("org.mockito.Mockito.*");
+ excludes.add("org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.*");
+ excludes.add("org.springframework.boot.configurationprocessor.TestCompiler.*");
+ excludes.add("org.springframework.boot.test.autoconfigure.AutoConfigurationImportedCondition.*");
+ excludes.add("org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*");
+ excludes.add("org.springframework.restdocs.headers.HeaderDocumentation.*");
+ excludes.add("org.springframework.restdocs.hypermedia.HypermediaDocumentation.*");
+ excludes.add("org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*");
+ excludes.add("org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*");
+ excludes.add("org.springframework.restdocs.operation.preprocess.Preprocessors.*");
+ excludes.add("org.springframework.restdocs.payload.PayloadDocumentation.*");
+ excludes.add("org.springframework.restdocs.request.RequestDocumentation.*");
+ excludes.add("org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.*");
+ excludes.add("org.springframework.restdocs.restassured.RestAssuredRestDocumentation.*");
+ excludes.add("org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*");
+ excludes.add("org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*");
+ excludes.add("org.springframework.restdocs.snippet.Attributes.*");
+ excludes.add("org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.*");
+ excludes.add("org.springframework.security.config.Customizer.*");
+ excludes.add("org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.*");
+ excludes.add("org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*");
+ excludes.add("org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*");
+ excludes.add("org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*");
+ excludes.add("org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*");
+ excludes.add("org.springframework.test.web.client.ExpectedCount.*");
+ excludes.add("org.springframework.test.web.client.match.MockRestRequestMatchers.*");
+ excludes.add("org.springframework.test.web.client.response.MockRestResponseCreators.*");
+ excludes.add("org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*");
+ excludes.add("org.springframework.test.web.servlet.result.MockMvcResultHandlers.*");
+ excludes.add("org.springframework.test.web.servlet.result.MockMvcResultMatchers.*");
+ excludes.add("org.springframework.test.web.servlet.setup.MockMvcBuilders.*");
+ excludes.add("org.springframework.web.reactive.function.BodyInserters.*");
+ excludes.add("org.springframework.web.reactive.function.server.RequestPredicates.*");
+ excludes.add("org.springframework.web.reactive.function.server.RouterFunctions.*");
+ excludes.add("org.springframework.web.servlet.function.RequestPredicates.*");
+ excludes.add("org.springframework.web.servlet.function.RouterFunctions.*");
+ excludes.add("org.springframework.ws.test.client.RequestMatchers.*");
+ excludes.add("org.springframework.ws.test.client.ResponseCreators.*");
+ ALWAYS_EXCLUDED = Collections.unmodifiableSet(excludes);
+ }
+
+ public SpringAvoidStaticImportCheck() {
+ setExcludes(ALWAYS_EXCLUDED.toArray(new String[0]));
+ }
+
+ @Override
+ public void setExcludes(String... excludes) {
+ Set merged = new LinkedHashSet<>(ALWAYS_EXCLUDED);
+ merged.addAll(Arrays.asList(excludes));
+ super.setExcludes(merged.toArray(new String[0]));
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringCatchCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringCatchCheck.java
index b0725cde..81d2144b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringCatchCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringCatchCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -60,6 +60,9 @@ private void checkIdent(DetailAST ast) {
if (text.length() == 1) {
log(ast.getLineNo(), ast.getColumnNo(), "catch.singleLetter");
}
+ if (text.toLowerCase().equals("o_o")) {
+ log(ast.getLineNo(), ast.getColumnNo(), "catch.wideEye");
+ }
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringDeprecatedCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringDeprecatedCheck.java
new file mode 100644
index 00000000..42bf0f4b
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringDeprecatedCheck.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-present 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 com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Checks that {@link Deprecated @Deprecated} annotations follow Spring conventions.
+ *
+ * @author Andy Wilkinson
+ * @since 0.0.35
+ */
+public class SpringDeprecatedCheck extends AbstractSpringCheck {
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return new int[] { TokenTypes.ANNOTATION };
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ if (ast.getType() == TokenTypes.ANNOTATION) {
+ visitAnnotation(ast);
+ }
+ }
+
+ private void visitAnnotation(DetailAST annotation) {
+ String text = FullIdent.createFullIdent(annotation.findFirstToken(TokenTypes.AT).getNextSibling()).getText();
+ if ("Deprecated".equals(text) || "java.lang.Deprecated".equals(text)) {
+ visitDeprecated(annotation);
+ }
+ }
+
+ private void visitDeprecated(DetailAST deprecated) {
+ DetailAST sinceAttribute = findSinceAttribute(deprecated);
+ if (sinceAttribute == null) {
+ log(deprecated.getLineNo(), deprecated.getColumnNo(), "deprecated.missingSince");
+ }
+ else {
+ DetailAST expr = sinceAttribute.findFirstToken(TokenTypes.EXPR);
+ DetailAST sinceLiteral = expr.findFirstToken(TokenTypes.STRING_LITERAL);
+ if ("\"\"".equals(sinceLiteral.getText())) {
+ log(deprecated.getLineNo(), deprecated.getColumnNo(), "deprecated.emptySince");
+ }
+ }
+ }
+
+ private DetailAST findSinceAttribute(DetailAST deprecated) {
+ DetailAST child = deprecated.getFirstChild();
+ while (child != null) {
+ if (child.getType() == TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR) {
+ DetailAST attributeIdent = child.findFirstToken(TokenTypes.IDENT);
+ if (attributeIdent != null && ("since".equals(attributeIdent.getText()))) {
+ return child;
+ }
+ }
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHeaderCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHeaderCheck.java
index 086eab26..c58e74c4 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHeaderCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHeaderCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -23,6 +23,10 @@
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@@ -57,14 +61,24 @@ public class SpringHeaderCheck extends AbstractFileSetCheck {
/**
* The default header copyright pattern.
*/
- public static final String DEFAULT_HEADER_COPYRIGHT_PATTERN = "20\\d\\d-20\\d\\d";
+ public static final String DEFAULT_HEADER_COPYRIGHT_PATTERN = "20\\d\\d(-20\\d\\d|-present)?";
+
+ private static final String DEFAULT_CHARSET = System.getProperty("file.encoding", StandardCharsets.UTF_8.name());
+
+ private String charset = DEFAULT_CHARSET;
private String headerType = DEFAULT_HEADER_TYPE;
+ private URI headerFile;
+
private String headerCopyrightPattern = DEFAULT_HEADER_COPYRIGHT_PATTERN;
private String packageInfoHeaderType;
+ private URI packageInfoHeaderFile;
+
+ private boolean blankLineAfter = true;
+
private HeaderCheck check;
private HeaderCheck packageInfoCheck;
@@ -72,29 +86,31 @@ public class SpringHeaderCheck extends AbstractFileSetCheck {
@Override
protected void finishLocalSetup() throws CheckstyleException {
try {
- this.check = createCheck(this.headerType);
- this.packageInfoCheck = createCheck(this.packageInfoHeaderType != null
- ? this.packageInfoHeaderType : this.headerType);
+ this.check = createCheck(this.headerType, this.headerFile);
+ String packageInfoHeaderType = this.packageInfoHeaderType != null ? this.packageInfoHeaderType
+ : this.headerType;
+ URI packageInfoHeaderFile = this.packageInfoHeaderFile != null ? this.packageInfoHeaderFile
+ : this.headerFile;
+ this.packageInfoCheck = createCheck(packageInfoHeaderType, packageInfoHeaderFile);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
- private HeaderCheck createCheck(String headerType) throws IOException {
+ private HeaderCheck createCheck(String headerType, URI headerFile) throws IOException {
if (UNCHECKED.equals(headerType)) {
return HeaderCheck.NONE;
}
if (NONE.equals(headerType)) {
return new NoHeaderCheck();
}
- return new RegexHeaderCheck(headerType, this.headerCopyrightPattern);
+ return new RegexHeaderCheck(headerType, headerFile);
}
@Override
- protected void processFiltered(File file, FileText fileText)
- throws CheckstyleException {
- getCheck(file).run(fileText);
+ protected void processFiltered(File file, FileText fileText) throws CheckstyleException {
+ getCheck(file).run(fileText, this.blankLineAfter);
}
private HeaderCheck getCheck(File file) {
@@ -104,10 +120,21 @@ private HeaderCheck getCheck(File file) {
return this.check;
}
+ public void setCharset(String charset) throws UnsupportedEncodingException {
+ if (!Charset.isSupported(charset)) {
+ throw new UnsupportedEncodingException("unsupported charset: '" + charset + "'");
+ }
+ this.charset = charset;
+ }
+
public void setHeaderType(String headerType) {
this.headerType = headerType;
}
+ public void setHeaderFile(URI headerFile) throws CheckstyleException {
+ this.headerFile = headerFile;
+ }
+
public void setHeaderCopyrightPattern(String headerCopyrightPattern) {
this.headerCopyrightPattern = headerCopyrightPattern;
}
@@ -116,6 +143,14 @@ public void setPackageInfoHeaderType(String packageInfoHeaderType) {
this.packageInfoHeaderType = packageInfoHeaderType;
}
+ public void setPackageInfoHeaderFile(URI packageInfoHeaderFile) {
+ this.packageInfoHeaderFile = packageInfoHeaderFile;
+ }
+
+ public void setBlankLineAfter(boolean blankLineAfter) {
+ this.blankLineAfter = blankLineAfter;
+ }
+
/**
* Interface used to check for a header.
*/
@@ -124,14 +159,15 @@ private interface HeaderCheck {
/**
* Don't run any checks.
*/
- HeaderCheck NONE = (fileText) -> true;
+ HeaderCheck NONE = (fileText, blankLineAfter) -> true;
/**
* Run the check.
* @param fileText the text to check
+ * @param blankLineAfter if a blank line should be after the header
* @return {@code true} if the header is valid
*/
- boolean run(FileText fileText);
+ boolean run(FileText fileText, boolean blankLineAfter);
}
@@ -142,19 +178,25 @@ private class RegexHeaderCheck implements HeaderCheck {
private final List lines;
- RegexHeaderCheck(String type, String copyrightPattern) throws IOException {
+ RegexHeaderCheck(String type, URI file) throws IOException {
+ this.lines = loadLines(openInputStream(type, file));
+ }
+
+ private InputStream openInputStream(String type, URI file) throws IOException {
+ if (file != null) {
+ return file.toURL().openStream();
+ }
String name = "header-" + type + ".txt";
InputStream inputStream = SpringHeaderCheck.class.getResourceAsStream(name);
if (inputStream == null) {
throw new IllegalStateException("Unknown header type " + type);
}
- this.lines = loadLines(inputStream, copyrightPattern);
+ return inputStream;
}
- private List loadLines(InputStream inputStream, String copyrightPattern)
- throws IOException {
+ private List loadLines(InputStream inputStream) throws IOException {
inputStream = new BufferedInputStream(inputStream);
- try (Reader reader = new InputStreamReader(inputStream, "UTF-8")) {
+ try (Reader reader = new InputStreamReader(inputStream, SpringHeaderCheck.this.charset)) {
LineNumberReader lineReader = new LineNumberReader(reader);
List lines = new ArrayList<>();
while (true) {
@@ -162,7 +204,7 @@ private List loadLines(InputStream inputStream, String copyrightPattern
if (line == null) {
return lines;
}
- lines.add(loadLine(line, copyrightPattern));
+ lines.add(loadLine(line, SpringHeaderCheck.this.headerCopyrightPattern));
}
}
}
@@ -174,7 +216,7 @@ private Pattern loadLine(String line, String copyrightPattern) {
}
@Override
- public boolean run(FileText fileText) {
+ public boolean run(FileText fileText, boolean blankLineAfter) {
if (this.lines.size() > fileText.size()) {
log(1, RegexpHeaderCheck.MSG_HEADER_MISSING);
return false;
@@ -187,6 +229,11 @@ public boolean run(FileText fileText) {
return false;
}
}
+ if (blankLineAfter) {
+ if (fileText.size() <= this.lines.size() || !"".equals(fileText.get(this.lines.size()))) {
+ log(this.lines.size() + 1, "header.blankLine");
+ }
+ }
return true;
}
@@ -198,7 +245,7 @@ public boolean run(FileText fileText) {
private class NoHeaderCheck implements HeaderCheck {
@Override
- public boolean run(FileText fileText) {
+ public boolean run(FileText fileText, boolean blankLineAfter) {
for (int i = 0; i < fileText.size(); i++) {
String fileLine = fileText.get(i);
if (fileLine.trim().isEmpty()) {
@@ -214,8 +261,7 @@ public boolean run(FileText fileText) {
}
private boolean isHeaderComment(String fileLine) {
- return (fileLine.contains("/*") || fileLine.contains("//"))
- && !fileLine.contains("/**");
+ return (fileLine.contains("/*") || fileLine.contains("//")) && !fileLine.contains("/**");
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHideUtilityClassConstructor.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHideUtilityClassConstructor.java
new file mode 100644
index 00000000..882b9b9a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringHideUtilityClassConstructor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present 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.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.checks.design.HideUtilityClassConstructorCheck;
+import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;
+
+/**
+ * Extension to {@link HideUtilityClassConstructorCheck} that doesn't fail certain common
+ * Spring patterns.
+ *
+ * @author Phillip Webb
+ */
+public class SpringHideUtilityClassConstructor extends HideUtilityClassConstructorCheck {
+
+ private static final Set BYPASS_ANNOTATIONS;
+ static {
+ Set annotations = new LinkedHashSet<>();
+ annotations.add("org.springframework.context.annotation.Configuration");
+ annotations.add("org.springframework.boot.autoconfigure.SpringBootApplication");
+ annotations.add("org.springframework.boot.autoconfigure.EnableAutoConfiguration");
+ Set shortNames = annotations.stream()
+ .map((name) -> name.substring(name.lastIndexOf(".") + 1))
+ .collect(Collectors.toSet());
+ annotations.addAll(shortNames);
+ BYPASS_ANNOTATIONS = Collections.unmodifiableSet(annotations);
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ if (!isBypassed(ast)) {
+ super.visitToken(ast);
+ }
+ }
+
+ private boolean isBypassed(DetailAST ast) {
+ for (String bypassAnnotation : BYPASS_ANNOTATIONS) {
+ if (AnnotationUtil.containsAnnotation(ast, bypassAnnotation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringImportOrderCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringImportOrderCheck.java
new file mode 100644
index 00000000..69f8bf31
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringImportOrderCheck.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-present 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 com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck;
+
+/**
+ * Checks that the order of imports follow Spring conventions.
+ *
+ * @author Vedran Pavic
+ */
+public class SpringImportOrderCheck extends ImportOrderCheck {
+
+ /**
+ * The default root package.
+ */
+ public static final String DEFAULT_PROJECT_ROOT_PACKAGE = "org.springframework";
+
+ public SpringImportOrderCheck() {
+ setProjectRootPackage(DEFAULT_PROJECT_ROOT_PACKAGE);
+ setOrdered(true);
+ setSeparated(true);
+ setOption("bottom");
+ setSortStaticImportsAlphabetically(true);
+ }
+
+ public void setProjectRootPackage(String projectRootPackage) {
+ setGroups("java", "/^javax?\\./", "*", projectRootPackage);
+ }
+
+}
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
new file mode 100644
index 00000000..722c8868
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2017-present 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.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;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;
+
+/**
+ * Checks that JUnit 5 conventions are followed and that JUnit 4 is not accidentally used.
+ *
+ * @author Phillip Webb
+ */
+public class SpringJUnit5Check extends AbstractSpringCheck {
+
+ private static final String JUNIT4_TEST_ANNOTATION_NAME = "org.junit.Test";
+
+ private static final List TEST_ANNOTATIONS;
+ static {
+ 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;
+ static {
+ 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_NAME);
+ bannedImports.add("org.junit.After");
+ bannedImports.add("org.junit.AfterClass");
+ bannedImports.add("org.junit.Before");
+ bannedImports.add("org.junit.BeforeClass");
+ bannedImports.add("org.junit.Rule");
+ bannedImports.add("org.junit.ClassRule");
+ BANNED_IMPORTS = Collections.unmodifiableSet(bannedImports);
+ }
+
+ private List unlessImports = new ArrayList<>();
+
+ private final List testMethods = new ArrayList<>();
+
+ private final Map imports = new LinkedHashMap<>();
+
+ 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, 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
+ 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 (containsAnnotation(ast, TEST_ANNOTATIONS)) {
+ this.testMethods.add(ast);
+ }
+ 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()) {
+ check();
+ }
+ }
+
+ private boolean shouldCheck() {
+ if (this.testMethods.isEmpty() && this.lifecycleMethods.isEmpty() && this.nestedTestClasses.isEmpty()) {
+ return false;
+ }
+ for (String unlessImport : this.unlessImports) {
+ if (this.imports.containsKey(unlessImport)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ 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) {
+ log(ident.getLineNo(), ident.getColumnNo(), "junit5.bannedImport", bannedImport);
+ }
+ }
+ for (DetailAST testMethod : this.testMethods) {
+ if (AnnotationUtil.containsAnnotation(testMethod, JUNIT4_TEST_ANNOTATION_NAME)) {
+ log(testMethod, "junit5.bannedTestAnnotation");
+ }
+ }
+ checkVisibility(this.testMethods, "junit5.testPublicMethod", "junit5.testPrivateMethod");
+ checkVisibility(this.lifecycleMethods, "junit5.lifecyclePublicMethod", "junit5.lifecyclePrivateMethod");
+ }
+
+ 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(ast, publicMessageKey);
+ }
+ if ((privateMessageKey != null) && (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null)) {
+ log(ast, privateMessageKey);
+ }
+ }
+ }
+
+ 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) {
+ this.unlessImports = Collections
+ .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/SpringJavadocCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJavadocCheck.java
index 0e9d9a65..56f7ea63 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJavadocCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJavadocCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,10 +16,18 @@
package io.spring.javaformat.checkstyle.check;
+import java.util.ArrayList;
+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.regex.Matcher;
import java.util.regex.Pattern;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FileContents;
import com.puppycrawl.tools.checkstyle.api.TextBlock;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
@@ -30,53 +38,345 @@
*/
public class SpringJavadocCheck extends AbstractSpringCheck {
- private static final Pattern[] PATTERNS = { Pattern.compile("@param\\s+\\S+\\s+(.*)"),
- Pattern.compile("@throws\\s+\\S+\\s+(.*)"),
- Pattern.compile("@return\\s+(.*)") };
+ private static final List CASE_CHECKED_TAG_PATTERNS;
+ static {
+ List patterns = new ArrayList<>();
+ patterns.add(Pattern.compile("@param\\s+\\S+\\s+(.*)"));
+ patterns.add(Pattern.compile("@throws\\s+\\S+\\s+(.*)"));
+ patterns.add(Pattern.compile("@return\\s+(.*)"));
+ CASE_CHECKED_TAG_PATTERNS = Collections.unmodifiableList(patterns);
+ }
+
+ private static final List BANNED_TAGS;
+ static {
+ List patterns = new ArrayList<>();
+ patterns.add(Pattern.compile("(@soundtrack)\\s+.*"));
+ BANNED_TAGS = Collections.unmodifiableList(patterns);
+ }
+
+ private static final Pattern SINCE_TAG_PATTERN = Pattern.compile("@since\\s+(.*)");
+
+ private static final Pattern AT_TAG_PATTERN = Pattern.compile("[^{]@\\w+\\s+.*");
+
+ private static final Pattern NON_JAVADOC_COMMENT = Pattern.compile("\\(non-Javadoc\\)", Pattern.CASE_INSENSITIVE);
+
+ private static final Set TOP_LEVEL_TYPES;
+ static {
+ Set topLevelTypes = new HashSet();
+ topLevelTypes.add(TokenTypes.INTERFACE_DEF);
+ topLevelTypes.add(TokenTypes.CLASS_DEF);
+ topLevelTypes.add(TokenTypes.ENUM_DEF);
+ topLevelTypes.add(TokenTypes.ANNOTATION_DEF);
+ TOP_LEVEL_TYPES = Collections.unmodifiableSet(topLevelTypes);
+ }
+
+ private boolean requireSinceTag;
+
+ private boolean publicOnlySinceTags;
+
+ private boolean allowNonJavadocComments;
+
+ private Map blockComments;
@Override
public int[] getDefaultTokens() {
- return new int[] { TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF,
- TokenTypes.ENUM_DEF, TokenTypes.ANNOTATION_DEF, TokenTypes.METHOD_DEF,
- TokenTypes.CTOR_DEF };
+ return new int[] { TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF,
+ TokenTypes.ANNOTATION_DEF, TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF, TokenTypes.ANNOTATION_FIELD_DEF };
}
@Override
public int[] getAcceptableTokens() {
- return new int[] { TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF,
- TokenTypes.ENUM_DEF, TokenTypes.ANNOTATION_DEF, TokenTypes.METHOD_DEF,
- TokenTypes.CTOR_DEF, TokenTypes.ENUM_CONSTANT_DEF,
+ return new int[] { TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF,
+ TokenTypes.ANNOTATION_DEF, TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF, TokenTypes.ENUM_CONSTANT_DEF,
TokenTypes.ANNOTATION_FIELD_DEF };
}
+ @Override
+ public void beginTree(DetailAST rootAST) {
+ super.beginTree(rootAST);
+ this.blockComments = new HashMap<>();
+ FileContents contents = getFileContents();
+ for (List blockComments : contents.getBlockComments().values()) {
+ for (TextBlock blockComment : blockComments) {
+ this.blockComments.put(blockComment.getEndLineNo(), blockComment);
+ }
+ }
+ }
+
@Override
public void visitToken(DetailAST ast) {
int lineNumber = ast.getLineNo();
TextBlock javadoc = getFileContents().getJavadocBefore(lineNumber);
if (javadoc != null) {
- checkParamTags(javadoc);
+ checkJavadoc(ast, javadoc);
+ }
+ if (!this.allowNonJavadocComments) {
+ checkForNonJavadocComments(javadoc);
+ checkForNonJavadocComments(getBlockCommentBefore(lineNumber));
+ }
+ }
+
+ public TextBlock getBlockCommentBefore(int lineNoBefore) {
+ FileContents contents = getFileContents();
+ int lineNo = lineNoBefore - 1;
+ while (lineNo > 0 && (contents.lineIsBlank(lineNo) || contents.lineIsComment(lineNo))) {
+ lineNo--;
+ }
+ return this.blockComments.get(lineNo);
+ }
+
+ private void checkJavadoc(DetailAST ast, TextBlock javadoc) {
+ checkBannedTags(ast, javadoc);
+ checkTagCase(ast, javadoc);
+ checkSinceTag(ast, javadoc);
+ checkMethodJavaDoc(ast, javadoc);
+ checkAnnotationFieldJavaDoc(ast, javadoc);
+ }
+
+ private void checkBannedTags(DetailAST ast, TextBlock javadoc) {
+ String[] text = javadoc.getText();
+ for (int i = 0; i < text.length; i++) {
+ for (Pattern pattern : BANNED_TAGS) {
+ Matcher matcher = pattern.matcher(text[i]);
+ if (matcher.find()) {
+ String tagName = matcher.group(1).trim();
+ log(javadoc.getStartLineNo() + i, tagName.length(), "javadoc.bannedTag", tagName);
+ }
+ }
}
}
- private void checkParamTags(TextBlock javadoc) {
+ private void checkTagCase(DetailAST ast, TextBlock javadoc) {
String[] text = javadoc.getText();
for (int i = 0; i < text.length; i++) {
- for (Pattern pattern : PATTERNS) {
+ for (Pattern pattern : CASE_CHECKED_TAG_PATTERNS) {
Matcher matcher = pattern.matcher(text[i]);
if (matcher.find()) {
String description = matcher.group(1).trim();
if (startsWithUppercase(description)) {
- log(javadoc.getStartLineNo() + i,
- text[i].length() - description.length(),
- "javadoc.badCase");
+ log(javadoc.getStartLineNo() + i, text[i].length() - description.length(), "javadoc.badCase");
}
}
}
}
}
+ private void checkSinceTag(DetailAST ast, TextBlock javadoc) {
+ if (!TOP_LEVEL_TYPES.contains(ast.getType())) {
+ return;
+ }
+ DetailAST interfaceOrAnnotationDef = getInterfaceOrAnnotationDef(ast);
+ boolean privateType = !isPublicOrProtected(ast)
+ && (interfaceOrAnnotationDef == null || !isPublicOrProtected(interfaceOrAnnotationDef));
+ SinceTag sinceTag = SinceTag.find(ast, javadoc);
+ if (sinceTag != null) {
+ if (this.publicOnlySinceTags && privateType) {
+ log(sinceTag.lineNumber, sinceTag.columnNumber, "javadoc.publicSince");
+ }
+ else {
+ checkContainingSince(ast, sinceTag);
+ }
+ }
+ else {
+ boolean innerType = ast.getParent() != null && ast.getParent().getType() != TokenTypes.COMPILATION_UNIT;
+ if (this.requireSinceTag && !innerType && sinceTag == null && !(this.publicOnlySinceTags && privateType)) {
+ log(javadoc.getStartLineNo(), 0, "javadoc.missingSince");
+ }
+ }
+ }
+
+ private void checkContainingSince(DetailAST ast, SinceTag currentTag) {
+ SinceTag containingSince = findContainingSince(ast);
+ if (containingSince != null) {
+ SinceVersion current = currentTag.version;
+ SinceVersion container = containingSince.version;
+ if (current != SinceVersion.UNKNOWN && container != SinceVersion.UNKNOWN) {
+ int comparison = current.compareTo(container);
+ if (comparison < 0) {
+ log(currentTag.lineNumber, currentTag.columnNumber, "javadoc.earlierSince", current, container, containingSince.lineNumber, containingSince.columnNumber);
+ }
+ else if (comparison == 0) {
+ log(currentTag.lineNumber, currentTag.columnNumber, "javadoc.sameSince", current, containingSince.lineNumber, containingSince.columnNumber);
+ }
+ }
+ }
+ }
+
+ private SinceTag findContainingSince(DetailAST ast) {
+ DetailAST parent = ast.getParent();
+ while (parent != null && parent.getType() != TokenTypes.COMPILATION_UNIT) {
+ TextBlock javadoc = getFileContents().getJavadocBefore(parent.getLineNo());
+ if (javadoc != null) {
+ SinceTag sinceTag = SinceTag.find(ast, javadoc);
+ if (sinceTag != null) {
+ return sinceTag;
+ }
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ private void checkMethodJavaDoc(DetailAST ast, TextBlock javadoc) {
+ if (TokenTypes.METHOD_DEF != ast.getType()) {
+ return;
+ }
+ String[] text = javadoc.getText();
+ for (int i = 0; i < text.length; i++) {
+ Matcher matcher = AT_TAG_PATTERN.matcher(text[i]);
+ if (matcher.find() && i > 0 && text[i - 1].trim().equals("*")) {
+ log(javadoc.getStartLineNo() + i - 1, 0, "javadoc.emptyLineBeforeTag");
+ }
+ }
+ SinceTag sinceTag = SinceTag.find(ast, javadoc);
+ if (sinceTag != null) {
+ checkContainingSince(ast, sinceTag);
+ }
+ }
+
+ private void checkAnnotationFieldJavaDoc(DetailAST ast, TextBlock javadoc) {
+ if (TokenTypes.ANNOTATION_FIELD_DEF != ast.getType()) {
+ return;
+ }
+ SinceTag sinceTag = SinceTag.find(ast, javadoc);
+ if (sinceTag != null) {
+ checkContainingSince(ast, sinceTag);
+ }
+ }
+
private boolean startsWithUppercase(String description) {
return description.length() > 0 && Character.isUpperCase(description.charAt(0));
}
+ private void checkForNonJavadocComments(TextBlock block) {
+ if (block == null) {
+ return;
+ }
+ String[] text = block.getText();
+ for (int i = 0; i < text.length; i++) {
+ if (NON_JAVADOC_COMMENT.matcher(text[i]).find()) {
+ log(block.getStartLineNo() + i - 1, 0, "javadoc.nonJavadocComment");
+ }
+ }
+ }
+
+ public void setRequireSinceTag(boolean requireSinceTag) {
+ this.requireSinceTag = requireSinceTag;
+ }
+
+ public void setPublicOnlySinceTags(boolean publicOnlySinceTags) {
+ this.publicOnlySinceTags = publicOnlySinceTags;
+ }
+
+ public void setAllowNonJavadocComments(boolean allowNonJavadocComments) {
+ this.allowNonJavadocComments = allowNonJavadocComments;
+ }
+
+ private DetailAST getInterfaceOrAnnotationDef(DetailAST ast) {
+ return findParent(ast, TokenTypes.INTERFACE_DEF, TokenTypes.ANNOTATION_DEF);
+ }
+
+ private DetailAST findParent(DetailAST ast, int... classDefs) {
+ while (ast != null) {
+ for (int classDef : classDefs) {
+ if (ast.getType() == classDef) {
+ return ast;
+ }
+ }
+ ast = ast.getParent();
+ }
+ return null;
+ }
+
+ private boolean isPublicOrProtected(DetailAST ast) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+ if (modifiers == null) {
+ return false;
+ }
+ return modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
+ || modifiers.findFirstToken(TokenTypes.LITERAL_PROTECTED) != null;
+ }
+
+ private static final class SinceTag {
+
+ private final int lineNumber;
+
+ private final int columnNumber;
+
+ private final SinceVersion version;
+
+ private SinceTag(int lineNumber, int columnNumber, SinceVersion version) {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ this.version = version;
+ }
+
+ private static SinceTag find(DetailAST ast, TextBlock javadoc) {
+ String[] text = javadoc.getText();
+ for (int i = 0; i < text.length; i++) {
+ Matcher matcher = SINCE_TAG_PATTERN.matcher(text[i]);
+ if (matcher.find()) {
+ String description = matcher.group(1).trim();
+ return new SinceTag(javadoc.getStartLineNo() + i, text[i].length() - description.length(), SinceVersion.of(description));
+ }
+ }
+ return null;
+ }
+ }
+
+ private static final class SinceVersion implements Comparable {
+
+ private static final SinceVersion UNKNOWN = new SinceVersion(-1, -1, -1, "unknown");
+
+ private static final Pattern DATE_PATTERN = Pattern.compile("[0-3][0-9]\\.[0-1][0-9]\\.20[0-2][0-9]");
+
+ private final int major;
+
+ private final int minor;
+
+ private final int patch;
+
+ private final String text;
+
+ private SinceVersion(int major, int minor, int patch, String text) {
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ this.text = text;
+ }
+
+ private static SinceVersion of(String text) {
+ if (DATE_PATTERN.matcher(text).matches()) {
+ return UNKNOWN;
+ }
+ try {
+ String[] components = text.split("\\.");
+ int major = (components.length > 0) ? Integer.parseInt(components[0]) : 0;
+ int minor = (components.length > 1) ? Integer.parseInt(components[1]) : 0;
+ int patch = (components.length > 2) ? Integer.parseInt(components[2]) : 0;
+ return new SinceVersion(major, minor, patch, text);
+ }
+ catch (NumberFormatException ex) {
+ return UNKNOWN;
+ }
+ }
+
+ public String toString() {
+ return this.text;
+ }
+
+ @Override
+ public int compareTo(SinceVersion other) {
+ int diff = this.major - other.major;
+ if (diff == 0) {
+ diff = this.minor - other.minor;
+ if (diff == 0) {
+ diff = this.patch - other.patch;
+ }
+ }
+ return diff;
+ }
+
+ }
+
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLambdaCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLambdaCheck.java
index ea88c887..c0f45f07 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLambdaCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLambdaCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -38,7 +38,8 @@ public int[] getAcceptableTokens() {
@Override
public void visitToken(DetailAST ast) {
- if (ast.getType() == TokenTypes.LAMBDA) {
+ if (ast.getType() == TokenTypes.LAMBDA && ast.getParent() != null
+ && ast.getParent().getType() != TokenTypes.SWITCH_RULE) {
visitLambda(ast);
}
}
@@ -51,22 +52,34 @@ private void visitLambda(DetailAST lambda) {
}
else if (!this.singleArgumentParentheses && hasParentheses) {
if (!isUsingParametersToDefineType(lambda)) {
- log(lambda.getLineNo(), lambda.getColumnNo(),
- "lambda.unnecessaryParen");
+ log(lambda.getLineNo(), lambda.getColumnNo(), "lambda.unnecessaryParen");
}
}
}
DetailAST block = lambda.getLastChild();
- if (isStatementList(block) && block.getChildCount(TokenTypes.SEMI) <= 1
- && !isNecessaryBlock(block)) {
+ int statements = countDescendantsOfType(block, TokenTypes.SEMI);
+ int requireBlock = countDescendantsOfType(block, TokenTypes.LCURLY, TokenTypes.LITERAL_THROW, TokenTypes.SLIST);
+ if (statements == 1 && requireBlock == 0) {
log(block.getLineNo(), block.getColumnNo(), "lambda.unnecessaryBlock");
}
}
+ private int countDescendantsOfType(DetailAST ast, int... types) {
+ int count = 0;
+ for (int type : types) {
+ count += ast.getChildCount(type);
+ }
+ DetailAST child = ast.getFirstChild();
+ while (child != null) {
+ count += countDescendantsOfType(child, types);
+ child = child.getNextSibling();
+ }
+ return count;
+ }
+
private boolean hasSingleParameter(DetailAST lambda) {
DetailAST parameters = lambda.findFirstToken(TokenTypes.PARAMETERS);
- return (parameters == null)
- || (parameters.getChildCount(TokenTypes.PARAMETER_DEF) == 1);
+ return (parameters == null) || (parameters.getChildCount(TokenTypes.PARAMETER_DEF) == 1);
}
private boolean isUsingParametersToDefineType(DetailAST lambda) {
@@ -77,31 +90,6 @@ private boolean isUsingParametersToDefineType(DetailAST lambda) {
return ast != null;
}
- private boolean isNecessaryBlock(DetailAST block) {
- DetailAST firstChild = block.getFirstChild();
- if (firstChild == null) {
- return false;
- }
- if (firstChild.getType() == TokenTypes.LITERAL_THROW) {
- return true;
- }
- if (block.getChildCount() == 1 && firstChild.getType() == TokenTypes.RCURLY) {
- return true;
- }
- DetailAST candidate = firstChild.getFirstChild();
- while (candidate != null) {
- if (isStatementList(candidate)) {
- return true;
- }
- candidate = candidate.getNextSibling();
- }
- return false;
- }
-
- private boolean isStatementList(DetailAST ast) {
- return ast != null && ast.getType() == TokenTypes.SLIST;
- }
-
private boolean hasToken(DetailAST ast, int type) {
return ast.findFirstToken(type) != null;
}
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
new file mode 100644
index 00000000..abeba9de
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringLeadingWhitespaceCheck.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-present 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.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;
+import java.util.regex.Pattern;
+
+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;
+
+/**
+ * Checks that leading whitespace matches the expected indentation style.
+ *
+ * @author Phillip Webb
+ */
+public class SpringLeadingWhitespaceCheck extends AbstractSpringCheck {
+
+ private static final Pattern PATTERN = Pattern.compile("^([\\ \\t]+)\\S");
+
+ private static final Map INDENTATION_STYLE_PATTERN;
+ static {
+ Map indentationStylePatterns = new HashMap<>();
+ indentationStylePatterns.put(IndentationStyle.TABS, Pattern.compile("\\t*"));
+ indentationStylePatterns.put(IndentationStyle.SPACES, Pattern.compile("\\ *"));
+ INDENTATION_STYLE_PATTERN = Collections.unmodifiableMap(indentationStylePatterns);
+ }
+
+ private IndentationStyle indentationStyle;
+
+ private final Deque textBlockPairs = new ArrayDeque<>();
+
+ @Override
+ public int[] getAcceptableTokens() {
+ 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();
+ if (file == null) {
+ return;
+ }
+ IndentationStyle indentationStyle = (this.indentationStyle != null) ? this.indentationStyle
+ : JavaFormatConfig.findFrom(file.getParentFile()).getIndentationStyle();
+ for (int i = 0; i < fileText.size(); 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
+ && fileContents.hasIntersectionWithComment(lineNo, matcher.start(0), lineNo, matcher.end(0) - 1)) {
+ found = matcher.find(matcher.end(0));
+ }
+ if (found && !INDENTATION_STYLE_PATTERN.get(indentationStyle).matcher(matcher.group(1)).matches()) {
+ 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) {
+ this.indentationStyle = (indentationStyle != null && !"".equals(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/SpringMethodOrderCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodOrderCheck.java
index d9ee57ff..bbb088bc 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodOrderCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodOrderCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -33,7 +33,7 @@
public class SpringMethodOrderCheck extends AbstractSpringCheck {
private static final List EXPECTED_ORDER = Collections
- .unmodifiableList(Arrays.asList("equals", "hashCode", "toString"));
+ .unmodifiableList(Arrays.asList("equals", "hashCode", "toString"));
@Override
public int[] getAcceptableTokens() {
@@ -59,15 +59,13 @@ public void visitToken(DetailAST ast) {
}
private void checkOrder(List methods) {
- List methodsNames = methods.stream().map(DetailAST::getText)
- .collect(Collectors.toList());
+ List methodsNames = methods.stream().map(DetailAST::getText).collect(Collectors.toList());
List expected = new ArrayList<>(EXPECTED_ORDER);
expected.retainAll(methodsNames);
for (int i = 0; i < methods.size(); i++) {
DetailAST method = methods.get(i);
if (!method.getText().equals(expected.get(i))) {
- log(method.getLineNo(), method.getColumnNo(), "methodorder.outOfOrder",
- method.getText(), expected);
+ log(method.getLineNo(), method.getColumnNo(), "methodorder.outOfOrder", method.getText(), expected);
}
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodVisibilityCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodVisibilityCheck.java
new file mode 100644
index 00000000..ca5bd3ef
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringMethodVisibilityCheck.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2017-present 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 com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Check for compliance with Spring-style method visibility. Checks that:
+ *
+ *
+ *
package-private and private classes do not have public methods
+ * unless they are also annotated with {@link Override @Override}
+ *
final classes do not have protected methods unless that are also
+ * annotated with {@link Override @Override}
+ *
+ *
+ * @author Phillip Webb
+ * @author Andy Wilkinson
+ */
+public class SpringMethodVisibilityCheck extends AbstractSpringCheck {
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return new int[] { TokenTypes.METHOD_DEF };
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+ if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null) {
+ visitPublicMethod(modifiers, ast);
+ }
+ else if (modifiers.findFirstToken(TokenTypes.LITERAL_PROTECTED) != null) {
+ visitProtectedMethod(modifiers, ast);
+ }
+ }
+
+ private void visitPublicMethod(DetailAST modifiers, DetailAST method) {
+ if (hasOverrideAnnotation(modifiers)) {
+ return;
+ }
+ DetailAST classDef = getClassDef(method.getParent());
+ if (classDef == null || isPublicOrProtected(classDef)) {
+ return;
+ }
+ DetailAST interfaceDef = getInterfaceDef(classDef.getParent());
+ if (interfaceDef != null && isPublicOrProtected(interfaceDef)) {
+ return;
+ }
+ DetailAST ident = method.findFirstToken(TokenTypes.IDENT);
+ log(ident.getLineNo(), ident.getColumnNo(), "methodvisibility.publicMethod", ident.getText());
+ }
+
+ private void visitProtectedMethod(DetailAST modifiers, DetailAST method) {
+ if (hasOverrideAnnotation(modifiers)) {
+ return;
+ }
+ DetailAST classDef = getClassDef(method.getParent());
+ if (classDef == null || !isFinal(classDef)) {
+ return;
+ }
+ DetailAST ident = method.findFirstToken(TokenTypes.IDENT);
+ log(ident.getLineNo(), ident.getColumnNo(), "methodvisibility.protectedMethodInFinalClass", ident.getText());
+ }
+
+ private boolean hasOverrideAnnotation(DetailAST modifiers) {
+ DetailAST candidate = modifiers.getFirstChild();
+ while (candidate != null) {
+ if (candidate.getType() == TokenTypes.ANNOTATION) {
+ DetailAST dot = candidate.findFirstToken(TokenTypes.DOT);
+ String name = (dot != null ? dot : candidate).findFirstToken(TokenTypes.IDENT).getText();
+ if ("Override".equals(name)) {
+ return true;
+ }
+ }
+ candidate = candidate.getNextSibling();
+ }
+ return false;
+ }
+
+ private DetailAST getClassDef(DetailAST ast) {
+ return findParent(ast, TokenTypes.CLASS_DEF);
+ }
+
+ private DetailAST getInterfaceDef(DetailAST ast) {
+ return findParent(ast, TokenTypes.INTERFACE_DEF);
+ }
+
+ private DetailAST findParent(DetailAST ast, int classDef) {
+ while (ast != null) {
+ if (ast.getType() == classDef) {
+ return ast;
+ }
+ ast = ast.getParent();
+ }
+ return null;
+ }
+
+ private boolean isPublicOrProtected(DetailAST ast) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+ if (modifiers == null) {
+ return false;
+ }
+ return modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
+ || modifiers.findFirstToken(TokenTypes.LITERAL_PROTECTED) != null;
+ }
+
+ private boolean isFinal(DetailAST ast) {
+ DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+ if (modifiers == null) {
+ return false;
+ }
+ return modifiers.findFirstToken(TokenTypes.FINAL) != null;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoThisCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoThisCheck.java
index d4d3f478..1a4ee466 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoThisCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoThisCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -53,8 +53,7 @@ private void visitIdent(DetailAST ast) {
DetailAST sibling = ast.getPreviousSibling();
if (sibling != null && sibling.getType() == TokenTypes.LITERAL_THIS) {
DetailAST parent = getFirstNonDotParent(ast);
- if (!(this.allowAssignement && parent != null
- && parent.getType() == TokenTypes.ASSIGN)) {
+ if (!(this.allowAssignement && parent != null && parent.getType() == TokenTypes.ASSIGN)) {
log(ast.getLineNo(), ast.getColumnNo(), "nothis.unexpected", name);
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoWhitespaceBeforeCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoWhitespaceBeforeCheck.java
new file mode 100644
index 00000000..f06a88c5
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNoWhitespaceBeforeCheck.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present 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 com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+import com.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceBeforeCheck;
+
+/**
+ * Spring-specific customization of {@link NoWhitespaceBeforeCheck} that permits
+ * whitespace before {@code ...} when it is a separator after an annotation, for
+ * example {@code int @Nullable ...}.
+ *
+ * @author Andy Wilkinson
+ */
+public class SpringNoWhitespaceBeforeCheck extends NoWhitespaceBeforeCheck {
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ if (ast.getType() != TokenTypes.ELLIPSIS) {
+ super.visitToken(ast);
+ }
+ else {
+ visitEllipsis(ast);
+ }
+ }
+
+ private void visitEllipsis(DetailAST ellipsis) {
+ DetailAST previousSibling = ellipsis.getPreviousSibling();
+ if (previousSibling.getType() == TokenTypes.TYPE &&
+ previousSibling.getChildCount() == 2 &&
+ previousSibling.getLastChild().getType() == TokenTypes.ANNOTATIONS) {
+ return;
+ }
+ super.visitToken(ellipsis);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNullabilityCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNullabilityCheck.java
new file mode 100644
index 00000000..4c48c381
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringNullabilityCheck.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2017-present 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.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Checks compliance with Spring team's nullability conventions. JSpecify annotations
+ * should be used to express nullability and type-use annotations ({@code @Nullable}
+ * and {@code @NonNull}) should appear immediately before a type.
+ *
+ * @author Andy Wilkinson
+ */
+public class SpringNullabilityCheck extends AbstractSpringCheck {
+
+ private final Set unwantedNullabilityImports = new HashSet<>();
+
+ private final List modifiers = new ArrayList<>();
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return new int[] { TokenTypes.IMPORT, TokenTypes.MODIFIERS };
+ }
+
+ @Override
+ public void beginTree(DetailAST rootAST) {
+ this.modifiers.clear();
+ this.unwantedNullabilityImports.clear();
+ }
+
+ @Override
+ public void finishTree(DetailAST rootAST) {
+ this.modifiers.forEach(this::visitModifiers);
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ switch (ast.getType()) {
+ case TokenTypes.IMPORT:
+ visitImport(ast);
+ break;
+ case TokenTypes.MODIFIERS:
+ this.modifiers.add(ast);
+ break;
+ }
+ }
+
+ private void visitImport(DetailAST ast) {
+ FullIdent ident = FullIdent.createFullIdentBelow(ast);
+ if (!isFullyQualifiedJSpecifyAnnotation(ident)) {
+ String simpleName = simpleNameOf(ident);
+ for (JSpecifyAnnotation annotation: JSpecifyAnnotation.values()) {
+ if (annotation.replaces.contains(simpleName)) {
+ log(ident.getLineNo(), ident.getColumnNo(), "nullability.bannedImport", ident.getText(), annotation.name);
+ this.unwantedNullabilityImports.add(simpleName);
+ }
+ }
+ }
+ }
+
+ private boolean isFullyQualifiedJSpecifyAnnotation(FullIdent ident) {
+ for (JSpecifyAnnotation annotation: JSpecifyAnnotation.values()) {
+ if (ident.getText().equals(annotation.name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private String simpleNameOf(FullIdent ident) {
+ String identText = ident.getText();
+ return identText.substring(identText.lastIndexOf(".") + 1);
+ }
+
+ private void visitModifiers(DetailAST ast) {
+ DetailAST annotation = ast.findFirstToken(TokenTypes.ANNOTATION);
+ if (annotation != null) {
+ DetailAST ident = annotation.findFirstToken(TokenTypes.IDENT);
+ if (ident != null) {
+ String identText = ident.getText();
+ DetailAST lastChild = ast.getLastChild();
+ if (isJSpecifyAnnotation(ident) && !annotation.equals(lastChild)) {
+ log(annotation.getLineNo(), annotation.getColumnNo(), "nullability.annotationLocation", identText);
+ }
+ }
+ }
+ }
+
+ private boolean isJSpecifyAnnotation(DetailAST ident) {
+ for (JSpecifyAnnotation annotation: JSpecifyAnnotation.values()) {
+ if (ident.getText().equals(annotation.simpleName) && !this.unwantedNullabilityImports.contains(ident.getText())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private enum JSpecifyAnnotation {
+
+ NULLABLE("Nullable", "Nullable"),
+
+ NON_NULL("NonNull", "NonNull", "Nonnull");
+
+ private final String simpleName;
+
+ private final String name;
+
+ private Set replaces;
+
+ JSpecifyAnnotation(String simpleName, String... replaces) {
+ this.simpleName = simpleName;
+ this.name = "org.jspecify.annotations." + simpleName;
+ this.replaces = new HashSet<>(Arrays.asList(replaces));
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringParenPadCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringParenPadCheck.java
new file mode 100644
index 00000000..a49789b0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringParenPadCheck.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017-present 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.Locale;
+
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.checks.whitespace.PadOption;
+import com.puppycrawl.tools.checkstyle.checks.whitespace.ParenPadCheck;
+import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
+
+/**
+ * {@link ParenPadCheck} variant that allows whitespace after {@code (} if before
+ * {@code //}.
+ *
+ * @author Phillip Webb
+ */
+public class SpringParenPadCheck extends ParenPadCheck {
+
+ private static final char OPEN_PARENTHESIS = '(';
+
+ private static final char CLOSE_PARENTHESIS = ')';
+
+ private PadOption option = PadOption.NOSPACE;
+
+ @Override
+ public void setOption(String optionStr) {
+ this.option = PadOption.valueOf(optionStr.trim().toUpperCase(Locale.ENGLISH));
+ }
+
+ @Override
+ protected void processLeft(DetailAST ast) {
+ String line = getLines()[ast.getLineNo() - 1];
+ int[] codePoints = line.codePoints().toArray();
+ int after = ast.getColumnNo() + 1;
+ if (after < codePoints.length) {
+ boolean hasWhitespaceAfter = isConsideredWhitespace(codePoints, after);
+ if (this.option == PadOption.NOSPACE && hasWhitespaceAfter) {
+ log(ast, MSG_WS_FOLLOWED, OPEN_PARENTHESIS);
+ }
+ else if (this.option == PadOption.SPACE && !hasWhitespaceAfter && line.charAt(after) != CLOSE_PARENTHESIS) {
+ log(ast, MSG_WS_NOT_FOLLOWED, OPEN_PARENTHESIS);
+ }
+ }
+ }
+
+ private boolean isConsideredWhitespace(int[] codePoints, int after) {
+ if (CommonUtil.isCodePointWhitespace(codePoints, after)) {
+ return !isSlashSlash(codePoints, after + 1);
+ }
+ return false;
+ }
+
+ private boolean isSlashSlash(int[] codePoints, int index) {
+ if (index + 1 < codePoints.length) {
+ char c1 = Character.toChars(codePoints[index])[0];
+ char c2 = Character.toChars(codePoints[index + 1])[0];
+ return c1 == '/' && c2 == '/';
+ }
+ return false;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTernaryCheck.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTernaryCheck.java
index b57bde47..caf82d1e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTernaryCheck.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTernaryCheck.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -61,9 +61,9 @@ private void visitQuestion(DetailAST ast) {
private boolean requiresParens(DetailAST expression) {
if (expression != null && expression.getChildCount() > 1) {
switch (expression.getType()) {
- case TokenTypes.METHOD_CALL:
- case TokenTypes.DOT:
- return false;
+ case TokenTypes.METHOD_CALL:
+ case TokenTypes.DOT:
+ return false;
}
return true;
}
@@ -86,13 +86,13 @@ private boolean isSimpleEqualsExpression(DetailAST expression) {
private boolean isEqualsTestAllowed(DetailAST ast) {
switch (this.equalsTest) {
- case ANY:
- return true;
- case NEVER:
- return false;
- case NEVER_FOR_NULLS:
- DetailAST equal = ast.findFirstToken(TokenTypes.EQUAL);
- return equal.findFirstToken(TokenTypes.LITERAL_NULL) == null;
+ case ANY:
+ return true;
+ case NEVER:
+ return false;
+ case NEVER_FOR_NULLS:
+ DetailAST equal = ast.findFirstToken(TokenTypes.EQUAL);
+ return equal.findFirstToken(TokenTypes.LITERAL_NULL) == null;
}
throw new IllegalStateException("Unsupported equals test " + this.equalsTest);
}
@@ -103,8 +103,7 @@ private boolean hasType(DetailAST ast, int type) {
public void setEqualsTest(String equalsTest) {
try {
- this.equalsTest = Enum.valueOf(EqualsTest.class,
- equalsTest.trim().toUpperCase(Locale.ENGLISH));
+ this.equalsTest = Enum.valueOf(EqualsTest.class, equalsTest.trim().toUpperCase(Locale.ENGLISH));
}
catch (final IllegalArgumentException ex) {
throw new IllegalArgumentException("unable to parse " + equalsTest, ex);
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
new file mode 100644
index 00000000..31dda6a0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present 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.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 class filenames end {@literal Tests.java} and not
+ * {@literal Test.java}.
+ *
+ * @author Phillip Webb
+ * @author Andy Wilkinson
+ */
+public class SpringTestFileNameCheck extends AbstractFileSetCheck {
+
+ @Override
+ 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")) {
+ 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/java/io/spring/javaformat/checkstyle/filter/CheckFilter.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/CheckFilter.java
index bb178221..5388e5bd 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/CheckFilter.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/CheckFilter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -28,7 +28,7 @@
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.Context;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
+import com.puppycrawl.tools.checkstyle.api.Violation;
/**
* Base class for {@link AbstractCheck checks} that act as a filter for a single child.
@@ -44,7 +44,6 @@ public class CheckFilter extends AbstractCheck {
@Override
public void finishLocalSetup() {
DefaultContext context = new DefaultContext();
- context.add("classLoader", getClassLoader());
context.add("severity", getSeverity());
context.add("tabWidth", String.valueOf(getTabWidth()));
this.childContext = context;
@@ -56,8 +55,8 @@ public void setupChild(Configuration childConf) throws CheckstyleException {
String name = childConf.getName();
Object module = moduleFactory.createModule(name);
if (!(module instanceof AbstractCheck)) {
- throw new CheckstyleException("OptionalCheck is not allowed as a parent of "
- + name + " Please review 'Parent Module' section for this Check.");
+ throw new CheckstyleException("OptionalCheck is not allowed as a parent of " + name
+ + " Please review 'Parent Module' section for this Check.");
}
if (this.check != null) {
throw new CheckstyleException("Can only make a single check optional");
@@ -101,14 +100,14 @@ public boolean isCommentNodesRequired() {
}
@Override
- public SortedSet getMessages() {
- return this.check.getMessages();
+ public SortedSet getViolations() {
+ return this.check.getViolations();
}
@Override
public void beginTree(DetailAST rootAST) {
this.check.setFileContents(getFileContents());
- this.check.clearMessages();
+ this.check.clearViolations();
this.check.beginTree(rootAST);
}
@@ -127,6 +126,4 @@ public void leaveToken(DetailAST ast) {
this.check.leaveToken(ast);
}
-
-
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/IdentCheckFilter.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/IdentCheckFilter.java
index 79fab14a..6e434bcc 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/IdentCheckFilter.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/IdentCheckFilter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/RequiresOuterThisFilter.java b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/RequiresOuterThisFilter.java
index 86405424..080bf8ec 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/RequiresOuterThisFilter.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/filter/RequiresOuterThisFilter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,7 +21,7 @@
import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
+import com.puppycrawl.tools.checkstyle.api.Violation;
/**
* {@link TreeWalkerFilter} that can used to relax the {@code 'this.'} requirement when
@@ -35,9 +35,9 @@ public class RequiresOuterThisFilter implements TreeWalkerFilter {
@Override
public boolean accept(TreeWalkerAuditEvent event) {
- LocalizedMessage message = event.getLocalizedMessage();
- if ("require.this.variable".equals(message.getKey())) {
- Object[] args = getArgs(message);
+ Violation violation = event.getViolation();
+ if ("require.this.variable".equals(violation.getKey())) {
+ Object[] args = getArgs(violation);
String prefex = (args.length > 1 ? Objects.toString(args[1]) : null);
if (prefex != null && prefex.length() > 0) {
return false;
@@ -46,12 +46,12 @@ public boolean accept(TreeWalkerAuditEvent event) {
return true;
}
- private Object[] getArgs(LocalizedMessage message) {
+ private Object[] getArgs(Violation violation) {
if (ARGS_FIELD == null) {
throw new IllegalStateException("Unable to extract message args");
}
try {
- return (Object[]) ARGS_FIELD.get(message);
+ return (Object[]) ARGS_FIELD.get(violation);
}
catch (Exception ex) {
return null;
@@ -60,7 +60,7 @@ private Object[] getArgs(LocalizedMessage message) {
private static Field getArgsField() {
try {
- Field field = LocalizedMessage.class.getDeclaredField("args");
+ Field field = Violation.class.getDeclaredField("args");
field.setAccessible(true);
return field;
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/header-apache2.txt b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/header-apache2.txt
index 3f5d4761..dd9f9cce 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/header-apache2.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/header-apache2.txt
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
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 5d82007e..eaaec1f1 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,10 +1,49 @@
-lambda.missingParen=Lambda argument missing parentheses.
-lambda.unnecessaryParen=Lambda argument has unnecessary parentheses.
-lambda.unnecessaryBlock=Lambda block is unnecessary.
-ternary.missingParen=Ternary operation missing parentheses.
-ternary.equalOperator=Ternary operation should use != when testing.
+annotation.attribute.overlyVerboseValue=Value of ''{0}'' attribute is overly verbose. Import ''{1}'' and use ''{2}'' instead.
+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).
-javadoc.badCase=Javadoc element descriptions should not start with an uppercase letter.
+catch.wideEye=''o_O'' catch variable (use "ex" instead).
header.unexpected=Unexpected header.
-nothis.unexpected=Reference to instance variable ''{0}'' should not use \"this.\".
+header.mismatch=Line does not match expected header line of ''{0}''.
+header.blankLine=Blank line expected after header.
+hide.utility.class=Utility classes should not have a public or default constructor.
+import.avoidStatic=Using a static member import should be avoided - {0}.
+import.ordering=Wrong order for ''{0}'' import.
+javadoc.badCase=Javadoc element descriptions should not start with an uppercase letter.
+javadoc.bannedTag=Javadoc tag ''{0}'' should not be used.
+javadoc.earlierSince=Javadoc @since version ''{0}'' is earlier than @since version ''{1}'' at {2}:{3}.
+javadoc.missingSince=Missing Javadoc @since tag.
+javadoc.sameSince=Javadoc @since version ''{0}'' is unnecessary as it is the same as the @since version at {1}:{2}.
+javadoc.publicSince=Javadoc @since tag should not be used on private classes.
+javadoc.emptyLineBeforeTag=Method Javadoc should not have empty line before tag.
+javadoc.nonJavadocComment=Comments should not include \"(non-Javadoc)\".
+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.
+lambda.unnecessaryBlock=Lambda block is unnecessary.
+lambda.unnecessaryParen=Lambda argument has unnecessary parentheses.
methodorder.outOfOrder=Method ''{0}'' is out of order, expected {1}.
+methodvisibility.publicMethod=Method ''{0}'' in private class should not be public.
+methodvisibility.protectedMethodInFinalClass=Method ''{0}'' in final class should be package-private rather than protected.
+nothis.unexpected=Reference to instance variable ''{0}'' should not use \"this.\".
+nullability.bannedImport=Nullability should be expressed using JSpecify. Replace ''{0}'' with ''{1}''.
+nullability.annotationLocation=''{0}'' should only be used immediately before a type.
+ternary.equalOperator=Ternary operation should use != when testing.
+ternary.missingParen=Ternary operation missing parentheses. Use the form \"(a != b) ? y : n\".
+testfilename.wrongName=Test classes should have a name ending with 'Tests.java'.
+leadingwhitespace.incorrect=Indentation should be performed with {0} only.
+deprecated.missingSince=@Deprecated has no since attribute.
+deprecated.emptySince=@Deprecated has an empty since attribute.
+ws.followed=''{0}'' is followed by whitespace.
+ws.illegalFollow=''{0}'' is followed by an illegal character.
+ws.notFollowed=''{0}'' is not followed by whitespace.
+ws.notPreceded=''{0}'' is not preceded with whitespace.
+ws.preceded=''{0}'' is preceded with whitespace.
+ws.typeCast=''typecast'' is not followed by whitespace.
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/checkstyle.xml b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/checkstyle.xml
index b1231c9b..886a68d2 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/checkstyle.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/checkstyle.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle-suppressions.xml b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle-suppressions.xml
index 5ebc0a4b..0c736d01 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle-suppressions.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle-suppressions.xml
@@ -1,7 +1,7 @@
+ "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
+ "https://checkstyle.org/dtds/suppressions_1_2.dtd">
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 e09c3622..829e6959 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
@@ -1,16 +1,19 @@
-
+
-
-
-
-
-
+
+
+
+
+
+
@@ -19,11 +22,10 @@
+
-
-
-
+
+
@@ -39,7 +41,7 @@
-
+
@@ -67,23 +69,16 @@
+
-
-
-
-
-
-
-
-
-
+
+
@@ -91,11 +86,9 @@
-
-
-
+
-
+
@@ -106,11 +99,11 @@
-
+
-
+
-
+
@@ -126,22 +119,16 @@
-
-
+
+
+
+ value="Please use BDD-style (given, when, then) using BDDMockito imports." />
-
-
-
-
-
-
-
-
-
+
+
+
@@ -158,17 +145,23 @@
-
-
+
+
+
+
+
-
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/AssertionsAuditListener.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/AssertionsAuditListener.java
index b69ab3ec..6b36f545 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/AssertionsAuditListener.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/AssertionsAuditListener.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -27,8 +27,8 @@
import com.puppycrawl.tools.checkstyle.Definitions;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
+import com.puppycrawl.tools.checkstyle.api.Violation;
import static org.assertj.core.api.Assertions.assertThat;
@@ -75,10 +75,10 @@ public void auditFinished(AuditEvent event) {
private void runCheck(String check) {
String description = this.filenames.toString();
if (check.startsWith("+")) {
- assertThat(this.message).as(description).contains(check.substring(1));
+ assertThat(this.message.toString()).as(description).contains(check.substring(1));
}
else if (check.startsWith("-")) {
- assertThat(this.message).as(description).doesNotContain(check.substring(1));
+ assertThat(this.message.toString()).as(description).doesNotContain(check.substring(1));
}
}
@@ -106,13 +106,12 @@ public void addException(AuditEvent event, Throwable throwable) {
}
private void recordLevel(AuditEvent event) {
- this.severityCounts.compute(event.getSeverityLevel(),
- (level, count) -> (count == null ? 1 : count + 1));
+ this.severityCounts.compute(event.getSeverityLevel(), (level, count) -> (count == null ? 1 : count + 1));
}
private void recordLocalizedMessage(String message, String... args) {
- recordMessage(new LocalizedMessage(0, Definitions.CHECKSTYLE_BUNDLE, message,
- args, null, LocalizedMessage.class, null).getMessage());
+ recordMessage(new Violation(0, Definitions.CHECKSTYLE_BUNDLE, message, args, null, Violation.class, null)
+ .getViolation());
}
private void recordMessage(String message) {
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTestParameter.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTestParameter.java
index 34b3d69c..62e4a959 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTestParameter.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTestParameter.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
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 120ca04a..0be6bdb9 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,9 +21,12 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Locale;
import java.util.Properties;
import java.util.stream.Collectors;
@@ -39,10 +42,9 @@
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.RootModule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import org.xml.sax.InputSource;
/**
@@ -50,79 +52,86 @@
*
* @author Phillip Webb
*/
-@RunWith(Parameterized.class)
public class SpringChecksTests {
+ private static final boolean RUNNING_ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
+
private static final File SOURCES_DIR = new File("src/test/resources/source");
private static final File CHECKS_DIR = new File("src/test/resources/check");
private static final File CONFIGS_DIR = new File("src/test/resources/config");
- private static final File DEFAULT_CONFIG = new File(CONFIGS_DIR,
- "default-checkstyle-configuration.xml");
-
- private final Parameter parameter;
+ private static final File DEFAULT_CONFIG = new File(CONFIGS_DIR, "default-checkstyle-configuration.xml");
- public SpringChecksTests(Parameter parameter) throws Exception {
- this.parameter = parameter;
- }
+ @TempDir
+ public Path temp;
- @Test
- public void processHasExpectedResults() throws Exception {
- Configuration configuration = loadConfiguration();
+ @ParameterizedTest
+ @MethodSource("paramaters")
+ public void processHasExpectedResults(Parameter parameter) throws Exception {
+ Locale previousLocale = Locale.getDefault();
+ Locale.setDefault(Locale.ENGLISH);
+ Configuration configuration = loadConfiguration(parameter);
RootModule rootModule = createRootModule(configuration);
try {
- processAndCheckResults(rootModule);
+ processAndCheckResults(parameter, rootModule);
}
finally {
rootModule.destroy();
+ Locale.setDefault(previousLocale);
}
}
- private Configuration loadConfiguration() throws Exception {
- try (InputStream inputStream = new FileInputStream(
- this.parameter.getConfigFile())) {
- Configuration configuration = ConfigurationLoader.loadConfiguration(
- new InputSource(inputStream),
- new PropertiesExpander(new Properties()),
- IgnoredModulesOptions.EXECUTE,
+ private Configuration loadConfiguration(Parameter parameter) throws Exception {
+ try (InputStream inputStream = new FileInputStream(parameter.getConfigFile())) {
+ Configuration configuration = ConfigurationLoader.loadConfiguration(new InputSource(inputStream),
+ new PropertiesExpander(new Properties()), IgnoredModulesOptions.EXECUTE,
ThreadModeSettings.SINGLE_THREAD_MODE_INSTANCE);
return configuration;
}
}
- private RootModule createRootModule(Configuration configuration)
- throws CheckstyleException {
- ModuleFactory factory = new PackageObjectFactory(
- Checker.class.getPackage().getName(), getClass().getClassLoader());
- RootModule rootModule = (RootModule) factory
- .createModule(configuration.getName());
+ private RootModule createRootModule(Configuration configuration) throws CheckstyleException {
+ ModuleFactory factory = new PackageObjectFactory(Checker.class.getPackage().getName(),
+ getClass().getClassLoader());
+ RootModule rootModule = (RootModule) factory.createModule(configuration.getName());
rootModule.setModuleClassLoader(getClass().getClassLoader());
rootModule.configure(configuration);
return rootModule;
}
- private void processAndCheckResults(RootModule rootModule)
- throws CheckstyleException {
- rootModule.addListener(this.parameter.getAssersionsListener());
- printDebugInfo(this.parameter.getSourceFile());
- rootModule.process(Arrays.asList(this.parameter.getSourceFile()));
+ private void processAndCheckResults(Parameter parameter, RootModule rootModule) throws CheckstyleException {
+ rootModule.addListener(parameter.getAssertionsListener());
+ if (!RUNNING_ON_WINDOWS) {
+ printDebugInfo(parameter.getSourceFile());
+ }
+ rootModule.process(Arrays.asList(parameter.getSourceFile()));
}
private void printDebugInfo(File file) throws CheckstyleException {
try {
- System.out.println(AstTreeStringPrinter.printFileAst(file,
- JavaParser.Options.WITHOUT_COMMENTS));
+ System.out.println(AstTreeStringPrinter.printFileAst(file, JavaParser.Options.WITHOUT_COMMENTS));
}
catch (IOException ex) {
}
}
- @Parameters(name = "{0}")
- public static Collection files() throws IOException {
- return Arrays.stream(SOURCES_DIR.list((dir, name) -> !name.startsWith(".")))
- .map(Parameter::new).collect(Collectors.toList());
+ public static Collection paramaters() throws IOException {
+ ArrayList parameters = Arrays.stream(SOURCES_DIR.listFiles(SpringChecksTests::sourceFile))
+ .sorted()
+ .map(Parameter::new)
+ .collect(Collectors.toCollection(ArrayList::new));
+ parameters.add(new Parameter(new File(SOURCES_DIR, "nopackageinfo/NoPackageInfo.java")));
+ Arrays.stream(new File(SOURCES_DIR, "src/test/java").listFiles(SpringChecksTests::sourceFile))
+ .sorted()
+ .map(Parameter::new)
+ .forEach(parameters::add);
+ return parameters;
+ }
+
+ private static boolean sourceFile(File file) {
+ return file.isFile() && !file.getName().startsWith(".") && !file.getName().equals("package-info.java");
}
private static class Parameter {
@@ -131,17 +140,17 @@ private static class Parameter {
private final File sourceFile;
- private final AssertionsAuditListener assersionsListener;
+ private final AssertionsAuditListener assertionsListener;
private final File configFile;
- Parameter(String sourceName) {
+ Parameter(File sourceFile) {
+ String sourceName = sourceFile.getAbsolutePath().substring(SOURCES_DIR.getAbsolutePath().length() + 1);
this.name = sourceName.replace(".java", "");
this.sourceFile = new File(SOURCES_DIR, sourceName);
File configFile = new File(CONFIGS_DIR, this.name + ".xml");
this.configFile = (configFile.exists() ? configFile : DEFAULT_CONFIG);
- this.assersionsListener = new AssertionsAuditListener(
- readChecks(this.name + ".txt"));
+ this.assertionsListener = new AssertionsAuditListener(readChecks(this.name + ".txt"));
}
private List readChecks(String name) {
@@ -161,8 +170,8 @@ public File getConfigFile() {
return this.configFile;
}
- public AssertionsAuditListener getAssersionsListener() {
- return this.assersionsListener;
+ public AssertionsAuditListener getAssertionsListener() {
+ return this.assertionsListener;
}
@Override
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 962e74cf..2c81cdd4 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,17 +16,24 @@
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;
import com.puppycrawl.tools.checkstyle.DefaultContext;
-import com.puppycrawl.tools.checkstyle.ModuleFactory;
import com.puppycrawl.tools.checkstyle.PackageObjectFactory;
import com.puppycrawl.tools.checkstyle.PropertiesExpander;
import com.puppycrawl.tools.checkstyle.PropertyResolver;
+import com.puppycrawl.tools.checkstyle.TreeWalker;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
+import org.assertj.core.extractor.Extractors;
+import org.junit.jupiter.api.Test;
+
import io.spring.javaformat.checkstyle.check.SpringHeaderCheck;
-import org.junit.Test;
+import io.spring.javaformat.checkstyle.check.SpringImportOrderCheck;
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,21 +46,53 @@ public class SpringConfigurationLoaderTests {
@Test
public void loadShouldLoadChecks() {
+ Collection checks = load(null);
+ assertThat(checks).hasSize(5);
+ TreeWalker treeWalker = (TreeWalker) checks.toArray()[4];
+ Set> ordinaryChecks = (Set>) Extractors.byName("ordinaryChecks").extract(treeWalker);
+ assertThat(ordinaryChecks).hasSize(63);
+ Set> commentChecks = (Set>) Extractors.byName("commentChecks").extract(treeWalker);
+ assertThat(commentChecks).hasSize(6);
+ }
+
+ @Test
+ public void loadWithExcludeShouldExcludeChecks() {
+ 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(62);
+ Set> commentChecks = (Set>) Extractors.byName("commentChecks").extract(treeWalker);
+ assertThat(commentChecks).hasSize(5);
+ }
+
+ @Test
+ public void loadWithExcludeHeaderShouldExcludeChecks() {
+ Set excludes = Collections.singleton("io.spring.javaformat.checkstyle.check.SpringHeaderCheck");
+ Object[] checks = load(excludes).stream().toArray();
+ assertThat(checks).hasSize(4);
+ }
+
+ private Collection load(Set excludes) {
DefaultContext context = new DefaultContext();
- context.add("moduleFactory", new PackageObjectFactory(
- getClass().getPackage().getName(), getClass().getClassLoader()));
- ModuleFactory moduleFactory = new PackageObjectFactory(
- getClass().getPackage().getName(), getClass().getClassLoader());
- Collection checks = new SpringConfigurationLoader(context,
- moduleFactory).load(getPropertyResolver());
- assertThat(checks).hasSize(3);
+ FilteredModuleFactory filteredModuleFactory = new FilteredModuleFactory(
+ new PackageObjectFactory(getClass().getPackage().getName(), getClass().getClassLoader()), excludes);
+ context.add("moduleFactory", filteredModuleFactory);
+ Collection checks = new SpringConfigurationLoader(context, filteredModuleFactory)
+ .load(getPropertyResolver());
+ return checks;
}
private PropertyResolver getPropertyResolver() {
Properties properties = new Properties();
properties.put("headerType", SpringHeaderCheck.DEFAULT_HEADER_TYPE);
- properties.put("headerCopyrightPattern",
- SpringHeaderCheck.DEFAULT_HEADER_COPYRIGHT_PATTERN);
+ properties.put("headerFile", "");
+ properties.put("headerCopyrightPattern", SpringHeaderCheck.DEFAULT_HEADER_COPYRIGHT_PATTERN);
+ properties.put("projectRootPackage", SpringImportOrderCheck.DEFAULT_PROJECT_ROOT_PACKAGE);
+ properties.put("avoidStaticImportExcludes", "");
return new PropertiesExpander(properties);
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..17a91c25
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt
@@ -0,0 +1,2 @@
++AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java:17:84: Value of 'value' attribute is overly verbose. Import 'ConditionalOnWebApplicationType.WebApplicationType' and use 'WebApplicationType.SERVLET' instead. [SpringAnnotationAttributeConciseValue]
++1 error
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..2c02256f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.txt
@@ -0,0 +1,2 @@
++AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java:17:91: Value of 'type' attribute is overly verbose. Import 'ConditionalOnWebApplicationType.WebApplicationType' and use 'WebApplicationType.SERVLET' instead. [SpringAnnotationAttributeConciseValue]
++1 error
\ No newline at end of file
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/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AsciidoctorCallout.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AsciidoctorCallout.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AsciidoctorCallout.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertImport.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertImport.txt
new file mode 100644
index 00000000..05108d50
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertImport.txt
@@ -0,0 +1,2 @@
++Please use AssertJ imports.
++3 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertionsImport.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertionsImport.txt
new file mode 100644
index 00000000..05108d50
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/AssertJBadAssertionsImport.txt
@@ -0,0 +1,2 @@
++Please use AssertJ imports.
++3 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/CatchOo.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/CatchOo.txt
new file mode 100644
index 00000000..dba33895
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/CatchOo.txt
@@ -0,0 +1 @@
++'o_O' catch variable (use "ex" instead)
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedBadCase.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedBadCase.txt
new file mode 100644
index 00000000..96f86d18
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedBadCase.txt
@@ -0,0 +1,6 @@
++DeprecatedBadCase.java:22:1: @Deprecated has no since attribute. [SpringDeprecated]
++DeprecatedBadCase.java:25:9: @Deprecated has no since attribute. [SpringDeprecated]
++DeprecatedBadCase.java:28:9: @Deprecated has an empty since attribute. [SpringDeprecated]
++DeprecatedBadCase.java:33:9: @Deprecated has no since attribute. [SpringDeprecated]
++DeprecatedBadCase.java:36:17: @Deprecated has an empty since attribute. [SpringDeprecated]
++5 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedValid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedValid.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/DeprecatedValid.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderDate.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderDate.txt
index cb61a4b8..3d109568 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderDate.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderDate.txt
@@ -1 +1,3 @@
-+HeaderDate.java:2: header.mismatch [SpringHeader]
++HeaderDate.java:2
++Line does not match expected header
++[SpringHeader]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderFile.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderFile.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderFile.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMismatch.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMismatch.txt
index 49868389..186d6aed 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMismatch.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMismatch.txt
@@ -1 +1,3 @@
-+HeaderMismatch.java:5: header.mismatch [SpringHeader]
\ No newline at end of file
++HeaderMismatch.java:5
++Line does not match expected header
++[SpringHeader]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMissingBlankLine.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMissingBlankLine.txt
new file mode 100644
index 00000000..7ffa25dc
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderMissingBlankLine.txt
@@ -0,0 +1,2 @@
++Blank line expected after header
++1 error
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooLong.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooLong.txt
index 1c85c9e3..02c7a81b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooLong.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooLong.txt
@@ -1 +1,3 @@
-+HeaderTooLong.java:15: header.mismatch [SpringHeader]
++HeaderTooLong.java:15:
++Line does not match expected header
++[SpringHeader]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooShort.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooShort.txt
index 856886e8..4c47c177 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooShort.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderTooShort.txt
@@ -1 +1,3 @@
-+HeaderTooShort.java:14: header.mismatch [SpringHeader]
++HeaderTooShort.java:14
++Line does not match expected header
++[SpringHeader]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithDateToPresent.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithDateToPresent.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithDateToPresent.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithSingleDate.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithSingleDate.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HeaderWithSingleDate.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorInvalid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorInvalid.txt
new file mode 100644
index 00000000..dc14dcd3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorInvalid.txt
@@ -0,0 +1 @@
++HideUtilityClassConstructorInvalid.java:22:1: Utility classes should not have a public or default constructor. [SpringHideUtilityClassConstructor]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringApplication.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringApplication.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringApplication.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringConfiguration.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringConfiguration.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/HideUtilityClassConstructorSpringConfiguration.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageInvalid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageInvalid.txt
new file mode 100644
index 00000000..37a1d385
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageInvalid.txt
@@ -0,0 +1 @@
++ImportOrderCustomPackageInvalid.java:21:1: Wrong order for 'java.util.Objects' import. [SpringImportOrder]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageValid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageValid.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/ImportOrderCustomPackageValid.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadAnnotation.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadAnnotation.txt
new file mode 100644
index 00000000..ee903496
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadAnnotation.txt
@@ -0,0 +1 @@
++JUnit 4 @Test annotation should not be used in a JUnit 5 test.
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImport.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImport.txt
new file mode 100644
index 00000000..75e3c05b
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImport.txt
@@ -0,0 +1 @@
++Import 'org.junit.Before' should not be used in a JUnit 5 test.
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImportWithOptOut.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImportWithOptOut.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadImportWithOptOut.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
new file mode 100644
index 00000000..7ec1d4de
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt
@@ -0,0 +1,16 @@
++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
++Lifecycle method 'publicAfterEach' should not be public
++Lifecycle method 'privateBeforeAll' should not be private
++Lifecycle method 'privateBeforeEach' should not be private
++Lifecycle method 'privateAfterAll' should not be private
++Lifecycle method 'privateAfterEach' should not be private
\ No newline at end of file
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/JUnit5Valid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5Valid.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5Valid.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocAnnotationFieldHasEarlierSince.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocAnnotationFieldHasEarlierSince.txt
new file mode 100644
index 00000000..e5c19bf9
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocAnnotationFieldHasEarlierSince.txt
@@ -0,0 +1,2 @@
++28:19: Javadoc @since version '1.1.0' is earlier than @since version '1.2.0' at 21:10.
++1 error
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocInnerClassHasEarlierSince.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocInnerClassHasEarlierSince.txt
new file mode 100644
index 00000000..73737acb
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocInnerClassHasEarlierSince.txt
@@ -0,0 +1,2 @@
++28:19: Javadoc @since version '1.2.3' is earlier than @since version '2.0.0' at 21:10.
++1 error
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTag.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTag.txt
new file mode 100644
index 00000000..efa9ef2f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTag.txt
@@ -0,0 +1,2 @@
++Method Javadoc should not have empty line before tag.
++1 error
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodHasEarlierSince.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodHasEarlierSince.txt
new file mode 100644
index 00000000..7d3a7148
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMethodHasEarlierSince.txt
@@ -0,0 +1,2 @@
++27:19: Javadoc @since version '1.2.3' is earlier than @since version '2.0.0' at 21:10.
++1 error
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMissingSince.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMissingSince.txt
new file mode 100644
index 00000000..914724b7
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocMissingSince.txt
@@ -0,0 +1,2 @@
++Missing Javadoc @since tag.
++1 error
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonJavadocComment.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonJavadocComment.txt
new file mode 100644
index 00000000..7ba1b19a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonJavadocComment.txt
@@ -0,0 +1,3 @@
++23:1: Comments should not include "(non-Javadoc)"
++30:1: Comments should not include "(non-Javadoc)"
++2 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSince.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSince.txt
new file mode 100644
index 00000000..ecb8dbc3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSince.txt
@@ -0,0 +1,3 @@
++JavadocNonPublicSince.java:21:11: Javadoc @since tag should not be used on private classes. [SpringJavadoc]
++JavadocNonPublicSince.java:28:19: Javadoc @since tag should not be used on private classes. [SpringJavadoc]
++2 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideAnnotation.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideAnnotation.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideAnnotation.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideInterface.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideInterface.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocNonPublicSinceInsideInterface.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocSoundtrack.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocSoundtrack.txt
new file mode 100644
index 00000000..20ea9833
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JavadocSoundtrack.txt
@@ -0,0 +1 @@
++Javadoc tag '@soundtrack' should not be used. [SpringJavadoc]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaNecessaryVoidCallable.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaNecessaryVoidCallable.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaNecessaryVoidCallable.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaSwitch.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaSwitch.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LambdaSwitch.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceSpaces.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceSpaces.txt
new file mode 100644
index 00000000..23d7767e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceSpaces.txt
@@ -0,0 +1,2 @@
++Indentation should be performed with spaces only. [SpringLeadingWhitespace]
++1 error
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabs.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabs.txt
new file mode 100644
index 00000000..3a32b527
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/LeadingWhitespaceTabs.txt
@@ -0,0 +1,2 @@
++Indentation should be performed with tabs only. [SpringLeadingWhitespace]
++1 error
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/MethodVisibilityFinalClassWithOverride.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityFinalClassWithOverride.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityFinalClassWithOverride.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityFinalClassWithProtectedMethod.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityFinalClassWithProtectedMethod.txt
new file mode 100644
index 00000000..20293abd
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityFinalClassWithProtectedMethod.txt
@@ -0,0 +1,2 @@
++Method 'bad' in final class should be package-private rather than protected.
++Method 'badStatic' in final class should be package-private rather than protected.
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityInnerClassesWithPublicMethod.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityInnerClassesWithPublicMethod.txt
new file mode 100644
index 00000000..e66b5bd9
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityInnerClassesWithPublicMethod.txt
@@ -0,0 +1,3 @@
++Method 'badPrivateInner' in private class should not be public.
++Method 'badDefaultInner' in private class should not be public.
++2 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityPackagePrivateWithPublicMethod.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityPackagePrivateWithPublicMethod.txt
new file mode 100644
index 00000000..4d1363b7
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityPackagePrivateWithPublicMethod.txt
@@ -0,0 +1,3 @@
++Method 'bad' in private class should not be public.
++Method 'badStatic' in private class should not be public.
++2 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityProtectedWithPublicMethod.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityProtectedWithPublicMethod.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityProtectedWithPublicMethod.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityWithOverride.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityWithOverride.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/MethodVisibilityWithOverride.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NestedInterfaceItems.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NestedInterfaceItems.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NestedInterfaceItems.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNonNull.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNonNull.txt
new file mode 100644
index 00000000..2565624c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNonNull.txt
@@ -0,0 +1,3 @@
++NullabilityBannedNonNull.java:17:8: Nullability should be expressed using JSpecify. Replace 'javax.annotation.Nonnull' with 'org.jspecify.annotations.NonNull'. [SpringNullability]
++NullabilityBannedNonNull.java:19:8: Nullability should be expressed using JSpecify. Replace 'org.checkerframework.checker.nullness.qual.NonNull' with 'org.jspecify.annotations.NonNull'. [SpringNullability]
++2 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNullable.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNullable.txt
new file mode 100644
index 00000000..f3829412
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityBannedNullable.txt
@@ -0,0 +1 @@
++Nullability should be expressed using JSpecify. Replace 'javax.annotation.Nullable' with 'org.jspecify.annotations.Nullable'. [SpringNullability]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingFieldType.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingFieldType.txt
new file mode 100644
index 00000000..de4383d2
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingFieldType.txt
@@ -0,0 +1 @@
++NullabilityNullableNotPrecedingFieldType.java:26:17: 'Nullable' should only be used immediately before a type. [SpringNullability]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingParameterType.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingParameterType.txt
new file mode 100644
index 00000000..7b47421a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingParameterType.txt
@@ -0,0 +1 @@
+NullabilityNullableNotPrecedingParameterType.java:26:30: 'Nullable' should only be used immediately before a type. [SpringNullability]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingReturnType.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingReturnType.txt
new file mode 100644
index 00000000..fe62aa47
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableNotPrecedingReturnType.txt
@@ -0,0 +1 @@
++NullabilityNullableNotPrecedingReturnType.java:26:9: 'Nullable' should only be used immediately before a type. [SpringNullability]
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableOnSeparateLine.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityNullableOnSeparateLine.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityValid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityValid.txt
new file mode 100644
index 00000000..23435c7a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/NullabilityValid.txt
@@ -0,0 +1 @@
++0 errors
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameInvalid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameInvalid.txt
new file mode 100644
index 00000000..c242222d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameInvalid.txt
@@ -0,0 +1 @@
++The name of the outer type and the file do not match
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameValid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameValid.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/OuterTypeFilenameValid.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TernaryParensInvalid.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TernaryParensInvalid.txt
index bd07621a..0c329c35 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TernaryParensInvalid.txt
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TernaryParensInvalid.txt
@@ -1,2 +1,2 @@
-+Ternary operation missing parentheses
++Ternary operation missing parentheses. Use the form "(a != b) ? y : n"
+3 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TryWithResources.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TryWithResources.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/TryWithResources.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArray.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArray.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArray.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArrayElements.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArrayElements.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableArrayElements.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableVarargs.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableVarargs.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceNullableVarargs.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceVarargs.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceVarargs.txt
new file mode 100644
index 00000000..1ec0d7e2
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/WhitespaceVarargs.txt
@@ -0,0 +1,2 @@
++WhitespaceVarargs.java:24:24: '...' is preceded with whitespace. [SpringNoWhitespaceBefore]
++1 error
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/nopackageinfo/NoPackageInfo.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/nopackageinfo/NoPackageInfo.txt
new file mode 100644
index 00000000..a19759c0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/nopackageinfo/NoPackageInfo.txt
@@ -0,0 +1 @@
++Missing package-info.java file
\ No newline at end of file
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/check/src/test/java/NamedTest.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/NamedTest.txt
new file mode 100644
index 00000000..38fff433
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/NamedTest.txt
@@ -0,0 +1 @@
++Test classes should have a name ending with Tests.java
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/NamedTests.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/NamedTests.txt
new file mode 100644
index 00000000..69174e4c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/src/test/java/NamedTests.txt
@@ -0,0 +1 @@
++0 errors
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedBadCase.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedBadCase.xml
new file mode 100644
index 00000000..0a4b92ee
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedBadCase.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedValid.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedValid.xml
new file mode 100644
index 00000000..0a4b92ee
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/DeprecatedValid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/FiltersToSkipThis.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/FiltersToSkipThis.xml
index 5cefa3a5..d12a0f37 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/FiltersToSkipThis.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/FiltersToSkipThis.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderDate.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderDate.xml
index 2ec372e9..dde28701 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderDate.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderDate.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderFile.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderFile.xml
new file mode 100644
index 00000000..1f3c7efa
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderFile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMissingBlankLine.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMissingBlankLine.xml
new file mode 100644
index 00000000..1f3c7efa
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMissingBlankLine.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissing.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissing.xml
index f03eb43e..79567613 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissing.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissing.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissingButIsNot.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissingButIsNot.xml
index f03eb43e..79567613 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissingButIsNot.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderMustBeMissingButIsNot.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderUnchecked.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderUnchecked.xml
index 6731bd0a..df9ccdac 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderUnchecked.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/HeaderUnchecked.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageInvalid.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageInvalid.xml
new file mode 100644
index 00000000..dca7c768
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageInvalid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageValid.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageValid.xml
new file mode 100644
index 00000000..dca7c768
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/ImportOrderCustomPackageValid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadAnnotation.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadAnnotation.xml
new file mode 100644
index 00000000..1f9cd714
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadAnnotation.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImport.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImport.xml
new file mode 100644
index 00000000..1f9cd714
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImport.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImportWithOptOut.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImportWithOptOut.xml
new file mode 100644
index 00000000..6d672900
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadImportWithOptOut.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadModifier.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadModifier.xml
new file mode 100644
index 00000000..1f9cd714
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5BadModifier.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5Valid.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5Valid.xml
new file mode 100644
index 00000000..1f9cd714
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JUnit5Valid.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocMissingSince.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocMissingSince.xml
new file mode 100644
index 00000000..c13dc89d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocMissingSince.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSince.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSince.xml
new file mode 100644
index 00000000..c2b98905
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSince.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideAnnotation.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideAnnotation.xml
new file mode 100644
index 00000000..c2b98905
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideAnnotation.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideInterface.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideInterface.xml
new file mode 100644
index 00000000..c2b98905
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/JavadocNonPublicSinceInsideInterface.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LambdaExtraParens.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LambdaExtraParens.xml
index 497832ff..0daf80c8 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LambdaExtraParens.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LambdaExtraParens.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LeadingWhitespaceSpaces.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LeadingWhitespaceSpaces.xml
new file mode 100644
index 00000000..0070d582
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/LeadingWhitespaceSpaces.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/NoThis.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/NoThis.xml
index 9b402015..ec09684f 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/NoThis.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/NoThis.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsAny.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsAny.xml
index 7611428a..e155786e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsAny.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsAny.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsNever.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsNever.xml
index dafbee0c..14306d10 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsNever.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/TernaryEqualsEqualsNever.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/default-checkstyle-configuration.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/default-checkstyle-configuration.xml
index 5f9503d2..f8fd854f 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/default-checkstyle-configuration.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/default-checkstyle-configuration.xml
@@ -1,5 +1,7 @@
-
+
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing-but-is-not.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing-but-is-not.xml
index a6e6df59..6b1603c3 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing-but-is-not.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing-but-is-not.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing.xml b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing.xml
index a6e6df59..6b1603c3 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing.xml
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/config/package-info-header-must-be-missing.xml
@@ -1,5 +1,7 @@
-
+
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/customHeaderFile.txt b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/customHeaderFile.txt
new file mode 100644
index 00000000..b96355a3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/customHeaderFile.txt
@@ -0,0 +1 @@
+// (c) Somebody ${copyright-pattern}
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..d7ea8e09
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnWebApplicationType(WebApplicationType.A.B.C.D.SERVLET)
+public class AnnotationAttributeWithValueThatHasConciseReferenceToContainedEnumValue {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.java
new file mode 100644
index 00000000..edc98fb7
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasReferenceToContainedConstant.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnSomething(ConditionalOnSomething.TYPE_ONE)
+public class AnnotationAttributeWithValueThatHasReferenceToContainedConstant {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..8594fc9b
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnWebApplicationType(ConditionalOnWebApplicationType.WebApplicationType.SERVLET)
+public class AnnotationAttributeWithValueThatHasVerboseReferenceToContainedEnumValue {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..ea1a39cd
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnWebApplicationType(type = WebApplicationType.A.B.C.D.SERVLET)
+public class AnnotationNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..12557326
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present 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 com.example.some.other.WebApplicationType;
+
+@ConditionalOnWebApplicationType(type = ConditionalOnWebApplicationType.WebApplicationType.SERVLET)
+public class AnnotationNamedAttributeWithValueThatHasNecessarilyVerboseReferenceToContainedEnumValue {
+
+ WebApplicationType type;
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.java
new file mode 100644
index 00000000..44d6eb5a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnSomething(type = ConditionalOnSomething.TYPE_ONE)
+public class AnnotationNamedAttributeWithValueThatHasReferenceToContainedConstant {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..c652976e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@ConditionalOnWebApplicationType(type = ConditionalOnWebApplicationType.WebApplicationType.SERVLET)
+public class AnnotationNamedAttributeWithValueThatHasVerboseReferenceToContainedEnumValue {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/preparator/Preparators.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java
similarity index 51%
rename from spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/preparator/Preparators.java
rename to spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java
index 811b7857..f4893731 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/preparator/Preparators.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationOnNewLine.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,25 +14,32 @@
* limitations under the License.
*/
-package io.spring.javaformat.formatter.preparator;
-
-import java.util.function.Consumer;
-
-import io.spring.javaformat.formatter.eclipse.Preparator;
+import org.jspecify.annotations.Nullable;
/**
- * {@link Preparator} instances that can be added.
+ * This is a valid example.
*
* @author Phillip Webb
*/
-public final class Preparators {
+public class AnnotationOnNewLine {
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+ @Nullable String test1() {
+ return "";
+ }
- private Preparators() {
+ @Override
+ @Nullable String test2() {
+ return "";
}
- public static void forEach(Consumer consumer) {
- consumer.accept(new JavadocLineBreakPreparator());
- consumer.accept(new CodeLineBreakPreparator());
+ @Override
+ public @Nullable String test3() {
+ return "";
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
new file mode 100644
index 00000000..614e11c0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+@com.example.web.condition.ConditionalOnWebApplicationType(type = WebApplicationType.A.B.C.D.SERVLET)
+public class AnnotationWithFullyQualifiedNameAndNamedAttributeWithValueThatHasConciseReferenceToContainedEnumValue {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AsciidoctorCallout.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AsciidoctorCallout.java
new file mode 100644
index 00000000..4f8a00ef
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AsciidoctorCallout.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017-present 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 a valid example.
+ *
+ * @author Phillip Webb
+ */
+public class AsciidoctorCallout {
+
+ public void example() {
+ RestAssured.given(this.spec).filter(document("headers", requestHeaders( // <1>
+ )));
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertImport.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertImport.java
new file mode 100644
index 00000000..7646caff
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertImport.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017-present 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.Assert;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Import of banned org.junit.Assert.
+ *
+ * @author Andy Wilkinson
+ */
+public class AssertJBadAssertImport {
+
+ @Test
+ void useTheImports() {
+ assertTrue(true);
+ Assert.assertFalse(false);
+ fail("oops");
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertionsImport.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertionsImport.java
new file mode 100644
index 00000000..5d877c52
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/AssertJBadAssertionsImport.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017-present 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.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Import of banned org.junit.jupiter.api.Assertions.
+ *
+ * @author Andy Wilkinson
+ */
+public class AssertJBadAssertionsImport {
+
+ @Test
+ void useTheImports() {
+ assertTrue(true);
+ Assertions.assertFalse(false);
+ fail("oops");
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchE.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchE.java
index 79aaa40a..c1e81c66 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchE.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchE.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchEx.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchEx.java
index 29d62ba0..e9739ae0 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchEx.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchEx.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchOo.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchOo.java
new file mode 100644
index 00000000..1d21cda5
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchOo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * A invalid catch with o_O as the variable.
+ *
+ * @author Phillip Webb
+ */
+public class CatchOo {
+
+ public void test() {
+ try {
+ new String("foo");
+ }
+ catch (IllegalStateException o_O) {
+ // Ignore
+ }
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchWord.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchWord.java
index 6a77e525..3c7d230b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchWord.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/CatchWord.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedBadCase.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedBadCase.java
new file mode 100644
index 00000000..b806639d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedBadCase.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Bad cases for use of {@link Deprecated @Deprecated}.
+ *
+ * @author Andy Wilkinson
+ */
+@Deprecated
+public class DeprecatedBadCase {
+
+ @java.lang.Deprecated
+ public static final String SOME_CONSTANT;
+
+ @Deprecated(since = "")
+ public void someMethod() {
+
+ }
+
+ @Deprecated
+ private class InnerClass {
+
+ @Deprecated(since = "")
+ private void someInnerMethod() {
+
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedValid.java
new file mode 100644
index 00000000..e52e3ae1
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/DeprecatedValid.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Valid cases for use of {@link Deprecated @Deprecated}.
+ *
+ * @author Andy Wilkinson
+ */
+@Deprecated(since = "2.0.0")
+public class DeprecatedValid {
+
+ @Deprecated(since = "1.2.0")
+ public static final String SOME_CONSTANT;
+
+ @Deprecated(since = "1.3.0")
+ public void someMethod() {
+
+ }
+
+ @Deprecated(since = "1.2.0")
+ private class InnerClass {
+
+ @Deprecated(since = "1.1.0")
+ private void someInnerMethod() {
+
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/FiltersToSkipThis.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/FiltersToSkipThis.java
index d765b047..e25b5cf8 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/FiltersToSkipThis.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/FiltersToSkipThis.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderDate.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderDate.java
index be1cc5c4..2f23d85c 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderDate.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderDate.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderFile.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderFile.java
new file mode 100644
index 00000000..6737309e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderFile.java
@@ -0,0 +1,10 @@
+// (c) Somebody 2017-2019
+
+/**
+ * A custom header file.
+ *
+ * @author Phillip Webb
+ */
+public class HeaderFile {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMismatch.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMismatch.java
index bc256fbb..48e94313 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMismatch.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMismatch.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this foil except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMissingBlankLine.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMissingBlankLine.java
new file mode 100644
index 00000000..a12b1152
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderMissingBlankLine.java
@@ -0,0 +1,9 @@
+// (c) Somebody 2017-2019
+/**
+ * A custom header file.
+ *
+ * @author Phillip Webb
+ */
+public class HeaderMissingBlankLine {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooLong.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooLong.java
index 6520e32b..8b8a0b85 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooLong.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooLong.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooShort.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooShort.java
index 8c10e592..0325be9e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooShort.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderTooShort.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithDateToPresent.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithDateToPresent.java
new file mode 100644
index 00000000..5f6957b3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithDateToPresent.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-present 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.
+ */
+
+/**
+ * The header uses NNNN-present.
+ *
+ * @author Phillip Webb
+ */
+public class HeaderWithDateToPresent {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithSingleDate.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithSingleDate.java
new file mode 100644
index 00000000..11600fcd
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HeaderWithSingleDate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-present 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.
+ */
+
+/**
+ * The header doesn't use a date range.
+ *
+ * @author Phillip Webb
+ */
+public class HeaderWithSingleDate {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorInvalid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorInvalid.java
new file mode 100644
index 00000000..5a6b3543
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorInvalid.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Invlid utility class.
+ *
+ * @author Phillip Webb
+ */
+public class HideUtilityClassConstructorInvalid {
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringApplication.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringApplication.java
new file mode 100644
index 00000000..ece74108
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringApplication.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Usually invalid utility class but OK because it's a Spring Application.
+ *
+ * @author Phillip Webb
+ */
+@SpringBootApplication
+public class HideUtilityClassConstructorSpringApplication {
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringConfiguration.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringConfiguration.java
new file mode 100644
index 00000000..cafe6164
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/HideUtilityClassConstructorSpringConfiguration.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Usually invalid utility class but OK because it's a Spring Configuration.
+ *
+ * @author Phillip Webb
+ */
+@Configuration
+public class HideUtilityClassConstructorSpringConfiguration {
+
+ @Bean
+ public static String myBean() {
+ return "foo";
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageInvalid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageInvalid.java
new file mode 100644
index 00000000..7aa089cf
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageInvalid.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present 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 com.example;
+
+import com.example.util.MyUtils1;
+import com.example.util.MyUtils2;
+import java.util.Objects;
+
+/**
+ * Custom pacakge with valid imports.
+ *
+ * @author Phillip Webb
+ */
+public final class ImportOrderCustomPackageInvalid {
+
+ private ImportOrderCustomPackageValid() {
+ }
+
+ public static void main(String[] args) {
+ if (Objects.nonNull(args)) {
+ MyUtils1.sort(args);
+ MyUtils2.find(args);
+ }
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageValid.java
new file mode 100644
index 00000000..427075e6
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/ImportOrderCustomPackageValid.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present 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 com.example;
+
+import java.util.Objects;
+
+import com.example.util.MyUtils1;
+import com.example.util.MyUtils2;
+
+/**
+ * Custom pacakge with valid imports.
+ *
+ * @author Phillip Webb
+ */
+public final class ImportOrderCustomPackageValid {
+
+ private ImportOrderCustomPackageValid() {
+ }
+
+ public static void main(String[] args) {
+ if (Objects.nonNull(args)) {
+ MyUtils1.sort(args);
+ MyUtils2.find(args);
+ }
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadAnnotation.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadAnnotation.java
new file mode 100644
index 00000000..e9c41790
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadAnnotation.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Test with bad full qualified annotation.
+ *
+ * @author Phillip Webb
+ */
+public class JUnit5BadAnnotation {
+
+ @org.junit.Test
+ void doSomethingWorks() {
+ // test here
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImport.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImport.java
new file mode 100644
index 00000000..2870f5fb
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImport.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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;
+import org.junit.Before;
+
+/**
+ * Test with banned import.
+ *
+ * @author Phillip Webb
+ */
+public class JUnit5BadImport {
+
+ @Before
+ public void bad() {
+ }
+
+ @Test
+ void doSomethingWorks() {
+ // test here
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImportWithOptOut.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImportWithOptOut.java
new file mode 100644
index 00000000..4b471be5
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadImportWithOptOut.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present 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 com.example.OptOutRunner;
+import org.junit.RunWith;
+import org.junit.Test;
+
+/**
+ * Test with banned import but also opt-out trigger.
+ *
+ * @author Phillip Webb
+ */
+@RunWith(OptOutRunner.class)
+public class JUnit5BadImportWithOptOut {
+
+ @Test
+ void doSomethingWorks() {
+ // test here
+ }
+
+}
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
new file mode 100644
index 00000000..0e665db0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-present 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.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestTemplate;
+
+/**
+ * Test with bad modifiers.
+ *
+ * @author Phillip Webb
+ */
+public class JUnit5BadModifier {
+
+ @BeforeAll
+ public static void publicBeforeAll() {
+
+ }
+
+ @BeforeEach
+ public void publicBeforeEach() {
+
+ }
+
+ @AfterAll
+ public static void publicAfterAll() {
+
+ }
+
+ @AfterEach
+ public void publicAfterEach() {
+
+ }
+
+ @BeforeAll
+ private static void privateBeforeAll() {
+
+ }
+
+ @BeforeEach
+ private void privateBeforeEach() {
+
+ }
+
+ @AfterAll
+ private static void privateAfterAll() {
+
+ }
+
+ @AfterEach
+ private void privateAfterEach() {
+
+ }
+
+ @Test
+ public void doSomethingWorks() {
+ // test here
+ }
+
+ @Test
+ private void doSomethingElseWorks() {
+ // test here
+ }
+
+ @TestTemplate
+ public void doSomethingWithTemplateWorks() {
+ // test here
+ }
+
+ @TestTemplate
+ 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..dee91ee2
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5PublicAbstractIsValid.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present 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
new file mode 100644
index 00000000..df921319
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present 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.
+ *
+ * @author Phillip Webb
+ */
+class JUnit5Valid {
+
+ @Test
+ void doSomethingWorks() {
+ // test here
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAnnotationFieldHasEarlierSince.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAnnotationFieldHasEarlierSince.java
new file mode 100644
index 00000000..2ecaf03c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAnnotationFieldHasEarlierSince.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with a good since tag.
+ *
+ * @author Andy Wilkinson
+ * @since 1.2.0
+ */
+public @interface JavadocAnnotationFieldHasEarlierSince {
+
+ /**
+ * An attribute.
+ * @return the value
+ * @since 1.1.0
+ */
+ boolean attribute() default true;
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAuthorWithoutSpace.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAuthorWithoutSpace.java
index 0aba7142..8a421b44 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAuthorWithoutSpace.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocAuthorWithoutSpace.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocBadCase.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocBadCase.java
index 41382834..4a5df596 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocBadCase.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocBadCase.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocInnerClassHasEarlierSince.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocInnerClassHasEarlierSince.java
new file mode 100644
index 00000000..2ad74700
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocInnerClassHasEarlierSince.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with an earlier since tag on an inner class.
+ *
+ * @author Phillip Webb
+ * @since 2.0.0
+ */
+class JavadocInnerClassHasEarlierSince {
+
+ /**
+ * Inner class.
+ *
+ * @since 1.2.3
+ */
+ private static class Inner {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTag.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTag.java
new file mode 100644
index 00000000..dcb778a8
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTag.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with white space.
+ * @param this is a valid param
+ * @author Sushant Kumar Singh
+ */
+public class JavadocMethodEmptyLineBeforeTag {
+
+ /**
+ * Do something.
+ *
+ * @param something a lovely thing
+ */
+ public void test(String something) {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.java
new file mode 100644
index 00000000..2d92f513
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodEmptyLineBeforeTagWithStarAtEnd.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with white space.
+ * @param this is a valid param
+ * @author Sushant Kumar Singh
+ */
+public class JavadocMethodEmptyLineBeforeTagWithStarAtEnd {
+
+ /**
+ * First paragraph.
+ *
+ *
Second paragraph contains an asterisk in a code element: {@code *}.
+ * @since 1.0
+ */
+ public void test() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodHasEarlierSince.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodHasEarlierSince.java
new file mode 100644
index 00000000..d23d74ee
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMethodHasEarlierSince.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with an earlier since tag on a method.
+ *
+ * @author Andy Wilkinson
+ * @since 2.0.0
+ */
+public class JavadocMethodHasEarlierSince {
+
+ /**
+ * Some method.
+ * @since 1.2.3
+ */
+ public void someMethod() {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/FormatterOption.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMissingSince.java
similarity index 66%
rename from spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/FormatterOption.java
rename to spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMissingSince.java
index 0c04a23d..c9afd407 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/FormatterOption.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocMissingSince.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package io.spring.javaformat.formatter;
-
/**
- * Options that can be used to configure a {@link Formatter}.
+ * Javadoc with a bad since tag.
*
* @author Phillip Webb
*/
-public enum FormatterOption {
+public class JavadocMissingSince {
/**
- * Show Eclipse NLS warnings.
+ * Inner class.
*/
- SHOW_NLS_WARNINGS
+ private static class Inner {
+
+ }
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonJavadocComment.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonJavadocComment.java
new file mode 100644
index 00000000..047b2a05
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonJavadocComment.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Example with non javadoc comments.
+ *
+ * @author Phillip Webb
+ */
+public class JavadocNonJavadocComment {
+
+ /* (non-Javadoc)
+ * Example.
+ */
+ public void one() {
+ }
+
+ /**
+ * (non-Javadoc).
+ */
+ public void two() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSince.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSince.java
new file mode 100644
index 00000000..4f0f2fde
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSince.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with a bad since tag.
+ *
+ * @author Phillip Webb
+ * @since 1.2.3
+ */
+class JavadocNonPublicSince {
+
+ /**
+ * Inner class.
+ *
+ * @since 1.2.4
+ */
+ private static class Inner {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideAnnotation.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideAnnotation.java
new file mode 100644
index 00000000..b79a5a85
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideAnnotation.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with a good since tag.
+ *
+ * @author Phillip Webb
+ * @since 1.2.3
+ */
+public @interface JavadocNonPublicSinceInsideAnnotation {
+
+ /**
+ * Inner enum.
+ *
+ * @since 1.2.4
+ */
+ enum Inner {
+
+ FOO
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideInterface.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideInterface.java
new file mode 100644
index 00000000..c0e4b412
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocNonPublicSinceInsideInterface.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Javadoc with a good since tag.
+ *
+ * @author Phillip Webb
+ * @since 1.2.3
+ */
+public interface JavadocNonPublicSinceInsideInterface {
+
+ /**
+ * Inner enum.
+ *
+ * @since 1.2.4
+ */
+ enum Inner {
+
+ FOO
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocSoundtrack.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocSoundtrack.java
new file mode 100644
index 00000000..846bf48d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocSoundtrack.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Valid Javadoc.
+ *
+ * @param this is a valid param
+ * @author Phillip Webb
+ * @soundtrack Gina G - Ooh Aah Just A Little Bit
+ */
+public class JavadocSoundtrack {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocValid.java
index 6b925542..6584ef36 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocValid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocValid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -15,7 +15,7 @@
*/
/**
- * Javadoc with a bad author tag.
+ * Valid Javadoc.
*
* @param this is a valid param
* @author Phillip Webb
@@ -43,7 +43,37 @@ public void test2(String something) {
* @return the thing
* @throws RuntimeException on the error
*/
- public String test3(String something) throw RuntimeException {
+ public String test3(String something) throws RuntimeException {
+ }
+
+ /**
+ * Class with a numeric date since.
+ * @since 28.12.2003
+ */
+ public class NumericDateSince {
+
+ /**
+ * Method with version-based since.
+ * @since 1.3.0
+ */
+ public void versionSince() {
+ }
+
+ }
+
+ /**
+ * Class with an alphanumeric date since.
+ * @since 16 April 2001
+ */
+ public class AlphanumericDateSince {
+
+ /**
+ * Method with version-based since.
+ * @since 1.3.0
+ */
+ public void versionSince() {
+ }
+
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaExtraParens.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaExtraParens.java
index b638608a..5e82a117 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaExtraParens.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaExtraParens.java
@@ -1,12 +1,12 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaMissingParens.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaMissingParens.java
index 77775604..9ab33a37 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaMissingParens.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaMissingParens.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryBlock.java
index f1c47d40..cfb42294 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryEmptyBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryEmptyBlock.java
index 62f736f3..b8246fee 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryEmptyBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryEmptyBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfBlock.java
index 01ff0754..5468bb48 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfElseBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfElseBlock.java
index f0e58f8e..473fa096 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfElseBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryIfElseBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryThrowBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryThrowBlock.java
index 18ada5f4..61350fe8 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryThrowBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryThrowBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryTryBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryTryBlock.java
index 1884c28f..2c874d0d 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryTryBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryTryBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryVoidCallable.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryVoidCallable.java
new file mode 100644
index 00000000..54864d72
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaNecessaryVoidCallable.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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 java.util.concurrent.Callable;
+
+/**
+ * This is a valid example of a lambda where the block is required.
+ *
+ * @author Andy Wilkinson
+ */
+public class LambdaNecessaryVoidCallable {
+
+ public Callable test() {
+ return () -> {
+ new String("test");
+ return null;
+ };
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaSwitch.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaSwitch.java
new file mode 100644
index 00000000..55640621
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaSwitch.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present 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 java.util.function.Function;
+
+/**
+ * Lambda in a switch statement.
+ *
+ * @author Josef Reichardt
+ */
+public class LambdaSwitch {
+
+ private void sayHello(String[] args) {
+ Function getText = (cnt) -> "Number of args: " + cnt;
+ String message = switch (args.length) {
+ case 0 -> "No arg";
+ case 1 -> "One arg";
+ default -> getText.apply(args.length);
+ };
+ System.out.println(message);
+ }
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaUnnecessaryBlock.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaUnnecessaryBlock.java
index 1c983775..df215545 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaUnnecessaryBlock.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaUnnecessaryBlock.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import java.util.function.Consumer;
import java.util.function.Function;
/**
@@ -30,7 +31,7 @@ public Function test() {
};
}
- public Consimer test() {
+ public Consumer test() {
return (string) -> {
new StringBuilder()
.append("foo");
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaValid.java
index bd198b42..768488e7 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaValid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LambdaValid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceSpaces.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceSpaces.java
new file mode 100644
index 00000000..0e69080a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceSpaces.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present 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 expects only tabs.
+ *
+ * @author Phillip Webb
+ */
+public class LeadingWhitespaceSpaces {
+
+ /**
+ * Comments are ignored.
+ */
+ public void hello() {
+ System.out.println("World");
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabs.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabs.java
new file mode 100644
index 00000000..53d64c19
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabs.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present 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 expects only tabs.
+ *
+ * @author Phillip Webb
+ */
+public class LeadingWhitespaceTabs {
+
+ /**
+ * Comments are ignored.
+ */
+ public void hello() {
+ System.out.println("World");
+ }
+
+}
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..21a2311a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/LeadingWhitespaceTabsAndTextBlock.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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/MethodOrderInvalid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderInvalid.java
index 0f4e6ec2..0db3e04c 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderInvalid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderInvalid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderValid.java
index df0feb0d..b44ad87b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderValid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodOrderValid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithOverride.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithOverride.java
new file mode 100644
index 00000000..6a74b3b7
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithOverride.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Good visibility because, while class is final, protected methods are
+ * annotated with {@code @Override}.
+ *
+ * @author Andy Wilkinson
+ */
+public final class MethodVisibilityFinalClassWithOverride {
+
+ @Override
+ protected void good() {
+ }
+
+ @Override
+ protected static void goodStatic() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithProtectedMethod.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithProtectedMethod.java
new file mode 100644
index 00000000..7452e21f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityFinalClassWithProtectedMethod.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Bad visibility because class is final.
+ *
+ * @author Andy Wilkinson
+ */
+public final class MethodVisibilityFinalClassWithProtectedMethod {
+
+ protected void bad() {
+ }
+
+ protected static void badStatic() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityInnerClassesWithPublicMethod.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityInnerClassesWithPublicMethod.java
new file mode 100644
index 00000000..262a258f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityInnerClassesWithPublicMethod.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Bad visibility because of public method.
+ *
+ * @author Phillip Webb
+ */
+public class MethodVisibilityInnerClassesWithPublicMethod {
+
+ private static class PrivateInnerClass {
+
+ public void badPrivateInner() {
+ }
+
+ }
+
+ protected static class ProtectedInnerClass {
+
+ public void okProtectedInner() {
+ }
+
+ }
+
+ static class DefaultInnerClass {
+
+ public void badDefaultInner() {
+ }
+
+ }
+
+ public static class PublicInnerClass {
+
+ public void okPublicInner() {
+ }
+
+ }
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityPackagePrivateWithPublicMethod.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityPackagePrivateWithPublicMethod.java
new file mode 100644
index 00000000..c6377f3d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityPackagePrivateWithPublicMethod.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Bad visibility because of public method.
+ *
+ * @author Phillip Webb
+ */
+class MethodVisibilityPackagePrivateWithPublicMethod {
+
+ MethodVisibilityPackagePrivateWithPublicMethod() {
+ }
+
+ public void bad() {
+ }
+
+ public static void badStatic() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityProtectedWithPublicMethod.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityProtectedWithPublicMethod.java
new file mode 100644
index 00000000..fe36ec8c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityProtectedWithPublicMethod.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Good visibility because class is protected.
+ *
+ * @author Phillip Webb
+ */
+protected class MethodVisibilityProtectedWithPublicMethod {
+
+ MethodVisibilityPackagePrivateWithPublicMethod() {
+ }
+
+ public void bad() {
+ }
+
+ public static void badStatic() {
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityWithOverride.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityWithOverride.java
new file mode 100644
index 00000000..c4b8d3b3
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/MethodVisibilityWithOverride.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Good visibility because of {@code @Override} annotation.
+ *
+ * @author Phillip Webb
+ */
+public class MethodVisibilityWithOverride {
+
+ private static class PrivateInnerClass {
+
+ @Override
+ public void okPrivateInner() {
+ }
+
+ }
+
+ protected static class ProtectedInnerClass {
+
+ @Override
+ public void okProtectedInner() {
+ }
+
+ }
+
+ static class DefaultInnerClass {
+
+ @Override
+ public void okDefaultInner() {
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NestedInterfaceItems.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NestedInterfaceItems.java
new file mode 100644
index 00000000..8f9bb820
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NestedInterfaceItems.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present 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;
+
+/**
+ * Interface with implicit public elements.
+ *
+ * @author Phillip Webb
+ */
+public interface NestedInterfaceItems {
+
+ /**
+ * A nested class class.
+ */
+ class NestedClass {
+
+ public NestedClass(String arg) {
+ // This is valid because nested class is implicitly public
+ }
+
+ public void thisIsFine() {
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NewlineAtEndOfFile.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NewlineAtEndOfFile.java
index 7c583197..436c72a4 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NewlineAtEndOfFile.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NewlineAtEndOfFile.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-public class MissingNewLine {
+public class NewlineAtEndOfFile {
}
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NoThis.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NoThis.java
index 3a40b334..556214ab 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NoThis.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NoThis.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNonNull.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNonNull.java
new file mode 100644
index 00000000..870a40e9
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNonNull.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present 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 javax.annotation.Nonnull;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * JSpecify's NonNull annotation should be used.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityBannedNonNull {
+
+ public void method(@Nonnull String one, @NonNull String two) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNullable.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNullable.java
new file mode 100644
index 00000000..61d918d1
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityBannedNullable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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 javax.annotation.Nullable;
+
+/**
+ * JSpecify's Nullable annotation should be used.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityBannedNullable {
+
+ public void method(@Nullable String one) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingFieldType.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingFieldType.java
new file mode 100644
index 00000000..a54069ef
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingFieldType.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present 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;
+
+/**
+ * {@code @Nullable} should appear immediately before the parameter type.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityNullableNotPrecedingFieldType {
+
+ private @Nullable static String field = null;
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingParameterType.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingParameterType.java
new file mode 100644
index 00000000..bd55d9d2
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingParameterType.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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;
+
+/**
+ * {@code @Nullable} should appear immediately before the parameter type.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityNullableNotPrecedingParameterType {
+
+ public String method(@Nullable final String arg) {
+ return "result";
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingReturnType.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingReturnType.java
new file mode 100644
index 00000000..9b9b8a4e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableNotPrecedingReturnType.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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;
+
+/**
+ * {@code @Nullable} should appear immediately before the return type.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityNullableNotPrecedingReturnType {
+
+ @Nullable public String method() {
+ return "result";
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableOnSeparateLine.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableOnSeparateLine.java
new file mode 100644
index 00000000..b18ee10a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityNullableOnSeparateLine.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present 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;
+
+/**
+ * {@code @Nullable} should appear immediately before the return type.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityNullableOnSeparateLine {
+
+ @Nullable
+ public String method() {
+ return "result";
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityValid.java
new file mode 100644
index 00000000..e0ea5cca
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/NullabilityValid.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017-present 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 java.util.Collections;
+import java.util.Map;
+
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Valid use of nullability annotations.
+ *
+ * @author Andy Wilkinson
+ */
+public class NullabilityValid {
+
+ private @Nullable String field;
+
+ public NullabilityValid(@Nullable String arg, final @Nullable String anotherArg) {
+
+ }
+
+ public @Nullable String publicMethod() {
+ return "result";
+ }
+
+ @Nullable String packagePrivateMethod() {
+ return "result";
+ }
+
+ public Map genericReturnType() {
+ return Collections.emptyMap();
+ }
+
+ void genericParameter(Map<@Nullable ? extends String, @Nullable String> arg) {
+
+ }
+
+ void parameter(@Nullable String arg) {
+
+ }
+
+ void finalParameter(final @Nullable String arg) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameInvalid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameInvalid.java
new file mode 100644
index 00000000..59f7dc88
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameInvalid.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present 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 example of a class name not matching its filename.
+ *
+ * @author Christoph Dreis
+ */
+public class NameNotMatching {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameValid.java
new file mode 100644
index 00000000..6814ed2f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/OuterTypeFilenameValid.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present 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 a valid example of a class name matching its filename.
+ *
+ * @author Christoph Dreis
+ */
+public class OuterTypeFilenameValid {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/SpringApplication.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/SpringApplication.java
index 33a838f0..d72c300b 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/SpringApplication.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/SpringApplication.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -935,8 +935,8 @@ public void setMainApplicationClass(Class> mainApplicationClass) {
/**
* Returns whether this {@link SpringApplication} is running within a web environment.
* @return {@code true} if running within a web environment, otherwise {@code false}.
- * @see #setWebEnvironment(boolean)
* @deprecated since 2.0.0 in favor of {@link #getWebApplicationType()}
+ * @see #setWebEnvironment(boolean)
*/
@Deprecated
public boolean isWebEnvironment() {
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEquals.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEquals.java
index 08a42aed..afd0926d 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEquals.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEquals.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsAny.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsAny.java
index d818405e..9eb48eb9 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsAny.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsAny.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsNever.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsNever.java
index 83df865c..3a30c31a 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsNever.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryEqualsEqualsNever.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInArray.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInArray.java
index b5472d6d..99c43de5 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInArray.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInArray.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInIf.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInIf.java
index 71c157aa..6414b748 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInIf.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInIf.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -24,7 +24,9 @@ public class TernaryInIf {
public void test() {
boolean a = true;
boolean b = false;
- if ((a != b) ? true : false) {
+ int c = 1;
+ int d = 2;
+ if ((a != b) ? d < c : c >= d) {
System.out.println("OK");
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInWhile.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInWhile.java
index ddc333cf..1bef3bee 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInWhile.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryInWhile.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -24,7 +24,9 @@ public class TernaryInWhile {
public void test() {
boolean a = true;
boolean b = false;
- while ((a != b) ? true : false) {
+ int c = 1;
+ int d = 2;
+ while ((a != b) ? d < c : c >= d) {
System.out.println("OK");
}
}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensAndPlus.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensAndPlus.java
index 06303fb2..36e22af3 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensAndPlus.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensAndPlus.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensInvalid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensInvalid.java
index bca4d7ea..cbd7ce9e 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensInvalid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensInvalid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensValid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensValid.java
index bda2d180..f9f490ee 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensValid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TernaryParensValid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TryWithResources.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TryWithResources.java
new file mode 100644
index 00000000..c68396dc
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/TryWithResources.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-present 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 a valid example.
+ *
+ * @author Phillip Webb
+ */
+public class TryWithResources {
+
+ public void test() {
+ try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
+ System.out.println(session);
+ }
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/Valid.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/Valid.java
index eb199261..e14319f1 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/Valid.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/Valid.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArray.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArray.java
new file mode 100644
index 00000000..2d25cfa7
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArray.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Whitespace is expected before {@code []} when @Nullable.
+ *
+ * @author Andy Wilkinson
+ */
+public class WhitespaceNullableArray {
+
+ void bytes(int @Nullable [] elements) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArrayElements.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArrayElements.java
new file mode 100644
index 00000000..6e23b7fb
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableArrayElements.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Whitespace is expected before {@code type[]} when @Nullable.
+ *
+ * @author Andy Wilkinson
+ */
+public class WhitespaceNullableArrayElements {
+
+ void bytes(@Nullable int[] elements) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableVarargs.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableVarargs.java
new file mode 100644
index 00000000..1b4eaeae
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceNullableVarargs.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Whitespace is expected before ... when @Nullable.
+ *
+ * @author Andy Wilkinson
+ */
+public class WhitespaceNullableVarargs {
+
+ void bytes(int @Nullable ... elements) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceVarargs.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceVarargs.java
new file mode 100644
index 00000000..2a962abe
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/WhitespaceVarargs.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present 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.
+ */
+
+/**
+ * Whitespace is not expected before {@code ...}.
+ *
+ * @author Andy Wilkinson
+ */
+public class WhitespaceVarargs {
+
+ void bytes(int ... elements) {
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/nopackageinfo/NoPackageInfo.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/nopackageinfo/NoPackageInfo.java
new file mode 100644
index 00000000..5ae26280
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/nopackageinfo/NoPackageInfo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2017-present 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 nopackageinfo;
+
+/**
+ * A class in a package with no {@code package-info.java} file.
+ *
+ * @author Andy Wilkinson
+ */
+class NoPackageInfo {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing-but-is-not.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing-but-is-not.java
index 3850a9ec..a7f468eb 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing-but-is-not.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing-but-is-not.java
@@ -1,4 +1,4 @@
/**
* Something.
*/
-package com.example
+package com.example;
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing.java
index 2f645a7d..039f3f05 100644
--- a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing.java
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info-header-must-be-missing.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this foil except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,4 +14,4 @@
* limitations under the License.
*/
-package com.example
+package com.example;
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/package-info.java
new file mode 100644
index 00000000..e69de29b
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..cdc31f8c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/AnnotationEndingInTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present 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..d79b6453
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/InterfaceEndingInTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present 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-checkstyle/src/test/resources/source/src/test/java/NamedTest.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/NamedTest.java
new file mode 100644
index 00000000..a042f613
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/NamedTest.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present 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 a test with the wrong name.
+ *
+ * @author Phillip Webb
+ */
+public class NamedTest {
+
+}
diff --git a/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/NamedTests.java b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/NamedTests.java
new file mode 100644
index 00000000..423428e5
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/src/test/java/NamedTests.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present 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 a test with the correct name.
+ *
+ * @author Phillip Webb
+ */
+public class NamedTests {
+
+}
diff --git a/spring-javaformat/spring-javaformat-config/pom.xml b/spring-javaformat/spring-javaformat-config/pom.xml
new file mode 100644
index 00000000..e984a073
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/pom.xml
@@ -0,0 +1,15 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-config
+ Spring JavaFormat Config
+
+ ${basedir}/../..
+
+
diff --git a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/DefaultJavaFormatConfig.java b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/DefaultJavaFormatConfig.java
new file mode 100644
index 00000000..d2b5ee8c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/DefaultJavaFormatConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-present 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.config;
+
+/**
+ * Default {@link JavaFormatConfig} implementation used when no config file is found.
+ *
+ * @author Phillip Webb
+ */
+class DefaultJavaFormatConfig implements JavaFormatConfig {
+
+ private final JavaBaseline javaBaseline;
+
+ private final IndentationStyle indentationStyle;
+
+ DefaultJavaFormatConfig(JavaBaseline javaBaseline, IndentationStyle indentationStyle) {
+ this.javaBaseline = javaBaseline;
+ this.indentationStyle = indentationStyle;
+ }
+
+ @Override
+ public JavaBaseline getJavaBaseline() {
+ return this.javaBaseline;
+ }
+
+ @Override
+ public IndentationStyle getIndentationStyle() {
+ return this.indentationStyle;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/IndentationStyle.java b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/IndentationStyle.java
new file mode 100644
index 00000000..f6e2144d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/IndentationStyle.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.config;
+
+/**
+ * Indentation styles that can be used.
+ *
+ * @author Phillip Webb
+ */
+public enum IndentationStyle {
+
+ /**
+ * Indent with tabs.
+ */
+ TABS,
+
+ /**
+ * Indent with spaces.
+ */
+ SPACES
+
+}
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
new file mode 100644
index 00000000..a27c3df0
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaBaseline.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present 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.config;
+
+/**
+ * Java JDK baseline version expected be used when formatting.
+ *
+ * @author Phillip Webb
+ */
+public enum JavaBaseline {
+
+ /**
+ * Use JDK 8+ compatible formatter.
+ */
+ V8,
+
+ /**
+ * Use JDK 17+ or higher compatible formatter.
+ */
+ 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
new file mode 100644
index 00000000..23bf45c8
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/JavaFormatConfig.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017-present 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.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+
+/**
+ * Support for the {@code .springjavaformatconfig} file that can be used to apply settings
+ * on a per-project basis.
+ *
+ * @author Phillip Webb
+ */
+public interface JavaFormatConfig {
+
+ /**
+ * The default {@link JavaFormatConfig}.
+ */
+ JavaFormatConfig DEFAULT = of(JavaBaseline.V17, IndentationStyle.TABS);
+
+ /**
+ * Java JDK baseline version expected be used when formatting.
+ * @return the JDK version
+ */
+ JavaBaseline getJavaBaseline();
+
+ /**
+ * Return the indentation style that should be used with the project.
+ * @return the indentation style
+ */
+ IndentationStyle getIndentationStyle();
+
+ /**
+ * Find and load a {@code .springjavaformatconfig} by searching from the given file.
+ * @param path the file or directory to search from
+ * @return a loaded {@link JavaFormatConfig} or {@link #DEFAULT} if no
+ * {@code .springjavaformatconfig} file is found
+ */
+ static JavaFormatConfig findFrom(Path path) {
+ return findFrom((path != null) ? path.toFile() : (File) null);
+ }
+
+ /**
+ * Find and load a {@code .springjavaformatconfig} by searching from the given file.
+ * @param file the file or directory to search from
+ * @return a loaded {@link JavaFormatConfig} or {@link #DEFAULT} if no
+ * {@code .springjavaformatconfig} file is found
+ */
+ static JavaFormatConfig findFrom(File file) {
+ if (file != null && file.isFile()) {
+ return findFrom(file.getParentFile());
+ }
+ try {
+ while (file != null) {
+ File candidate = new File(file, ".springjavaformatconfig");
+ if (candidate.exists() && candidate.isFile()) {
+ return load(candidate);
+ }
+ file = file.getParentFile();
+ }
+ }
+ catch (Exception ex) {
+ }
+ return DEFAULT;
+ }
+
+ /**
+ * Load a {@link JavaFormatConfig} from the given file.
+ * @param file the file to load
+ * @return the loaded config
+ */
+ static JavaFormatConfig load(File file) {
+ try {
+ return PropertiesJavaFormatConfig.load(file);
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
+ * Load a {@link JavaFormatConfig} from the given input stream.
+ * @param inputStream the input stream to load
+ * @return the loaded config
+ */
+ static JavaFormatConfig load(InputStream inputStream) {
+ try {
+ return PropertiesJavaFormatConfig.load(inputStream);
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
+ * Factory method to create a {@link JavaFormatConfig} with specific settings.
+ * @param javaBaseline The baseline JDK version
+ * @param indentationStyle the indentation style
+ * @return a {@link JavaFormatConfig} instance
+ */
+ static JavaFormatConfig of(JavaBaseline javaBaseline, IndentationStyle indentationStyle) {
+ return new DefaultJavaFormatConfig(javaBaseline, indentationStyle);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/PropertiesJavaFormatConfig.java b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/PropertiesJavaFormatConfig.java
new file mode 100644
index 00000000..d631312d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/main/java/io/spring/javaformat/config/PropertiesJavaFormatConfig.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present 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.config;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * {@link JavaFormatConfig} backed by a properties file.
+ *
+ * @author Phillip Webb
+ */
+class PropertiesJavaFormatConfig implements JavaFormatConfig {
+
+ private final Properties properties;
+
+ PropertiesJavaFormatConfig(Properties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public JavaBaseline getJavaBaseline() {
+ Object value = this.properties.get("java-baseline");
+ return (value != null) ? JavaBaseline.valueOf("V" + value.toString().toUpperCase().trim())
+ : DEFAULT.getJavaBaseline();
+ }
+
+ @Override
+ public IndentationStyle getIndentationStyle() {
+ Object value = this.properties.get("indentation-style");
+ return (value != null) ? IndentationStyle.valueOf(value.toString().toUpperCase().trim())
+ : DEFAULT.getIndentationStyle();
+ }
+
+ static JavaFormatConfig load(File file) throws IOException {
+ try (InputStream inputStream = new FileInputStream(file)) {
+ return load(inputStream);
+ }
+ }
+
+ static JavaFormatConfig load(InputStream inputStream) throws IOException {
+ Properties properties = new Properties();
+ properties.load(inputStream);
+ return new PropertiesJavaFormatConfig(properties);
+ }
+
+}
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
new file mode 100644
index 00000000..2c702617
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-config/src/test/java/io/spring/javaformat/config/PropertiesJavaFormatConfigTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017-present 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.config;
+
+import java.util.Properties;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link PropertiesJavaFormatConfig}.
+ *
+ * @author Phillip Webb
+ */
+class PropertiesJavaFormatConfigTests {
+
+ @Test
+ void getJavaBaselineWhenNoPropertyReturnsJava11() {
+ Properties properties = new Properties();
+ PropertiesJavaFormatConfig config = new PropertiesJavaFormatConfig(properties);
+ assertThat(config.getJavaBaseline()).isEqualTo(JavaBaseline.V17);
+ }
+
+ @Test
+ void getJavaBaselineWhenPropertyReturnsPropertyValue() {
+ Properties properties = new Properties();
+ properties.setProperty("java-baseline", "8");
+ PropertiesJavaFormatConfig config = new PropertiesJavaFormatConfig(properties);
+ assertThat(config.getJavaBaseline()).isEqualTo(JavaBaseline.V8);
+ }
+
+ @Test
+ void getIndentationStyleWhenNoPropertyReturnsJava11() {
+ Properties properties = new Properties();
+ PropertiesJavaFormatConfig config = new PropertiesJavaFormatConfig(properties);
+ assertThat(config.getIndentationStyle()).isEqualTo(IndentationStyle.TABS);
+ }
+
+ @Test
+ void getIndentationStyleWhenPropertyReturnsPropertyValue() {
+ Properties properties = new Properties();
+ properties.setProperty("indentation-style", "spaces");
+ PropertiesJavaFormatConfig config = new PropertiesJavaFormatConfig(properties);
+ assertThat(config.getIndentationStyle()).isEqualTo(IndentationStyle.SPACES);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..5e2e9099
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Spring Formatter Eclipse Runtime JDK17
+Bundle-SymbolicName: spring-javaformat-formatter-eclipse-jdk17
+Bundle-Version: 0.0.48.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,
+ org.eclipse.jface.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
+ org.eclipse.jface.text.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
+ org.eclipse.text.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional
+Bundle-RequiredExecutionEnvironment: JavaSE-11
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/build.properties b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/build.properties
similarity index 100%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-runtime/build.properties
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/build.properties
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml
new file mode 100644
index 00000000..0e73c0e4
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk17/pom.xml
@@ -0,0 +1,213 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-eclipse-jdk17
+ eclipse-plugin
+ Spring JavaFormat Eclipse JDK-17
+
+ ${basedir}/../..
+ org.eclipse.jdt.core.source,org.eclipse.jface.source,org.eclipse.text.source
+
+
+
+ Eclipse Public License, Version 1.0
+ https://www.eclipse.org/legal/epl-v10.html
+
+
+
+
+ eclipse-jdk17
+ p2
+ ${eclipse.jdk17.repository}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-rewriter
+ ${project.version}
+
+
+ ant-contrib
+ ant-contrib
+ ${ant-contrib.version}
+
+
+ ant
+ ant
+
+
+
+
+ org.apache.ant
+ ant-nodeps
+ ${ant.version}
+
+
+
+
+ rewrite-bytecode
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+ repackage-source
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.tycho
+ tycho-packaging-plugin
+
+ false
+
+
+
+ org.eclipse.tycho
+ tycho-maven-plugin
+
+
+ org.eclipse.tycho
+ target-platform-configuration
+
+
+ org.eclipse.tycho
+ tycho-versions-plugin
+
+
+ update-eclipse-version
+ initialize
+
+ update-eclipse-metadata
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack-dependencies
+
+ unpack-dependencies
+
+ prepare-package
+
+ ${project.build.outputDirectory}
+ META-INF/*,**.dll,**.so,**.java
+ ${sourceartifacts}
+
+
+
+ unpack-source-dependencies
+
+ unpack-dependencies
+
+ prepare-package
+
+ ${project.build.directory}/sources
+ ${sourceartifacts}
+
+
+
+
+
+ com.github.wvengen
+ proguard-maven-plugin
+
+
+ reduce-eclipse-runtime
+ package
+
+ proguard
+
+
+ false
+
+ ${java.home}/jmods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-rewriter
+ ${project.version}
+ provided
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/META-INF/MANIFEST.MF b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
similarity index 72%
rename from spring-javaformat/spring-javaformat-formatter-eclipse-runtime/META-INF/MANIFEST.MF
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
index a7ad4746..3c5dbb8b 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/META-INF/MANIFEST.MF
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/META-INF/MANIFEST.MF
@@ -1,12 +1,12 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: Spring Formatter Eclipse Runtime
-Bundle-SymbolicName: spring-javaformat-formatter-eclipse-runtime
-Bundle-Version: 0.0.7.qualifier
+Bundle-Name: Spring Formatter Eclipse JDK8
+Bundle-SymbolicName: spring-javaformat-formatter-eclipse-jdk8
+Bundle-Version: 0.0.48.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,
org.eclipse.jface.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
org.eclipse.jface.text.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional,
org.eclipse.text.source;bundle-version="[1.0.0,10.0.0)";resolution:=optional
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-11
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/build.properties b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/build.properties
new file mode 100755
index 00000000..45d47043
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = target/classes
+bin.includes = META-INF/,\
+ .,\
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml
new file mode 100644
index 00000000..0e52bf06
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdk8/pom.xml
@@ -0,0 +1,213 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-eclipse-jdk8
+ eclipse-plugin
+ Spring JavaFormat Eclipse JDK-8
+
+ ${basedir}/../..
+ org.eclipse.jdt.core.source,org.eclipse.jface.source,org.eclipse.text.source
+
+
+
+ Eclipse Public License, Version 1.0
+ https://www.eclipse.org/legal/epl-v10.html
+
+
+
+
+ eclipse-jdk8
+ p2
+ ${eclipse.jdk8.repository}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-rewriter
+ ${project.version}
+
+
+ ant-contrib
+ ant-contrib
+ ${ant-contrib.version}
+
+
+ ant
+ ant
+
+
+
+
+ org.apache.ant
+ ant-nodeps
+ ${ant.version}
+
+
+
+
+ rewrite-bytecode
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+ repackage-source
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.tycho
+ tycho-packaging-plugin
+
+ false
+
+
+
+ org.eclipse.tycho
+ tycho-maven-plugin
+
+
+ org.eclipse.tycho
+ target-platform-configuration
+
+
+ org.eclipse.tycho
+ tycho-versions-plugin
+
+
+ update-eclipse-version
+ initialize
+
+ update-eclipse-metadata
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack-dependencies
+
+ unpack-dependencies
+
+ prepare-package
+
+ ${project.build.outputDirectory}
+ META-INF/*,**.dll,**.so,**.java
+ ${sourceartifacts}
+
+
+
+ unpack-source-dependencies
+
+ unpack-dependencies
+
+ prepare-package
+
+ ${project.build.directory}/sources
+ ${sourceartifacts}
+
+
+
+
+
+ com.github.wvengen
+ proguard-maven-plugin
+
+
+ reduce-eclipse-runtime
+ package
+
+ proguard
+
+
+ false
+
+ ${java.home}/jmods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-rewriter
+ ${project.version}
+ provided
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
similarity index 74%
rename from spring-javaformat/spring-javaformat-formatter-eclipse/pom.xml
rename to spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
index 6f9e13b0..9aef9a9a 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk17/pom.xml
@@ -1,23 +1,23 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOT
- spring-javaformat-formatter-eclipse
- Spring JavaFormat Eclipse
+ spring-javaformat-formatter-eclipse-jdt-jdk17
+ Spring JavaFormat Eclipse JDT JDK-17${basedir}/../..io.spring.javaformat
- spring-javaformat-formatter-eclipse-runtime
- 0.0.7-SNAPSHOT
+ spring-javaformat-formatter-eclipse-jdk17
+ ${project.version}true
@@ -48,16 +48,16 @@
- io.spring.javaformat:spring-javaformat-formatter-eclipse-runtime
+ io.spring.javaformat:spring-javaformat-formatter-eclipse-jdk17
- org/eclipse/jdt/internal/formatter/**
+ org/eclipse/jdt/**
- org.eclipse.jdt.internal.formatter
- io.spring.javaformat.formatter.eclipse
+ org.eclipse.jdt
+ io.spring.javaformat.eclipse.jdt.jdk17false
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse/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 57%
rename from spring-javaformat/spring-javaformat-formatter-eclipse/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 5caf3e37..a2664b72 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse/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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,7 +21,11 @@
import java.util.List;
import java.util.Map;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.formatter.Preparator.Phase;
/**
@@ -32,14 +36,15 @@
*/
public class ExtendedCodeFormatter extends DefaultCodeFormatter {
+ private static boolean useLegacyTokenize = false;
+
private final List preparators = new ArrayList<>();
public ExtendedCodeFormatter() {
super();
}
- public ExtendedCodeFormatter(DefaultCodeFormatterOptions defaultCodeFormatterOptions,
- Map options) {
+ public ExtendedCodeFormatter(DefaultCodeFormatterOptions defaultCodeFormatterOptions, Map options) {
super(defaultCodeFormatterOptions, options);
}
@@ -55,6 +60,43 @@ protected void addPreparator(Preparator preparator) {
this.preparators.add(preparator);
}
+ @Override
+ protected void tokenizeSource(int kind) {
+ if (useLegacyTokenize) {
+ legacyTokenizeSource(kind);
+ return;
+ }
+ try {
+ super.tokenizeSource(kind);
+ }
+ catch (NoSuchMethodError ex) {
+ useLegacyTokenize = true;
+ legacyTokenizeSource(kind);
+ }
+ }
+
+ private void legacyTokenizeSource(int kind) {
+ this.tokens.clear();
+ long sourceLevel = CompilerOptions.versionToJdkLevel(this.sourceLevel);
+ Scanner scanner = new Scanner(true, false, false, sourceLevel, null, null, false);
+ scanner.setSource(this.sourceArray);
+ scanner.fakeInModule = (kind & K_MODULE_INFO) != 0;
+ while (true) {
+ try {
+ int tokenType = scanner.getNextToken();
+ if (tokenType == TerminalTokens.TokenNameEOF) {
+ break;
+ }
+ Token token = Token.fromCurrent(scanner, tokenType);
+ this.tokens.add(token);
+ }
+ catch (InvalidInputException ex) {
+ Token token = Token.fromCurrent(scanner, TerminalTokens.TokenNameNotAToken);
+ this.tokens.add(token);
+ }
+ }
+ }
+
@Override
protected void prepareWraps(int kind) {
ASTNode astRoot = getField("astRoot", ASTNode.class);
@@ -64,11 +106,10 @@ protected void prepareWraps(int kind) {
applyPreparators(Phase.POST_WRAPPING, kind, astRoot, tokenManager);
}
- private void applyPreparators(Phase preWrapping, int kind, ASTNode astRoot,
- TokenManager tokenManager) {
+ private void applyPreparators(Phase preWrapping, int kind, ASTNode astRoot, TokenManager tokenManager) {
this.preparators.stream()
- .filter((preparator) -> preparator.getPhase() == preWrapping)
- .forEach((preparator) -> preparator.apply(kind, tokenManager, astRoot));
+ .filter((preparator) -> preparator.getPhase() == preWrapping)
+ .forEach((preparator) -> preparator.apply(kind, tokenManager, astRoot));
}
@SuppressWarnings("unchecked")
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse/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 92%
rename from spring-javaformat/spring-javaformat-formatter-eclipse/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 e0a8d12d..bfd16b37 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse/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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -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
new file mode 100644
index 00000000..30a2af39
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-eclipse-jdt-jdk8
+ Spring JavaFormat Eclipse JDT JDK-8
+
+ ${basedir}/../..
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-jdk8
+ ${project.version}
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-source
+ package
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+
+
+ io.spring.javaformat:spring-javaformat-formatter-eclipse-jdk8
+
+ org/eclipse/jdt/**
+
+
+
+
+
+ org.eclipse.jdt
+ io.spring.javaformat.eclipse.jdt.jdk8
+
+
+ false
+ true
+ true
+
+
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
new file mode 100644
index 00000000..a2664b72
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/ExtendedCodeFormatter.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017-present 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 org.eclipse.jdt.internal.formatter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.formatter.Preparator.Phase;
+
+/**
+ * Extended version of {@link DefaultCodeFormatter} that allows additional
+ * {@link Preparator preparators} to be used.
+ *
+ * @author Phillip Webb
+ */
+public class ExtendedCodeFormatter extends DefaultCodeFormatter {
+
+ private static boolean useLegacyTokenize = false;
+
+ private final List preparators = new ArrayList<>();
+
+ public ExtendedCodeFormatter() {
+ super();
+ }
+
+ public ExtendedCodeFormatter(DefaultCodeFormatterOptions defaultCodeFormatterOptions, Map options) {
+ super(defaultCodeFormatterOptions, options);
+ }
+
+ public ExtendedCodeFormatter(DefaultCodeFormatterOptions options) {
+ super(options);
+ }
+
+ public ExtendedCodeFormatter(Map options) {
+ super(options);
+ }
+
+ protected void addPreparator(Preparator preparator) {
+ this.preparators.add(preparator);
+ }
+
+ @Override
+ protected void tokenizeSource(int kind) {
+ if (useLegacyTokenize) {
+ legacyTokenizeSource(kind);
+ return;
+ }
+ try {
+ super.tokenizeSource(kind);
+ }
+ catch (NoSuchMethodError ex) {
+ useLegacyTokenize = true;
+ legacyTokenizeSource(kind);
+ }
+ }
+
+ private void legacyTokenizeSource(int kind) {
+ this.tokens.clear();
+ long sourceLevel = CompilerOptions.versionToJdkLevel(this.sourceLevel);
+ Scanner scanner = new Scanner(true, false, false, sourceLevel, null, null, false);
+ scanner.setSource(this.sourceArray);
+ scanner.fakeInModule = (kind & K_MODULE_INFO) != 0;
+ while (true) {
+ try {
+ int tokenType = scanner.getNextToken();
+ if (tokenType == TerminalTokens.TokenNameEOF) {
+ break;
+ }
+ Token token = Token.fromCurrent(scanner, tokenType);
+ this.tokens.add(token);
+ }
+ catch (InvalidInputException ex) {
+ Token token = Token.fromCurrent(scanner, TerminalTokens.TokenNameNotAToken);
+ this.tokens.add(token);
+ }
+ }
+ }
+
+ @Override
+ protected void prepareWraps(int kind) {
+ ASTNode astRoot = getField("astRoot", ASTNode.class);
+ TokenManager tokenManager = getField("tokenManager", TokenManager.class);
+ applyPreparators(Phase.PRE_WRAPPING, kind, astRoot, tokenManager);
+ super.prepareWraps(kind);
+ applyPreparators(Phase.POST_WRAPPING, kind, astRoot, tokenManager);
+ }
+
+ private void applyPreparators(Phase preWrapping, int kind, ASTNode astRoot, TokenManager tokenManager) {
+ this.preparators.stream()
+ .filter((preparator) -> preparator.getPhase() == preWrapping)
+ .forEach((preparator) -> preparator.apply(kind, tokenManager, astRoot));
+ }
+
+ @SuppressWarnings("unchecked")
+ private T getField(String name, Class type) {
+ try {
+ Field field = DefaultCodeFormatter.class.getDeclaredField(name);
+ field.setAccessible(true);
+ return (T) field.get(this);
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+}
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
new file mode 100644
index 00000000..bfd16b37
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/Preparator.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017-present 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 org.eclipse.jdt.internal.formatter;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+
+/**
+ * Strategy interface used by {@link ExtendedCodeFormatter} to allow additional code
+ * formatting before wrapping.
+ *
+ * @author Phillip Webb
+ */
+public interface Preparator {
+
+ default Phase getPhase() {
+ return Phase.POST_WRAPPING;
+ }
+
+ /**
+ * Apply the preparator.
+ * @param kind the format kind (see
+ * {@link CodeFormatter#format(int, String, org.eclipse.jface.text.IRegion[], int, String)}
+ * for details)
+ * @param tokenManager the token manager
+ * @param astRoot the AST root node
+ */
+ void apply(int kind, TokenManager tokenManager, ASTNode astRoot);
+
+ /**
+ * The phase where the {@link Preparator} should be applied.
+ */
+ enum Phase {
+
+ /**
+ * Apply the preparator before wrapping.
+ */
+ PRE_WRAPPING,
+
+ /**
+ * Apply the preparator after wrapping.
+ */
+ POST_WRAPPING
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
new file mode 100644
index 00000000..6878ca6f
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-jdt-jdk8/src/main/java/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -0,0 +1,1688 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2020 Mateusz Matela and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Mateusz Matela - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
+ * Mateusz Matela - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
+ *******************************************************************************/
+package org.eclipse.jdt.internal.formatter.linewrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
+import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.AssertStatement;
+import org.eclipse.jdt.core.dom.Assignment;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.ConditionalExpression;
+import org.eclipse.jdt.core.dom.ConstructorInvocation;
+import org.eclipse.jdt.core.dom.CreationReference;
+import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.EnhancedForStatement;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ExportsDirective;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ExpressionMethodReference;
+import org.eclipse.jdt.core.dom.FieldAccess;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ForStatement;
+import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.InfixExpression;
+import org.eclipse.jdt.core.dom.InfixExpression.Operator;
+import org.eclipse.jdt.core.dom.LambdaExpression;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.OpensDirective;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.ProvidesDirective;
+import org.eclipse.jdt.core.dom.QualifiedName;
+import org.eclipse.jdt.core.dom.RecordDeclaration;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperFieldAccess;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.SuperMethodReference;
+import org.eclipse.jdt.core.dom.SwitchExpression;
+import org.eclipse.jdt.core.dom.SwitchStatement;
+import org.eclipse.jdt.core.dom.ThisExpression;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.TypeMethodReference;
+import org.eclipse.jdt.core.dom.TypeParameter;
+import org.eclipse.jdt.core.dom.UnionType;
+import org.eclipse.jdt.core.dom.VariableDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jdt.core.dom.WhileStatement;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions.Alignment;
+import org.eclipse.jdt.internal.formatter.Token;
+import org.eclipse.jdt.internal.formatter.Token.WrapMode;
+import org.eclipse.jdt.internal.formatter.Token.WrapPolicy;
+import org.eclipse.jdt.internal.formatter.TokenManager;
+import org.eclipse.jdt.internal.formatter.TokenTraverser;
+import org.eclipse.jface.text.IRegion;
+
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOLON;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMA;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameDOT;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameEQUAL;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameIdentifier;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLBRACE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLESS;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLPAREN;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameOR;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameQUESTION;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRBRACE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRPAREN;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameSEMICOLON;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameenum;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameextends;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameimplements;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamenew;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamesuper;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethis;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethrows;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameto;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhile;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewith;
+
+public class WrapPreparator extends ASTVisitor {
+
+ // @formatter:off
+
+ /**
+ * Helper for common handling of all expressions that should be treated the same as
+ * {@link FieldAccess}
+ */
+ private static class FieldAccessAdapter {
+ final Expression accessExpression;
+
+ public FieldAccessAdapter(Expression expression) {
+ this.accessExpression = expression;
+ }
+
+ public static boolean isFieldAccess(ASTNode expr) {
+ return expr instanceof FieldAccess || expr instanceof QualifiedName || expr instanceof ThisExpression
+ || expr instanceof SuperFieldAccess;
+ }
+
+ public Expression getExpression() {
+ if (this.accessExpression instanceof FieldAccess) {
+ return ((FieldAccess) this.accessExpression).getExpression();
+ }
+ if (this.accessExpression instanceof QualifiedName) {
+ return ((QualifiedName) this.accessExpression).getQualifier();
+ }
+ if (this.accessExpression instanceof ThisExpression) {
+ return ((ThisExpression) this.accessExpression).getQualifier();
+ }
+ if (this.accessExpression instanceof SuperFieldAccess) {
+ return ((SuperFieldAccess) this.accessExpression).getQualifier();
+ }
+ throw new AssertionError();
+ }
+
+ public int getIdentifierIndex(TokenManager tm) {
+ if (this.accessExpression instanceof FieldAccess) {
+ return tm.firstIndexIn(((FieldAccess) this.accessExpression).getName(), TokenNameIdentifier);
+ }
+ if (this.accessExpression instanceof QualifiedName) {
+ return tm.firstIndexIn(((QualifiedName) this.accessExpression).getName(), TokenNameIdentifier);
+ }
+ if (this.accessExpression instanceof ThisExpression) {
+ return tm.lastIndexIn(this.accessExpression, TokenNamethis);
+ }
+ if (this.accessExpression instanceof SuperFieldAccess) {
+ return tm.lastIndexIn(this.accessExpression, TokenNamesuper);
+ }
+ throw new AssertionError();
+ }
+ }
+
+ private static final Map OPERATOR_PRECEDENCE;
+ private static final Map> OPERATOR_WRAPPING_OPTION;
+ private static final Map> OPERATOR_WRAP_BEFORE_OPTION;
+ static {
+ HashMap precedence = new HashMap<>();
+ HashMap> wrappingOption = new HashMap<>();
+ HashMap> wrapBeforeOption = new HashMap<>();
+ for (Operator op : Arrays.asList(Operator.TIMES, Operator.DIVIDE, Operator.REMAINDER)) {
+ precedence.put(op, 1);
+ wrappingOption.put(op, o -> o.alignment_for_multiplicative_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_multiplicative_operator);
+ }
+ for (Operator op : Arrays.asList(Operator.PLUS, Operator.MINUS)) {
+ precedence.put(op, 2);
+ wrappingOption.put(op, o -> o.alignment_for_additive_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_additive_operator);
+ }
+ for (Operator op : Arrays.asList(Operator.LEFT_SHIFT, Operator.RIGHT_SHIFT_SIGNED,
+ Operator.RIGHT_SHIFT_UNSIGNED)) {
+ precedence.put(op, 3);
+ wrappingOption.put(op, o -> o.alignment_for_shift_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_shift_operator);
+ }
+ for (Operator op : Arrays.asList(Operator.LESS, Operator.GREATER, Operator.LESS_EQUALS,
+ Operator.GREATER_EQUALS)) {
+ precedence.put(op, 4);
+ wrappingOption.put(op, o -> o.alignment_for_relational_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_relational_operator);
+ }
+ for (Operator op : Arrays.asList(Operator.EQUALS, Operator.NOT_EQUALS)) {
+ precedence.put(op, 5);
+ wrappingOption.put(op, o -> o.alignment_for_relational_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_relational_operator);
+ }
+
+ precedence.put(Operator.AND, 6);
+ precedence.put(Operator.XOR, 7);
+ precedence.put(Operator.OR, 8);
+ for (Operator op : Arrays.asList(Operator.AND, Operator.XOR, Operator.OR)) {
+ wrappingOption.put(op, o -> o.alignment_for_bitwise_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_bitwise_operator);
+ }
+
+ precedence.put(Operator.CONDITIONAL_AND, 9);
+ precedence.put(Operator.CONDITIONAL_OR, 10);
+ for (Operator op : Arrays.asList(Operator.CONDITIONAL_AND, Operator.CONDITIONAL_OR)) {
+ wrappingOption.put(op, o -> o.alignment_for_logical_operator);
+ wrapBeforeOption.put(op, o -> o.wrap_before_logical_operator);
+ }
+ // ternary and assignment operators not relevant to infix expressions
+
+ OPERATOR_PRECEDENCE = Collections.unmodifiableMap(precedence);
+ OPERATOR_WRAPPING_OPTION = Collections.unmodifiableMap(wrappingOption);
+ OPERATOR_WRAP_BEFORE_OPTION = Collections.unmodifiableMap(wrapBeforeOption);
+ }
+
+ /** Penalty multiplier for wraps that are preferred */
+ private final static float PREFERRED = 7f / 8;
+
+ final TokenManager tm;
+ final DefaultCodeFormatterOptions options;
+ final int kind;
+
+ final Aligner aligner;
+
+ /*
+ * temporary values used when calling {@link #handleWrap(int)} to avoid ArrayList
+ * initialization and long lists of parameters
+ */
+ private List wrapIndexes = new ArrayList<>();
+ /**
+ * Indexes for wraps that shouldn't happen but should be indented if cannot be removed
+ */
+ private List secondaryWrapIndexes = new ArrayList<>();
+ private List wrapPenalties = new ArrayList<>();
+ private int wrapParentIndex = -1;
+ private int wrapGroupEnd = -1;
+
+ private int currentDepth = 0;
+
+ public WrapPreparator(TokenManager tokenManager, DefaultCodeFormatterOptions options, int kind) {
+ this.tm = tokenManager;
+ this.options = options;
+ this.kind = kind;
+
+ this.aligner = new Aligner(this.tm, this.options);
+ }
+
+ @Override
+ public boolean preVisit2(ASTNode node) {
+ this.currentDepth++;
+
+ assert this.wrapIndexes.isEmpty() && this.secondaryWrapIndexes.isEmpty() && this.wrapPenalties.isEmpty();
+ assert this.wrapParentIndex == -1 && this.wrapGroupEnd == -1;
+
+ boolean isMalformed = (node.getFlags() & ASTNode.MALFORMED) != 0;
+ if (isMalformed) {
+ this.tm.addDisableFormatTokenPair(this.tm.firstTokenIn(node, -1), this.tm.lastTokenIn(node, -1));
+ }
+ return !isMalformed;
+ }
+
+ @Override
+ public void postVisit(ASTNode node) {
+ this.currentDepth--;
+ }
+
+ @Override
+ public boolean visit(PackageDeclaration node) {
+ handleAnnotations(node.annotations(), this.options.alignment_for_annotations_on_package);
+ return true;
+ }
+
+ @Override
+ public boolean visit(NormalAnnotation node) {
+ int lParen = this.tm.firstIndexAfter(node.getTypeName(), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_annotation);
+
+ handleArguments(node.values(), this.options.alignment_for_arguments_in_annotation);
+ return true;
+ }
+
+ @Override
+ public boolean visit(SingleMemberAnnotation node) {
+ int lParen = this.tm.firstIndexAfter(node.getTypeName(), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_annotation);
+ return true;
+ }
+
+ @Override
+ public boolean visit(TypeDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_type);
+
+ Type superclassType = node.getSuperclassType();
+ if (superclassType != null) {
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getName(), -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(superclassType, -1);
+ this.wrapIndexes.add(this.tm.firstIndexBefore(superclassType, TokenNameextends));
+ this.wrapIndexes.add(this.tm.firstIndexIn(superclassType, -1));
+ handleWrap(this.options.alignment_for_superclass_in_type_declaration, PREFERRED);
+ }
+
+ List superInterfaceTypes = node.superInterfaceTypes();
+ if (!superInterfaceTypes.isEmpty()) {
+ int implementsToken = node.isInterface() ? TokenNameextends : TokenNameimplements;
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getName(), -1);
+ this.wrapIndexes.add(this.tm.firstIndexBefore(superInterfaceTypes.get(0), implementsToken));
+ prepareElementsList(superInterfaceTypes, TokenNameCOMMA, -1);
+ handleWrap(this.options.alignment_for_superinterfaces_in_type_declaration, PREFERRED);
+ }
+
+ prepareElementsList(node.typeParameters(), TokenNameCOMMA, TokenNameLESS);
+ handleWrap(this.options.alignment_for_type_parameters);
+
+ this.aligner.handleAlign(node.bodyDeclarations());
+
+ return true;
+ }
+
+ @Override
+ public boolean visit(AnnotationTypeDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_type);
+ this.aligner.handleAlign(node.bodyDeclarations());
+ return true;
+ }
+
+ @Override
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_method);
+ return true;
+ }
+
+ @Override
+ public boolean visit(AnonymousClassDeclaration node) {
+ this.aligner.handleAlign(node.bodyDeclarations());
+ return true;
+ }
+
+ @Override
+ public boolean visit(RecordDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_type);
+
+ int lParen = this.tm.firstIndexAfter(node.getName(), TokenNameLPAREN);
+ List components = node.recordComponents();
+ int rParen = this.tm.firstIndexAfter(
+ components.isEmpty() ? node.getName() : components.get(components.size() - 1), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_record_declaration);
+
+ if (!components.isEmpty()) {
+ int wrappingOption = this.options.alignment_for_record_components;
+ this.wrapGroupEnd = this.tm.lastIndexIn(components.get(components.size() - 1), -1);
+ handleArguments(components, wrappingOption);
+ }
+
+ List superInterfaceTypes = node.superInterfaceTypes();
+ if (!superInterfaceTypes.isEmpty()) {
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getName(), -1);
+ this.wrapIndexes.add(this.tm.firstIndexBefore(superInterfaceTypes.get(0), TokenNameimplements));
+ prepareElementsList(superInterfaceTypes, TokenNameCOMMA, -1);
+ handleWrap(this.options.alignment_for_superinterfaces_in_record_declaration, PREFERRED);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(MethodDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_method);
+
+ if (!node.isCompactConstructor()) {
+ int lParen = this.tm.firstIndexAfter(node.getName(), TokenNameLPAREN);
+ int rParen = node.getBody() == null ? this.tm.lastIndexIn(node, TokenNameRPAREN)
+ : this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_declaration);
+ }
+
+ List parameters = node.parameters();
+ Type receiverType = node.getReceiverType();
+ if (!parameters.isEmpty() || receiverType != null) {
+ if (receiverType != null) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(receiverType, -1));
+ }
+ int wrappingOption = node.isConstructor() ? this.options.alignment_for_parameters_in_constructor_declaration
+ : this.options.alignment_for_parameters_in_method_declaration;
+ this.wrapGroupEnd = this.tm
+ .lastIndexIn(parameters.isEmpty() ? receiverType : parameters.get(parameters.size() - 1), -1);
+ handleArguments(parameters, wrappingOption);
+ }
+
+ List exceptionTypes = node.thrownExceptionTypes();
+ if (!exceptionTypes.isEmpty()) {
+ int wrappingOption = node.isConstructor()
+ ? this.options.alignment_for_throws_clause_in_constructor_declaration
+ : this.options.alignment_for_throws_clause_in_method_declaration;
+ if ((wrappingOption & Alignment.M_INDENT_ON_COLUMN) == 0) {
+ this.wrapParentIndex = this.tm.firstIndexAfter(node.getName(), TokenNameLPAREN);
+ }
+ prepareElementsList(exceptionTypes, TokenNameCOMMA, TokenNameRPAREN);
+ // instead of the first exception type, wrap the "throws" token
+ this.wrapIndexes.set(0, this.tm.firstIndexBefore(exceptionTypes.get(0), TokenNamethrows));
+ handleWrap(wrappingOption, 0.5f);
+ }
+
+ if (!node.isConstructor()) {
+ this.wrapParentIndex = this.tm.findFirstTokenInLine(this.tm.firstIndexIn(node.getName(), -1));
+ while (this.tm.get(this.wrapParentIndex).isComment()) {
+ this.wrapParentIndex++;
+ }
+ List typeParameters = node.typeParameters();
+ if (!typeParameters.isEmpty()) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(typeParameters.get(0), -1));
+ }
+ if (node.getReturnType2() != null) {
+ int returTypeIndex = this.tm.firstIndexIn(node.getReturnType2(), -1);
+ if (returTypeIndex != this.wrapParentIndex) {
+ this.wrapIndexes.add(returTypeIndex);
+ }
+ }
+ this.wrapIndexes.add(this.tm.firstIndexIn(node.getName(), -1));
+ this.wrapGroupEnd = this.tm.lastIndexIn(node.getName(), -1);
+ handleWrap(this.options.alignment_for_method_declaration);
+ }
+
+ prepareElementsList(node.typeParameters(), TokenNameCOMMA, TokenNameLESS);
+ handleWrap(this.options.alignment_for_type_parameters);
+
+ return true;
+ }
+
+ @Override
+ public boolean visit(EnumDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_type);
+
+ List enumConstants = node.enumConstants();
+ int constantsEnd = -1;
+ if (!enumConstants.isEmpty()) {
+ for (EnumConstantDeclaration constant : enumConstants) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(constant, -1));
+ }
+ this.wrapParentIndex = (this.options.alignment_for_enum_constants & Alignment.M_INDENT_ON_COLUMN) > 0
+ ? this.tm.firstIndexBefore(enumConstants.get(0), TokenNameLBRACE)
+ : this.tm.firstIndexIn(node, TokenNameenum);
+ this.wrapGroupEnd = constantsEnd = this.tm.lastIndexIn(enumConstants.get(enumConstants.size() - 1), -1);
+ handleWrap(this.options.alignment_for_enum_constants, node);
+ }
+
+ if (!this.options.join_wrapped_lines) {
+ // preserve a line break between the last comma and semicolon
+ int commaIndex = -1;
+ int i = constantsEnd > 0 ? constantsEnd : this.tm.firstIndexAfter(node.getName(), TokenNameLBRACE);
+ while (++i < this.tm.size()) {
+ Token t = this.tm.get(i);
+ if (t.isComment()) {
+ continue;
+ }
+ if (t.tokenType == TokenNameCOMMA) {
+ commaIndex = i;
+ continue;
+ }
+ if (t.tokenType == TokenNameSEMICOLON && commaIndex >= 0
+ && this.tm.countLineBreaksBetween(this.tm.get(commaIndex), t) == 1) {
+ t.setWrapPolicy(new WrapPolicy(WrapMode.WHERE_NECESSARY, commaIndex, 0));
+ }
+ break;
+ }
+ }
+
+ List superInterfaceTypes = node.superInterfaceTypes();
+ if (!superInterfaceTypes.isEmpty()) {
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getName(), -1);
+ this.wrapIndexes.add(this.tm.firstIndexBefore(superInterfaceTypes.get(0), TokenNameimplements));
+ prepareElementsList(superInterfaceTypes, TokenNameCOMMA, -1);
+ handleWrap(this.options.alignment_for_superinterfaces_in_enum_declaration, PREFERRED);
+ }
+
+ this.aligner.handleAlign(node.bodyDeclarations());
+
+ return true;
+ }
+
+ @Override
+ public boolean visit(EnumConstantDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_enum_constant);
+
+ int lParen = this.tm.firstIndexAfter(node.getName(), -1);
+ while (this.tm.get(lParen).isComment()) {
+ lParen++;
+ }
+ if (this.tm.get(lParen).tokenType == TokenNameLPAREN) {
+ int rParen = node.getAnonymousClassDeclaration() == null ? this.tm.lastIndexIn(node, TokenNameRPAREN)
+ : this.tm.firstIndexBefore(node.getAnonymousClassDeclaration(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_enum_constant_declaration);
+ }
+
+ handleArguments(node.arguments(), this.options.alignment_for_arguments_in_enum_constant);
+ AnonymousClassDeclaration anonymousClass = node.getAnonymousClassDeclaration();
+ if (anonymousClass != null) {
+ forceContinuousWrapping(anonymousClass, this.tm.firstIndexIn(node.getName(), -1));
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(Block node) {
+ this.aligner.handleAlign(node);
+ return true;
+ }
+
+ @Override
+ public boolean visit(MethodInvocation node) {
+ // Method patched based on
+ // https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/189391/4/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+ int lParen = this.tm.firstIndexAfter(node.getName(), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_invocation);
+
+ handleArguments(node.arguments(), this.options.alignment_for_arguments_in_method_invocation);
+ handleTypeArguments(node.typeArguments());
+
+ boolean isInvocationChainRoot = !(node.getParent() instanceof MethodInvocation)
+ || node.getLocationInParent() != MethodInvocation.EXPRESSION_PROPERTY;
+ if (isInvocationChainRoot) {
+ Expression expression = node;
+ MethodInvocation invocation = node;
+ while (expression instanceof MethodInvocation) {
+ invocation = (MethodInvocation) expression;
+ expression = invocation.getExpression();
+ if (expression != null) {
+ this.wrapIndexes.add(this.tm.firstIndexBefore(invocation.getName(), TokenNameDOT));
+ this.secondaryWrapIndexes.add(this.tm.firstIndexIn(invocation.getName(), TokenNameIdentifier));
+ }
+ }
+ Collections.reverse(this.wrapIndexes);
+ expression = (expression != null) ? expression : invocation;
+ this.wrapParentIndex = this.tm.lastIndexIn(expression, -1);
+ if ((this.options.alignment_for_selector_in_method_invocation & Alignment.M_INDENT_ON_COLUMN) == 0) {
+ this.wrapParentIndex = this.tm.firstIndexIn(expression, -1);
+ }
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+ handleWrap(this.options.alignment_for_selector_in_method_invocation);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(SuperMethodInvocation node) {
+ int lParen = this.tm.firstIndexAfter(node.getName(), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_invocation);
+
+ handleArguments(node.arguments(), this.options.alignment_for_arguments_in_method_invocation);
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(ClassInstanceCreation node) {
+ int lParen = this.tm.firstIndexAfter(node.getType(), TokenNameLPAREN);
+ int rParen = node.getAnonymousClassDeclaration() == null ? this.tm.lastIndexIn(node, TokenNameRPAREN)
+ : this.tm.firstIndexBefore(node.getAnonymousClassDeclaration(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_invocation);
+
+ AnonymousClassDeclaration anonymousClass = node.getAnonymousClassDeclaration();
+ if (anonymousClass != null) {
+ forceContinuousWrapping(anonymousClass, this.tm.firstIndexIn(node, TokenNamenew));
+ }
+
+ int wrappingOption = node.getExpression() != null
+ ? this.options.alignment_for_arguments_in_qualified_allocation_expression
+ : this.options.alignment_for_arguments_in_allocation_expression;
+ handleArguments(node.arguments(), wrappingOption);
+
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(ConstructorInvocation node) {
+ int lParen = node.arguments().isEmpty() ? this.tm.lastIndexIn(node, TokenNameLPAREN)
+ : this.tm.firstIndexBefore((ASTNode) node.arguments().get(0), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_invocation);
+
+ handleArguments(node.arguments(), this.options.alignment_for_arguments_in_explicit_constructor_call);
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(SuperConstructorInvocation node) {
+ int lParen = node.arguments().isEmpty() ? this.tm.lastIndexIn(node, TokenNameLPAREN)
+ : this.tm.firstIndexBefore((ASTNode) node.arguments().get(0), TokenNameLPAREN);
+ int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_method_invocation);
+
+ handleArguments(node.arguments(), this.options.alignment_for_arguments_in_explicit_constructor_call);
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(FieldAccess node) {
+ handleFieldAccess(node);
+ return true;
+ }
+
+ @Override
+ public boolean visit(QualifiedName node) {
+ handleFieldAccess(node);
+ return true;
+ }
+
+ @Override
+ public boolean visit(ThisExpression node) {
+ handleFieldAccess(node);
+ return true;
+ }
+
+ @Override
+ public boolean visit(SuperFieldAccess node) {
+ handleFieldAccess(node);
+ return true;
+ }
+
+ private void handleFieldAccess(Expression node) {
+ boolean isAccessChainRoot = !FieldAccessAdapter.isFieldAccess(node.getParent());
+ if (!isAccessChainRoot) {
+ return;
+ }
+
+ Expression expression = node;
+ FieldAccessAdapter access = null;
+ while (FieldAccessAdapter.isFieldAccess(expression)) {
+ access = new FieldAccessAdapter(expression);
+ int nameIndex = access.getIdentifierIndex(this.tm);
+ // find a dot preceding the name, may not be there
+ for (int i = nameIndex - 1; i > this.tm.firstIndexIn(node, -1); i--) {
+ Token t = this.tm.get(i);
+ if (t.tokenType == TokenNameDOT) {
+ this.wrapIndexes.add(i);
+ this.secondaryWrapIndexes.add(nameIndex);
+ }
+ if (!t.isComment() && t.tokenType != TokenNamesuper) {
+ break;
+ }
+ }
+ expression = access.getExpression();
+ }
+ Collections.reverse(this.wrapIndexes);
+ this.wrapParentIndex = this.tm.lastIndexIn(expression != null ? expression : access.accessExpression, -1);
+ boolean isFollowedByInvocation = node.getParent() instanceof MethodInvocation
+ && node.getLocationInParent() == MethodInvocation.EXPRESSION_PROPERTY;
+ this.wrapGroupEnd = isFollowedByInvocation ? this.tm.lastIndexIn(node.getParent(), -1)
+ : new FieldAccessAdapter(node).getIdentifierIndex(this.tm);
+ // TODO need configuration for this, now only handles line breaks that cannot be
+ // removed
+ handleWrap(Alignment.M_NO_ALIGNMENT);
+ }
+
+ @Override
+ public boolean visit(InfixExpression node) {
+ Integer operatorPrecedence = OPERATOR_PRECEDENCE.get(node.getOperator());
+ if (operatorPrecedence == null) {
+ return true;
+ }
+ ASTNode parent = node.getParent();
+ if ((parent instanceof InfixExpression) && samePrecedence(node, (InfixExpression) parent)) {
+ return true; // this node has been handled higher in the AST
+ }
+
+ int wrappingOption = OPERATOR_WRAPPING_OPTION.get(node.getOperator()).applyAsInt(this.options);
+ boolean wrapBeforeOperator = OPERATOR_WRAP_BEFORE_OPTION.get(node.getOperator()).test(this.options);
+ if (this.tm.isStringConcatenation(node)) {
+ wrappingOption = this.options.alignment_for_string_concatenation;
+ wrapBeforeOperator = this.options.wrap_before_string_concatenation;
+ }
+
+ findTokensToWrap(node, wrapBeforeOperator, 0);
+ this.wrapParentIndex = this.wrapIndexes.remove(0);
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+ if ((wrappingOption & Alignment.M_INDENT_ON_COLUMN) != 0 && this.wrapParentIndex > 0) {
+ this.wrapParentIndex--;
+ }
+ for (int i = this.wrapParentIndex; i >= 0; i--) {
+ if (!this.tm.get(i).isComment()) {
+ this.wrapParentIndex = i;
+ break;
+ }
+ }
+ handleWrap(wrappingOption, !wrapBeforeOperator, node);
+ return true;
+ }
+
+ private void findTokensToWrap(InfixExpression node, boolean wrapBeforeOperator, int depth) {
+ Expression left = node.getLeftOperand();
+ if (left instanceof InfixExpression && samePrecedence(node, (InfixExpression) left)) {
+ findTokensToWrap((InfixExpression) left, wrapBeforeOperator, depth + 1);
+ }
+ else if (this.wrapIndexes.isEmpty() // always add first operand, it will be taken
+ // as wrap parent
+ || !wrapBeforeOperator) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(left, -1));
+ }
+
+ Expression right = node.getRightOperand();
+ List extended = node.extendedOperands();
+ for (int i = -1; i < extended.size(); i++) {
+ Expression operand = (i == -1) ? right : extended.get(i);
+ if (operand instanceof InfixExpression && samePrecedence(node, (InfixExpression) operand)) {
+ findTokensToWrap((InfixExpression) operand, wrapBeforeOperator, depth + 1);
+ }
+ int indexBefore = this.tm.firstIndexBefore(operand, -1);
+ while (this.tm.get(indexBefore).isComment()) {
+ indexBefore--;
+ }
+ assert node.getOperator().toString().equals(this.tm.toString(indexBefore));
+ int indexAfter = this.tm.firstIndexIn(operand, -1);
+ this.wrapIndexes.add(wrapBeforeOperator ? indexBefore : indexAfter);
+ this.secondaryWrapIndexes.add(wrapBeforeOperator ? indexAfter : indexBefore);
+
+ if (!this.options.join_wrapped_lines) {
+ // TODO there should be an option for never joining wraps on opposite side
+ // of the operator
+ if (wrapBeforeOperator) {
+ if (this.tm.countLineBreaksBetween(this.tm.get(indexAfter - 1), this.tm.get(indexAfter)) > 0) {
+ this.wrapIndexes.add(indexAfter);
+ }
+ }
+ else {
+ if (this.tm.countLineBreaksBetween(this.tm.get(indexBefore), this.tm.get(indexBefore - 1)) > 0) {
+ this.wrapIndexes.add(indexBefore);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean samePrecedence(InfixExpression expression1, InfixExpression expression2) {
+ Integer precedence1 = OPERATOR_PRECEDENCE.get(expression1.getOperator());
+ Integer precedence2 = OPERATOR_PRECEDENCE.get(expression2.getOperator());
+ if (precedence1 == null || precedence2 == null) {
+ return false;
+ }
+ return precedence1.equals(precedence2);
+ }
+
+ @Override
+ public boolean visit(ConditionalExpression node) {
+ boolean chainsMatter = (this.options.alignment_for_conditional_expression_chain
+ & Alignment.SPLIT_MASK) != Alignment.M_NO_ALIGNMENT;
+ boolean isNextInChain = node.getParent() instanceof ConditionalExpression
+ && node == ((ConditionalExpression) node.getParent()).getElseExpression();
+ boolean isFirstInChain = node.getElseExpression() instanceof ConditionalExpression && !isNextInChain;
+ boolean wrapBefore = this.options.wrap_before_conditional_operator;
+ List before = wrapBefore ? this.wrapIndexes : this.secondaryWrapIndexes;
+ List after = wrapBefore ? this.secondaryWrapIndexes : this.wrapIndexes;
+ if (!chainsMatter || (!isFirstInChain && !isNextInChain)) {
+ before.add(this.tm.firstIndexAfter(node.getExpression(), TokenNameQUESTION));
+ before.add(this.tm.firstIndexAfter(node.getThenExpression(), TokenNameCOLON));
+ after.add(this.tm.firstIndexIn(node.getThenExpression(), -1));
+ after.add(this.tm.firstIndexIn(node.getElseExpression(), -1));
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getExpression(), -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+ handleWrap(this.options.alignment_for_conditional_expression);
+
+ }
+ else if (isFirstInChain) {
+ List chain = new ArrayList<>();
+ chain.add(node);
+ ConditionalExpression next = node;
+ while (next.getElseExpression() instanceof ConditionalExpression) {
+ next = (ConditionalExpression) next.getElseExpression();
+ chain.add(next);
+ }
+
+ for (ConditionalExpression conditional : chain) {
+ before.add(this.tm.firstIndexAfter(conditional.getThenExpression(), TokenNameCOLON));
+ after.add(this.tm.firstIndexIn(conditional.getElseExpression(), -1));
+ }
+ this.wrapParentIndex = this.tm.firstIndexIn(node.getExpression(), -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+ handleWrap(this.options.alignment_for_conditional_expression_chain);
+
+ this.currentDepth++;
+ for (ConditionalExpression conditional : chain) {
+ before.add(this.tm.firstIndexAfter(conditional.getExpression(), TokenNameQUESTION));
+ after.add(this.tm.firstIndexIn(conditional.getThenExpression(), -1));
+ this.wrapParentIndex = this.tm.firstIndexIn(conditional.getExpression(), -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(conditional.getThenExpression(), -1);
+ handleWrap(this.options.alignment_for_conditional_expression);
+ }
+ this.currentDepth--;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(ArrayInitializer node) {
+ List expressions = node.expressions();
+ if (!expressions.isEmpty()) {
+ prepareElementsList(expressions, TokenNameCOMMA, TokenNameLBRACE);
+ handleWrap(this.options.alignment_for_expressions_in_array_initializer, node);
+ }
+ int openingBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
+ Token openingBrace = this.tm.get(openingBraceIndex);
+ if (openingBrace.isNextLineOnWrap() && openingBrace.getWrapPolicy() == null && openingBraceIndex > 0) {
+ // add fake wrap policy to make sure the brace indentation is right
+ openingBrace.setWrapPolicy(new WrapPolicy(WrapMode.DISABLED, openingBraceIndex - 1, 0));
+ }
+ if (!this.options.join_wrapped_lines
+ && !this.options.insert_new_line_before_closing_brace_in_array_initializer) {
+ // if there is a line break before the closing brace, formatter should treat
+ // it as a valid wrap to preserve
+ int closingBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
+ Token closingBrace = this.tm.get(closingBraceIndex);
+ if (this.tm.countLineBreaksBetween(this.tm.get(closingBraceIndex - 1), closingBrace) == 1) {
+ closingBrace.setWrapPolicy(new WrapPolicy(WrapMode.WHERE_NECESSARY, openingBraceIndex,
+ closingBraceIndex, 0, this.currentDepth, 1, true, false));
+ }
+ }
+ if (this.options.brace_position_for_array_initializer.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)
+ && openingBrace.getWrapPolicy() == null && (node.getParent() instanceof SingleMemberAnnotation
+ || node.getParent() instanceof MemberValuePair)) {
+ int parentIndex = this.tm.firstIndexIn(node.getParent(), -1);
+ int indent = this.options.indentation_size;
+ openingBrace.setWrapPolicy(new WrapPolicy(WrapMode.BLOCK_INDENT, parentIndex, indent));
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(Assignment node) {
+ int rightSideIndex = this.tm.firstIndexIn(node.getRightHandSide(), -1);
+ if (this.tm.get(rightSideIndex).getLineBreaksBefore() > 0) {
+ return true; // must be an array initializer in new line because of
+ // brace_position_for_array_initializer
+ }
+
+ int operatorIndex = this.tm.firstIndexBefore(node.getRightHandSide(), -1);
+ while (this.tm.get(operatorIndex).isComment()) {
+ operatorIndex--;
+ }
+ assert node.getOperator().toString().equals(this.tm.toString(operatorIndex));
+
+ this.wrapIndexes.add(this.options.wrap_before_assignment_operator ? operatorIndex : rightSideIndex);
+ this.secondaryWrapIndexes.add(this.options.wrap_before_assignment_operator ? rightSideIndex : operatorIndex);
+ this.wrapParentIndex = operatorIndex - 1;
+ this.wrapGroupEnd = this.tm.lastIndexIn(node.getRightHandSide(), -1);
+ handleWrap(this.options.alignment_for_assignment);
+ return true;
+ }
+
+ @Override
+ public boolean visit(VariableDeclarationFragment node) {
+ if (node.getInitializer() == null) {
+ return true;
+ }
+ int rightSideIndex = this.tm.firstIndexIn(node.getInitializer(), -1);
+ if (this.tm.get(rightSideIndex).getLineBreaksBefore() > 0) {
+ return true; // must be an array initializer in new line because of
+ // brace_position_for_array_initializer
+ }
+ int equalIndex = this.tm.firstIndexBefore(node.getInitializer(), TokenNameEQUAL);
+
+ this.wrapIndexes.add(this.options.wrap_before_assignment_operator ? equalIndex : rightSideIndex);
+ this.secondaryWrapIndexes.add(this.options.wrap_before_assignment_operator ? rightSideIndex : equalIndex);
+ this.wrapParentIndex = equalIndex - 1;
+ this.wrapGroupEnd = this.tm.lastIndexIn(node.getInitializer(), -1);
+ handleWrap(this.options.alignment_for_assignment);
+ return true;
+ }
+
+ @Override
+ public boolean visit(IfStatement node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_if_while_statement);
+
+ Statement elseStatement = node.getElseStatement();
+ boolean keepThenOnSameLine = this.options.keep_then_statement_on_same_line
+ || (this.options.keep_simple_if_on_one_line && elseStatement == null);
+ if (keepThenOnSameLine) {
+ handleSimpleLoop(node.getThenStatement(), this.options.alignment_for_compact_if);
+ }
+
+ if (this.options.keep_else_statement_on_same_line && elseStatement != null) {
+ handleSimpleLoop(elseStatement, this.options.alignment_for_compact_if);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(ForStatement node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_for_statement);
+
+ List initializers = node.initializers();
+ if (!initializers.isEmpty()) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(initializers.get(0), -1));
+ }
+ if (node.getExpression() != null) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(node.getExpression(), -1));
+ }
+ List updaters = node.updaters();
+ if (!updaters.isEmpty()) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(updaters.get(0), -1));
+ }
+ if (!this.wrapIndexes.isEmpty()) {
+ this.wrapParentIndex = lParen;
+ this.wrapGroupEnd = rParen;
+ handleWrap(this.options.alignment_for_expressions_in_for_loop_header);
+ }
+ if (this.options.keep_simple_for_body_on_same_line) {
+ handleSimpleLoop(node.getBody(), this.options.alignment_for_compact_loop);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(EnhancedForStatement node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_for_statement);
+
+ if (this.options.keep_simple_for_body_on_same_line) {
+ handleSimpleLoop(node.getBody(), this.options.alignment_for_compact_loop);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(WhileStatement node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_if_while_statement);
+
+ if (this.options.keep_simple_while_body_on_same_line) {
+ handleSimpleLoop(node.getBody(), this.options.alignment_for_compact_loop);
+ }
+ return true;
+ }
+
+ private void handleSimpleLoop(Statement body, int wrappingOption) {
+ if (!(body instanceof Block)) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(body, -1));
+ this.wrapParentIndex = this.tm.firstIndexBefore(body, TokenNameRPAREN);
+ this.wrapGroupEnd = this.tm.lastIndexIn(body, -1);
+ handleWrap(wrappingOption, body.getParent());
+
+ body.accept(new ASTVisitor() {
+ @Override
+ public boolean visit(Block node) {
+ forceContinuousWrapping(node, WrapPreparator.this.tm.firstIndexIn(node, -1));
+ return false;
+ }
+ });
+ }
+ }
+
+ @Override
+ public void endVisit(DoStatement node) {
+ if (this.options.keep_simple_do_while_body_on_same_line && !(node.getBody() instanceof Block)) {
+ int whileIndex = this.tm.firstIndexAfter(node.getBody(), TokenNamewhile);
+ this.wrapIndexes.add(whileIndex);
+ this.wrapParentIndex = this.tm.lastIndexIn(node.getBody(), -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+
+ int alignment = this.options.alignment_for_compact_loop;
+ for (int i = this.tm.firstIndexIn(node, -1) + 1; i < whileIndex; i++) {
+ Token token = this.tm.get(i);
+ if (token.getLineBreaksBefore() > 0 || token.getLineBreaksAfter() > 0) {
+ alignment |= Alignment.M_FORCE;
+ }
+ }
+ handleWrap(alignment, node);
+ }
+ }
+
+ @Override
+ public boolean visit(TryStatement node) {
+ if (!node.resources().isEmpty()) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_try_clause);
+ }
+ prepareElementsList(node.resources(), TokenNameSEMICOLON, TokenNameLPAREN);
+ handleWrap(this.options.alignment_for_resources_in_try);
+ return true;
+ }
+
+ @Override
+ public boolean visit(UnionType node) {
+ List types = node.types();
+ if (types.isEmpty()) {
+ return true;
+ }
+ if (this.options.wrap_before_or_operator_multicatch) {
+ for (Type type : types) {
+ if (this.wrapIndexes.isEmpty()) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(type, -1));
+ }
+ else {
+ this.wrapIndexes.add(this.tm.firstIndexBefore(type, TokenNameOR));
+ this.secondaryWrapIndexes.add(this.tm.firstIndexIn(type, -1));
+ }
+ }
+ this.wrapParentIndex = this.tm.firstIndexBefore(node, -1);
+ while (this.tm.get(this.wrapParentIndex).isComment()) {
+ this.wrapParentIndex--;
+ }
+ this.wrapGroupEnd = this.tm.lastIndexIn(types.get(types.size() - 1), -1);
+ handleWrap(this.options.alignment_for_union_type_in_multicatch);
+ }
+ else {
+ prepareElementsList(types, TokenNameOR, TokenNameLPAREN);
+ handleWrap(this.options.alignment_for_union_type_in_multicatch);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(LambdaExpression node) {
+ int lParen = this.tm.firstIndexIn(node, -1);
+ if (this.tm.get(lParen).tokenType == TokenNameLPAREN) {
+ int rParen = this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_lambda_declaration);
+ }
+ if (node.getBody() instanceof Block) {
+ forceContinuousWrapping(node.getBody(), this.tm.firstIndexIn(node, -1));
+
+ List statements = ((Block) node.getBody()).statements();
+ if (!statements.isEmpty()) {
+ int openBraceIndex = this.tm.firstIndexBefore(statements.get(0), TokenNameLBRACE);
+ int closeBraceIndex = this.tm.firstIndexAfter(statements.get(statements.size() - 1), TokenNameRBRACE);
+ boolean areKeptOnOneLine = this.tm.stream().skip(openBraceIndex + 1)
+ .limit(closeBraceIndex - openBraceIndex - 1)
+ .allMatch(t -> t.getLineBreaksBefore() == 0 && t.getLineBreaksAfter() == 0);
+ if (areKeptOnOneLine) {
+ for (Statement statement : statements) {
+ this.wrapIndexes.add(this.tm.firstIndexIn(statement, -1));
+ }
+ this.wrapParentIndex = openBraceIndex;
+ this.wrapGroupEnd = closeBraceIndex;
+ handleWrap(Alignment.M_ONE_PER_LINE_SPLIT, node);
+ this.tm.get(closeBraceIndex).setWrapPolicy(new WrapPolicy(WrapMode.TOP_PRIORITY, openBraceIndex,
+ closeBraceIndex, 0, this.currentDepth, 1, false, false));
+ }
+ }
+ }
+ if (node.hasParentheses()) {
+ List parameters = node.parameters();
+ // the legacy formatter didn't like wrapping lambda parameters, so neither do
+ // we
+ this.currentDepth++;
+ handleArguments(parameters, this.options.alignment_for_parameters_in_method_declaration);
+ this.currentDepth--;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visit(FieldDeclaration node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_field);
+ handleVariableDeclarations(node.fragments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(VariableDeclarationStatement node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_local_variable);
+ handleVariableDeclarations(node.fragments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(VariableDeclarationExpression node) {
+ handleAnnotations(node.modifiers(), this.options.alignment_for_annotations_on_local_variable);
+ handleVariableDeclarations(node.fragments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(SingleVariableDeclaration node) {
+ handleAnnotations(node.modifiers(),
+ node.getParent() instanceof EnhancedForStatement
+ ? this.options.alignment_for_annotations_on_local_variable
+ : this.options.alignment_for_annotations_on_parameter);
+ return true;
+ }
+
+ @Override
+ public boolean visit(ParameterizedType node) {
+ prepareElementsList(node.typeArguments(), TokenNameCOMMA, TokenNameLESS);
+ handleWrap(this.options.alignment_for_parameterized_type_references);
+ return true;
+ }
+
+ @Override
+ public boolean visit(TypeMethodReference node) {
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(ExpressionMethodReference node) {
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(SuperMethodReference node) {
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ @Override
+ public boolean visit(CreationReference node) {
+ handleTypeArguments(node.typeArguments());
+ return true;
+ }
+
+ private void handleTypeArguments(List typeArguments) {
+ if (typeArguments.isEmpty()) {
+ return;
+ }
+ prepareElementsList(typeArguments, TokenNameCOMMA, TokenNameLESS);
+ handleWrap(this.options.alignment_for_type_arguments);
+ }
+
+ @Override
+ public boolean visit(ExportsDirective node) {
+ handleModuleStatement(node.modules(), TokenNameto);
+ return true;
+ }
+
+ @Override
+ public boolean visit(OpensDirective node) {
+ handleModuleStatement(node.modules(), TokenNameto);
+ return true;
+ }
+
+ @Override
+ public boolean visit(ProvidesDirective node) {
+ handleModuleStatement(node.implementations(), TokenNamewith);
+ return true;
+ }
+
+ private void handleModuleStatement(List names, int joiningTokenType) {
+ if (names.isEmpty()) {
+ return;
+ }
+ int joiningTokenIndex = this.tm.firstIndexBefore(names.get(0), joiningTokenType);
+ this.wrapParentIndex = this.tm.firstIndexBefore(names.get(0), TokenNameIdentifier);
+ this.wrapIndexes.add(joiningTokenIndex);
+ prepareElementsList(names, TokenNameCOMMA, -1);
+ handleWrap(this.options.alignment_for_module_statements, PREFERRED);
+ }
+
+ @Override
+ public boolean visit(CatchClause node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexBefore(node.getBody(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_catch_clause);
+ return true;
+ }
+
+ @Override
+ public boolean visit(SwitchStatement node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_switch_statement);
+ return true;
+ }
+
+ @Override
+ public boolean visit(SwitchExpression node) {
+ int lParen = this.tm.firstIndexIn(node, TokenNameLPAREN);
+ int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_switch_statement);
+ return true;
+ }
+
+ @Override
+ public boolean visit(DoStatement node) {
+ int lParen = this.tm.firstIndexBefore(node.getExpression(), TokenNameLPAREN);
+ int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN);
+ handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_if_while_statement);
+ return true;
+ }
+
+ @Override
+ public boolean visit(AssertStatement node) {
+ Expression message = node.getMessage();
+ if (message != null) {
+ int atColon = this.tm.firstIndexBefore(message, TokenNameCOLON);
+ int afterColon = this.tm.firstIndexIn(message, -1);
+ if (this.options.wrap_before_assertion_message_operator) {
+ this.wrapIndexes.add(atColon);
+ this.secondaryWrapIndexes.add(afterColon);
+ }
+ else {
+ this.wrapIndexes.add(afterColon);
+ this.secondaryWrapIndexes.add(atColon);
+ }
+ this.wrapParentIndex = this.tm.firstIndexIn(node, -1);
+ this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
+ handleWrap(this.options.alignment_for_assertion_message);
+ }
+ return true;
+ }
+
+ /**
+ * Makes sure all new lines within given node will have wrap policy so that wrap
+ * executor will fix their indentation if necessary.
+ */
+ void forceContinuousWrapping(ASTNode node, int parentIndex) {
+ int parentIndent = this.tm.get(parentIndex).getIndent();
+ int indentChange = -parentIndent;
+ int lineStart = this.tm.findFirstTokenInLine(parentIndex);
+ for (int i = parentIndex; i >= lineStart; i--) {
+ int align = this.tm.get(i).getAlign();
+ if (align > 0) {
+ indentChange = -2 * parentIndent + align;
+ break;
+ }
+ }
+
+ Token previous = null;
+ int from = this.tm.firstIndexIn(node, -1);
+ int to = this.tm.lastIndexIn(node, -1);
+ for (int i = from; i <= to; i++) {
+ Token token = this.tm.get(i);
+ if ((token.getLineBreaksBefore() > 0 || (previous != null && previous.getLineBreaksAfter() > 0))
+ && (token.getWrapPolicy() == null || token.getWrapPolicy().wrapMode == WrapMode.BLOCK_INDENT)) {
+ int extraIndent = token.getIndent() + indentChange;
+ token.setWrapPolicy(new WrapPolicy(WrapMode.BLOCK_INDENT, parentIndex, extraIndent));
+ token.setIndent(parentIndent + extraIndent);
+ }
+ previous = token;
+ }
+ }
+
+ private void handleVariableDeclarations(List fragments) {
+ if (fragments.size() > 1) {
+ this.wrapParentIndex = this.tm.firstIndexIn(fragments.get(0), -1);
+ prepareElementsList(fragments, TokenNameCOMMA, -1);
+ this.wrapIndexes.remove(0);
+ handleWrap(this.options.alignment_for_multiple_fields);
+ }
+ }
+
+ private void handleArguments(List extends ASTNode> arguments, int wrappingOption) {
+ this.wrapPenalties.add(1 / PREFERRED);
+ prepareElementsList(arguments, TokenNameCOMMA, TokenNameLPAREN);
+ handleWrap(wrappingOption);
+ }
+
+ private void handleAnnotations(List extends IExtendedModifier> modifiers, int wrappingOption) {
+ Annotation last = null;
+ int i;
+ for (i = 0; i < modifiers.size(); i++) {
+ if (modifiers.get(i).isModifier()) {
+ break;
+ }
+ Annotation annotation = (Annotation) modifiers.get(i);
+ if (i == 0) {
+ this.wrapParentIndex = this.tm.firstIndexIn(annotation, -1);
+ }
+ else {
+ this.wrapIndexes.add(this.tm.firstIndexIn(annotation, -1));
+ this.wrapGroupEnd = this.tm.lastIndexIn(annotation, -1);
+ }
+ last = annotation;
+ }
+ handleWrap(wrappingOption, last);
+
+ if (i < modifiers.size()) {
+ // any annotations following other modifiers will be associated with
+ // declaration type
+ handleAnnotations(modifiers.subList(i + 1, modifiers.size()), this.options.alignment_for_type_annotations);
+ }
+ }
+
+ private void prepareElementsList(List extends ASTNode> elements, int separatorType, int wrapParentType) {
+ for (int i = 0; i < elements.size(); i++) {
+ ASTNode element = elements.get(i);
+ this.wrapIndexes.add(this.tm.firstIndexIn(element, -1));
+ if (i > 0) {
+ this.secondaryWrapIndexes.add(this.tm.firstIndexBefore(element, separatorType));
+ }
+ }
+ // wrapIndexes may have been filled with additional values even if arguments is
+ // empty
+ if (!this.wrapIndexes.isEmpty()) {
+ Token firstToken = this.tm.get(this.wrapIndexes.get(0));
+ if (this.wrapParentIndex < 0) {
+ this.wrapParentIndex = this.tm.findIndex(firstToken.originalStart - 1, wrapParentType, false);
+ }
+ if (!elements.isEmpty() && this.wrapGroupEnd < 0) {
+ this.wrapGroupEnd = this.tm.lastIndexIn(elements.get(elements.size() - 1), -1);
+ }
+ }
+ }
+
+ private void handleWrap(int wrappingOption) {
+ handleWrap(wrappingOption, null);
+ }
+
+ private void handleWrap(int wrappingOption, float firstPenaltyMultiplier) {
+ this.wrapPenalties.add(firstPenaltyMultiplier);
+ handleWrap(wrappingOption, null);
+ }
+
+ private void handleWrap(int wrappingOption, ASTNode parentNode) {
+ handleWrap(wrappingOption, true, parentNode);
+ }
+
+ private void handleWrap(int wrappingOption, boolean wrapPreceedingComments, ASTNode parentNode) {
+ doHandleWrap(wrappingOption, wrapPreceedingComments, parentNode);
+ this.wrapIndexes.clear();
+ this.secondaryWrapIndexes.clear();
+ this.wrapPenalties.clear();
+ this.wrapParentIndex = this.wrapGroupEnd = -1;
+ }
+
+ private void doHandleWrap(int wrappingOption, boolean wrapPreceedingComments, ASTNode parentNode) {
+ if (this.wrapIndexes.isEmpty()) {
+ return;
+ }
+ assert this.wrapParentIndex >= 0 && this.wrapParentIndex < this.wrapIndexes.get(0);
+ assert this.wrapGroupEnd >= this.wrapIndexes.get(this.wrapIndexes.size() - 1);
+
+ while (this.tm.get(this.wrapParentIndex).isComment() && this.wrapParentIndex > 0) {
+ this.wrapParentIndex--;
+ }
+
+ float penalty = this.wrapPenalties.isEmpty() ? 1 : this.wrapPenalties.get(0);
+ WrapPolicy policy = getWrapPolicy(wrappingOption, penalty, true, parentNode);
+
+ WrapPolicy existing = this.tm.get(this.wrapIndexes.get(0)).getWrapPolicy();
+ if (existing != null && existing.wrapMode == WrapMode.TOP_PRIORITY) {
+ // SEPARATE_LINES_IF_WRAPPED
+ assert existing.wrapParentIndex == this.wrapParentIndex;
+ this.wrapGroupEnd = existing.groupEndIndex;
+ policy = new WrapPolicy(WrapMode.TOP_PRIORITY, policy.wrapParentIndex, this.wrapGroupEnd,
+ policy.extraIndent, policy.structureDepth, policy.penaltyMultiplier, true, policy.indentOnColumn);
+ }
+
+ setTokenWrapPolicy(0, policy, true);
+
+ for (int i = 1; i < this.wrapIndexes.size(); i++) {
+ penalty = this.wrapPenalties.size() > i ? this.wrapPenalties.get(i) : 1;
+ if (penalty != policy.penaltyMultiplier || i == 1) {
+ policy = getWrapPolicy(wrappingOption, penalty, false, parentNode);
+ }
+ setTokenWrapPolicy(i, policy, wrapPreceedingComments);
+ }
+
+ if (!this.secondaryWrapIndexes.isEmpty()) {
+ int optionNoAlignment = (wrappingOption & ~Alignment.SPLIT_MASK) | Alignment.M_NO_ALIGNMENT;
+ policy = getWrapPolicy(optionNoAlignment, 1, false, parentNode);
+ for (int index : this.secondaryWrapIndexes) {
+ Token token = this.tm.get(index);
+ if (token.getWrapPolicy() == null) {
+ token.setWrapPolicy(policy);
+ }
+ }
+ }
+ }
+
+ private void setTokenWrapPolicy(int wrapIndexesIndex, WrapPolicy policy, boolean wrapPreceedingComments) {
+ int index = this.wrapIndexes.get(wrapIndexesIndex);
+ if (wrapPreceedingComments) {
+ for (int i = index - 1; i >= 0; i--) {
+ Token previous = this.tm.get(i);
+ if (!previous.isComment()) {
+ break;
+ }
+ if (previous.getWrapPolicy() == WrapPolicy.FORCE_FIRST_COLUMN) {
+ break;
+ }
+ if (previous.getLineBreaksAfter() == 0 && i == index - 1) {
+ index = i;
+ }
+ if (previous.getLineBreaksBefore() > 0) {
+ previous.setWrapPolicy(policy);
+ }
+ }
+ this.wrapIndexes.set(wrapIndexesIndex, index);
+ }
+
+ Token token = this.tm.get(index);
+ if (token.getWrapPolicy() == WrapPolicy.DISABLE_WRAP) {
+ return;
+ }
+
+ token.setWrapPolicy(policy);
+ if (policy.wrapMode == WrapMode.FORCE) {
+ token.breakBefore();
+ }
+ else if (this.options.join_wrapped_lines && token.tokenType == TokenNameCOMMENT_BLOCK) {
+ // allow wrap preparator to decide if this comment should be wrapped
+ token.clearLineBreaksBefore();
+ }
+ }
+
+ private WrapPolicy getWrapPolicy(int wrappingOption, float penaltyMultiplier, boolean isFirst, ASTNode parentNode) {
+ assert this.wrapParentIndex >= 0 && this.wrapGroupEnd >= 0;
+ int extraIndent = this.options.continuation_indentation;
+ boolean indentOnColumn = (wrappingOption & Alignment.M_INDENT_ON_COLUMN) != 0;
+ boolean isForceWrap = (wrappingOption & Alignment.M_FORCE) != 0;
+ boolean isAlreadyWrapped = false;
+ if (indentOnColumn) {
+ extraIndent = 0;
+ }
+ else if (parentNode instanceof Annotation) {
+ extraIndent = 0;
+ }
+ else if (parentNode instanceof EnumDeclaration) {
+ // special behavior for compatibility with legacy formatter
+ extraIndent = ((wrappingOption & Alignment.M_INDENT_BY_ONE) != 0) ? 2 : 1;
+ if (!this.options.indent_body_declarations_compare_to_enum_declaration_header) {
+ extraIndent--;
+ }
+ isAlreadyWrapped = isFirst;
+ }
+ else if (parentNode instanceof IfStatement || parentNode instanceof ForStatement
+ || parentNode instanceof EnhancedForStatement || parentNode instanceof WhileStatement) {
+ extraIndent = 1;
+ this.wrapParentIndex = this.tm.firstIndexIn(parentNode, -1); // only if
+ // !indoentOnColumn
+ }
+ else if (parentNode instanceof DoStatement) {
+ extraIndent = 0;
+ this.wrapParentIndex = this.tm.firstIndexIn(parentNode, -1); // only if
+ // !indoentOnColumn
+ }
+ else if (parentNode instanceof LambdaExpression) {
+ extraIndent = 1;
+ }
+ else if ((wrappingOption & Alignment.M_INDENT_BY_ONE) != 0) {
+ extraIndent = 1;
+ }
+ else if (parentNode instanceof ArrayInitializer) {
+ extraIndent = this.options.continuation_indentation_for_array_initializer;
+ isAlreadyWrapped = isFirst && this.options.insert_new_line_after_opening_brace_in_array_initializer;
+ }
+
+ WrapMode wrapMode = WrapMode.WHERE_NECESSARY;
+ boolean isTopPriority = false;
+ switch (wrappingOption & Alignment.SPLIT_MASK) {
+ case Alignment.M_NO_ALIGNMENT:
+ wrapMode = WrapMode.DISABLED;
+ isForceWrap = false;
+ break;
+ case Alignment.M_COMPACT_FIRST_BREAK_SPLIT:
+ isTopPriority = isFirst;
+ isForceWrap &= isFirst;
+ break;
+ case Alignment.M_ONE_PER_LINE_SPLIT:
+ isTopPriority = true;
+ break;
+ case Alignment.M_NEXT_SHIFTED_SPLIT:
+ isTopPriority = true;
+ if (!isFirst) {
+ extraIndent++;
+ }
+ break;
+ case Alignment.M_NEXT_PER_LINE_SPLIT:
+ isTopPriority = !isFirst;
+ isForceWrap &= !isFirst;
+ break;
+ }
+
+ if (isForceWrap) {
+ wrapMode = WrapMode.FORCE;
+ }
+ else if (isAlreadyWrapped) {
+ wrapMode = WrapMode.DISABLED; // to avoid triggering top priority wrapping
+ }
+ else if (isTopPriority) {
+ wrapMode = WrapMode.TOP_PRIORITY;
+ }
+ extraIndent *= this.options.indentation_size;
+ return new WrapPolicy(wrapMode, this.wrapParentIndex, this.wrapGroupEnd, extraIndent, this.currentDepth,
+ penaltyMultiplier, isFirst, indentOnColumn);
+ }
+
+ public void finishUp(ASTNode astRoot, List regions) {
+ preserveExistingLineBreaks();
+ applyBreaksOutsideRegions(regions);
+ new WrapExecutor(this.tm, this.options, regions).executeWraps();
+ this.aligner.alignComments();
+ wrapComments();
+ fixEnumConstantIndents(astRoot);
+ }
+
+ private void preserveExistingLineBreaks() {
+ // normally n empty lines = n+1 line breaks, but not at the file start and end
+ Token first = this.tm.get(0);
+ int startingBreaks = first.getLineBreaksBefore();
+ first.clearLineBreaksBefore();
+ first.putLineBreaksBefore(startingBreaks - 1);
+
+ this.tm.traverse(0, new TokenTraverser() {
+ boolean join_wrapped_lines = WrapPreparator.this.options.join_wrapped_lines;
+
+ @Override
+ protected boolean token(Token token, int index) {
+ int lineBreaks = getLineBreaksToPreserve(getPrevious(), token);
+ if (lineBreaks > 1 || (!this.join_wrapped_lines && token.isWrappable()) || index == 0) {
+ token.putLineBreaksBefore(lineBreaks);
+ }
+ return true;
+ }
+
+ });
+
+ Token last = this.tm.get(this.tm.size() - 1);
+ last.clearLineBreaksAfter();
+ int endingBreaks = getLineBreaksToPreserve(last, null);
+ if (endingBreaks > 0) {
+ last.putLineBreaksAfter(endingBreaks);
+ }
+ else if ((this.kind & (CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.K_MODULE_INFO)) != 0
+ && this.options.insert_new_line_at_end_of_file_if_missing) {
+ last.breakAfter();
+ }
+ }
+
+ int getLineBreaksToPreserve(Token token1, Token token2) {
+ if ((token1 != null && !token1.isPreserveLineBreaksAfter())
+ || (token2 != null && !token2.isPreserveLineBreaksBefore())) {
+ return 0;
+ }
+ if (token1 != null) {
+ List structure = token1.getInternalStructure();
+ if (structure != null && !structure.isEmpty()) {
+ token1 = structure.get(structure.size() - 1);
+ }
+ }
+ if (token2 != null) {
+ List structure = token2.getInternalStructure();
+ if (structure != null && !structure.isEmpty()) {
+ token2 = structure.get(0);
+ }
+ }
+ int lineBreaks = WrapPreparator.this.tm.countLineBreaksBetween(token1, token2);
+ int toPreserve = this.options.number_of_empty_lines_to_preserve;
+ if (token1 != null && token2 != null) {
+ toPreserve++; // n empty lines = n+1 line breaks, except for file start and
+ // end
+ }
+ return Math.min(lineBreaks, toPreserve);
+ }
+
+ private void applyBreaksOutsideRegions(List regions) {
+ String source = this.tm.getSource();
+ int previousRegionEnd = 0;
+ for (IRegion region : regions) {
+ int index = this.tm.findIndex(previousRegionEnd, -1, true);
+ Token token = this.tm.get(index);
+ if (this.tm.countLineBreaksBetween(source, previousRegionEnd,
+ Math.min(token.originalStart, region.getOffset())) > 0) {
+ token.breakBefore();
+ }
+ for (index++; index < this.tm.size(); index++) {
+ Token next = this.tm.get(index);
+ if (next.originalStart > region.getOffset()) {
+ if (this.tm.countLineBreaksBetween(source, token.originalEnd, region.getOffset()) > 0) {
+ next.breakBefore();
+ }
+ break;
+ }
+ if (this.tm.countLineBreaksBetween(token, next) > 0) {
+ next.breakBefore();
+ }
+ token = next;
+ }
+ previousRegionEnd = region.getOffset() + region.getLength() - 1;
+ }
+ }
+
+ private void wrapComments() {
+ CommentWrapExecutor commentWrapper = new CommentWrapExecutor(this.tm, this.options);
+ boolean isNLSTagInLine = false;
+ for (int i = 0; i < this.tm.size(); i++) {
+ Token token = this.tm.get(i);
+ if (token.getLineBreaksBefore() > 0 || token.getLineBreaksAfter() > 0) {
+ isNLSTagInLine = false;
+ }
+ if (token.hasNLSTag()) {
+ assert token.tokenType == TokenNameStringLiteral;
+ isNLSTagInLine = true;
+ }
+ List structure = token.getInternalStructure();
+ if (token.isComment() && structure != null && !structure.isEmpty() && !isNLSTagInLine) {
+ int startPosition = this.tm.getPositionInLine(i);
+ if (token.tokenType == TokenNameCOMMENT_LINE) {
+ commentWrapper.wrapLineComment(token, startPosition);
+ }
+ else {
+ assert token.tokenType == TokenNameCOMMENT_BLOCK || token.tokenType == TokenNameCOMMENT_JAVADOC;
+ commentWrapper.wrapMultiLineComment(token, startPosition, false, false);
+ }
+ }
+ }
+ }
+
+ private void fixEnumConstantIndents(ASTNode astRoot) {
+ if (this.options.use_tabs_only_for_leading_indentations) {
+ // enum constants should be indented like other declarations, not like wrapped
+ // elements
+ astRoot.accept(new ASTVisitor() {
+
+ @Override
+ public boolean visit(EnumConstantDeclaration node) {
+ WrapPreparator.this.tm.firstTokenIn(node, -1).setWrapPolicy(null);
+ return true;
+ }
+ });
+ }
+ }
+
+ private void handleParenthesesPositions(int openingParenIndex, int closingParenIndex, String positionsSetting) {
+ boolean isEmpty = openingParenIndex + 1 == closingParenIndex;
+ switch (positionsSetting) {
+ case DefaultCodeFormatterConstants.COMMON_LINES:
+ // nothing to do
+ break;
+ case DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED:
+ if (isEmpty) {
+ break;
+ }
+ this.tm.get(openingParenIndex + 1).setWrapPolicy(new WrapPolicy(WrapMode.TOP_PRIORITY, openingParenIndex,
+ closingParenIndex, this.options.indentation_size, this.currentDepth, 1, true, false));
+ this.tm.get(closingParenIndex).setWrapPolicy(new WrapPolicy(WrapMode.TOP_PRIORITY, openingParenIndex,
+ closingParenIndex, 0, this.currentDepth, 1, false, false));
+ break;
+ case DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPTY:
+ if (isEmpty) {
+ break;
+ }
+ //$FALL-THROUGH$
+ case DefaultCodeFormatterConstants.SEPARATE_LINES:
+ case DefaultCodeFormatterConstants.PRESERVE_POSITIONS:
+ boolean always = !positionsSetting.equals(DefaultCodeFormatterConstants.PRESERVE_POSITIONS);
+ Token afterOpening = this.tm.get(openingParenIndex + 1);
+ if (always || this.tm.countLineBreaksBetween(this.tm.get(openingParenIndex), afterOpening) > 0) {
+ afterOpening.setWrapPolicy(
+ new WrapPolicy(WrapMode.WHERE_NECESSARY, openingParenIndex, this.options.indentation_size));
+ afterOpening.breakBefore();
+ }
+ Token closingParen = this.tm.get(closingParenIndex);
+ if (always || this.tm.countLineBreaksBetween(this.tm.get(closingParenIndex - 1), closingParen) > 0) {
+ closingParen.setWrapPolicy(new WrapPolicy(WrapMode.WHERE_NECESSARY, openingParenIndex, 0));
+ closingParen.breakBefore();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unrecognized parentheses positions setting: " + positionsSetting); //$NON-NLS-1$
+ }
+ }
+
+ // @formatter:on
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
index 2e7c1713..9be11ea0 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-rewriter/pom.xml
@@ -1,11 +1,11 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-formatter-eclipse-rewriterSpring 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 41586fb7..7053dc0c 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,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -24,12 +24,17 @@
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.function.Function;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -40,48 +45,87 @@
*/
public final class EclipseRewriter {
+ private static final Set UPDATED_METHODS;
+ static {
+ Set updatedMethods = new LinkedHashSet();
+ updatedMethods.add("prepareWraps");
+ updatedMethods.add("tokenizeSource");
+ UPDATED_METHODS = Collections.unmodifiableSet(updatedMethods);
+ }
+
+ private static final Set UPDATED_FIELDS;
+ static {
+ Set updatedFields = new LinkedHashSet();
+ updatedFields.add("sourceLevel");
+ updatedFields.add("tokens");
+ UPDATED_FIELDS = Collections.unmodifiableSet(updatedFields);
+ }
+
private EclipseRewriter() {
}
- public void rewrite(String file) throws IOException {
+ public void rewrite(JdkVersion jdkVersion, String file) throws IOException {
System.out.println("Rewriting classes in " + file);
- URI uri = URI.create("jar:file:" + file);
- try (FileSystem zip = FileSystems.newFileSystem(uri,
- Collections.singletonMap("create", "true"))) {
- rewrite(zip);
+ URI uri = URI.create("jar:file:" + Paths.get(file).toUri().getPath());
+ try (FileSystem zip = FileSystems.newFileSystem(uri, Collections.singletonMap("create", "true"))) {
+ rewrite(jdkVersion, zip);
+ }
+ }
+
+ private void rewrite(JdkVersion jdkVersion, FileSystem zip) throws IOException {
+ rewrite(zip, "org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.class",
+ DefaultCodeFormatterManipulator::new);
+ if (jdkVersion == JdkVersion.V8) {
+ rewrite(zip, "org/eclipse/osgi/util/NLS$1.class", NlsJdk8Manipulator::new);
+ deleteWrapPreparator(zip);
+ }
+ else {
+ rewrite(zip, "org/eclipse/osgi/util/NLS.class", NlsJdk17Manipulator::new);
}
}
- private void rewrite(FileSystem zip) throws IOException {
- Path path = zip
- .getPath("org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.class");
- ClassWriter writer = new ClassWriter(0);
+ private void rewrite(FileSystem zip, String name, Function manipulator)
+ throws IOException {
+ ClassWriter classWriter = new ClassWriter(0);
+ Path path = zip.getPath(name);
try (InputStream in = Files.newInputStream(path)) {
- DefaultCodeFormatterManipulator manipulator = new DefaultCodeFormatterManipulator(
- writer);
ClassReader reader = new ClassReader(in);
- reader.accept(manipulator, 0);
+ reader.accept(manipulator.apply(classWriter), 0);
}
- Files.copy(new ByteArrayInputStream(writer.toByteArray()), path,
- StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(new ByteArrayInputStream(classWriter.toByteArray()), path, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ private void deleteWrapPreparator(FileSystem zip) throws IOException {
+ Path path = zip.getPath("org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.class");
+ Files.delete(path);
}
public static void main(String[] args) throws Exception {
- new EclipseRewriter().rewrite(args[0]);
+ new EclipseRewriter().rewrite(JdkVersion.valueOf("V" + args[0]), args[1]);
}
+ /**
+ * {@link ClassVisitor} to make some fields and methods from
+ * {@code DefaultCodeFormatter} public.
+ */
private static class DefaultCodeFormatterManipulator extends ClassVisitor {
DefaultCodeFormatterManipulator(ClassVisitor visitor) {
- super(Opcodes.ASM5, visitor);
+ super(Opcodes.ASM9, visitor);
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+ if ((access & Opcodes.ACC_PRIVATE) != 0 && UPDATED_FIELDS.contains(name)) {
+ access = Opcodes.ACC_PROTECTED;
+ }
+ return super.visitField(access, name, desc, signature, value);
}
@Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- if ("prepareWraps".equals(name) && Opcodes.ACC_PRIVATE == access) {
- return super.visitMethod(Opcodes.ACC_PROTECTED, name, desc, signature,
- exceptions);
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ if ((access & Opcodes.ACC_PRIVATE) != 0 && UPDATED_METHODS.contains(name)) {
+ access = Opcodes.ACC_PROTECTED;
}
return new DefaultCodeFormatterMethodManipulator(
super.visitMethod(access, name, desc, signature, exceptions));
@@ -89,22 +133,129 @@ public MethodVisitor visitMethod(int access, String name, String desc,
}
+ /**
+ * {@link MethodVisitor} to make some fields and methods from
+ * {@code DefaultCodeFormatter} public.
+ */
private static class DefaultCodeFormatterMethodManipulator extends MethodVisitor {
DefaultCodeFormatterMethodManipulator(MethodVisitor mv) {
- super(Opcodes.ASM5, mv);
+ super(Opcodes.ASM9, mv);
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
- if ("prepareWraps".equals(name) && opcode == Opcodes.INVOKESPECIAL) {
- super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
- return;
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+ if (opcode == Opcodes.INVOKESPECIAL && UPDATED_METHODS.contains(name)) {
+ opcode = Opcodes.INVOKEVIRTUAL;
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
+ /**
+ * {@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 NlsJdk8Manipulator extends ClassVisitor {
+
+ NlsJdk8Manipulator(ClassVisitor visitor) {
+ super(Opcodes.ASM9, visitor);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ if ("run".equals(name) && desc.contains("Boolean")) {
+ return new NslJdk8MethodManipulator(super.visitMethod(access, name, desc, signature, exceptions));
+ }
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ }
+
+ /**
+ * {@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 NslJdk8MethodManipulator extends MethodVisitor {
+
+ private final MethodVisitor methodVisitor;
+
+ NslJdk8MethodManipulator(MethodVisitor mv) {
+ super(Opcodes.ASM9, null);
+ this.methodVisitor = mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ MethodVisitor mv = this.methodVisitor;
+ mv.visitCode();
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
+ mv.visitInsn(Opcodes.ARETURN);
+ mv.visitMaxs(1, 1);
+ mv.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 NlsJdk17Manipulator extends ClassVisitor {
+
+ 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 NslJdk17MethodManipulator(super.visitMethod(access, name, desc, signature, exceptions));
+ }
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ }
+
+ /**
+ * {@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 NslJdk17MethodManipulator extends MethodVisitor {
+
+ private final MethodVisitor methodVisitor;
+
+ NslJdk17MethodManipulator(MethodVisitor mv) {
+ super(Opcodes.ASM9, null);
+ this.methodVisitor = mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ MethodVisitor mv = this.methodVisitor;
+ mv.visitCode();
+ mv.visitInsn(Opcodes.ICONST_0);
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, "org/eclipse/osgi/util/NLS", "EMPTY_ARGS", "[Ljava/lang/Object;");
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, "org/eclipse/osgi/util/NLS", "ignoreWarnings", "Z");
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Object");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false);
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, "org/eclipse/osgi/util/NLS", "ASSIGNED", "Ljava/lang/Object;");
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(2, 0);
+ mv.visitEnd();
+ }
+
+ }
+
+ enum JdkVersion {
+
+ V8, V11
+
+ }
+
}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
index a9042a0e..dab30621 100644
--- a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/pom.xml
@@ -1,189 +1,84 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0io.spring.javaformatspring-javaformat
- 0.0.7-SNAPSHOT
+ 0.0.48-SNAPSHOTspring-javaformat-formatter-eclipse-runtime
- eclipse-pluginSpring JavaFormat Eclipse Runtime${basedir}/../..
- org.eclipse.jdt.core.source,org.eclipse.jface.source,org.eclipse.text.source
-
-
- Eclipse Public License, Version 1.0
- https://www.eclipse.org/legal/epl-v10.html
-
-
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-jdk8
+ ${project.version}
+ true
+
+
+ org.apache.maven.plugins
- maven-antrun-plugin
-
-
- io.spring.javaformat
- spring-javaformat-formatter-eclipse-rewriter
- ${project.version}
-
-
- ant-contrib
- ant-contrib
- ${ant-contrib.version}
-
-
- ant
- ant
-
-
-
-
- org.apache.ant
- ant-nodeps
- ${ant.version}
-
-
+ maven-jar-plugin
- rewrite-bytecode
- package
-
- run
-
-
-
-
-
-
-
-
-
-
- repackage-source
+ empty-javadoc-jarpackage
- run
+ jar
-
-
-
-
+ javadoc
-
- org.eclipse.tycho
- tycho-packaging-plugin
-
- false
-
-
-
- org.eclipse.tycho
- tycho-maven-plugin
-
-
- org.eclipse.tycho
- target-platform-configuration
-
-
- org.eclipse.tycho
- tycho-versions-plugin
-
-
- update-eclipse-version
- initialize
-
- update-eclipse-metadata
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
+ maven-source-plugin
- unpack-dependencies
-
- unpack-dependencies
-
- prepare-package
-
- ${project.build.outputDirectory}
- META-INF/*,**.dll,**.so,**.java
- ${sourceartifacts}
-
-
-
- unpack-source-dependencies
+ attach-source
+ package
- unpack-dependencies
+ jar
- prepare-package
-
- ${project.build.directory}/sources
- ${sourceartifacts}
-
- com.github.wvengen
- proguard-maven-plugin
+ org.apache.maven.plugins
+ maven-shade-plugin
- reduce-eclipse-runtimepackage
- proguard
+ shade
- false
-
- ${java.home}/lib/rt.jar
- ${java.home}/lib/jsse.jar
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ io.spring.javaformat:spring-javaformat-formatter-eclipse-jdk8
+
+ org/eclipse/jdt/**
+ META-INF/ECLIPSE_.SF
+ META-INF/ECLIPSE_.RSA
+
+
+
+ false
+ true
+ true
-
-
- io.spring.javaformat
- spring-javaformat-formatter-eclipse-rewriter
- ${project.version}
- provided
-
-
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$ContentTypeChangeEvent.java b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$ContentTypeChangeEvent.java
new file mode 100644
index 00000000..78e9cd52
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$ContentTypeChangeEvent.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017-present 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 org.eclipse.core.runtime.content;
+
+public class IContentTypeManager$ContentTypeChangeEvent {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$IContentTypeChangeListener.java b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$IContentTypeChangeListener.java
new file mode 100644
index 00000000..6458ef5a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-eclipse-runtime/src/main/java/org/eclipse/core/runtime/content/IContentTypeManager$IContentTypeChangeListener.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017-present 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 org.eclipse.core.runtime.content;
+
+public interface IContentTypeManager$IContentTypeChangeListener {
+
+ void contentTypeChanged(IContentTypeManager$ContentTypeChangeEvent event);
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml b/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml
new file mode 100644
index 00000000..330f53c9
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-shaded/pom.xml
@@ -0,0 +1,124 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-shaded
+ Spring JavaFormat Formatter Shaded
+
+ ${basedir}/../..
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ empty-javadoc-jar
+ package
+
+ jar
+
+
+ javadoc
+
+
+
+
+
+ org.codehaus.mojo
+ flatten-maven-plugin
+
+ true
+ oss
+
+ expand
+ remove
+ remove
+ remove
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ ${project.groupId}
+ spring-javaformat-formatter-shader
+ ${project.version}
+
+
+
+ true
+ true
+ false
+
+
+ io.spring.javaformat:*
+
+
+
+
+ org.eclipse
+ io.spring.javaformat.org.eclipse
+
+
+ com.ibm
+ io.spring.javaformat.com.ibm
+
+
+ org.osgi
+ io.spring.javaformat.org.osgi
+
+
+
+
+
+
+ ${project.version}
+
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-config
+ ${project.version}
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ ${project.version}
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-runtime
+ ${project.version}
+
+
+ *
+ *
+
+
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-shader/pom.xml b/spring-javaformat/spring-javaformat-formatter-shader/pom.xml
new file mode 100644
index 00000000..a07cf239
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-shader/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-shader
+ Spring JavaFormat Formatter Shader
+
+ ${basedir}/../..
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+ maven-plugin
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-shader/src/main/java/io/spring/javaformat/formatter/shader/PrefsResourceTransformer.java b/spring-javaformat/spring-javaformat-formatter-shader/src/main/java/io/spring/javaformat/formatter/shader/PrefsResourceTransformer.java
new file mode 100644
index 00000000..09882163
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-shader/src/main/java/io/spring/javaformat/formatter/shader/PrefsResourceTransformer.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2017-present 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.shader;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import org.apache.maven.plugins.shade.relocation.Relocator;
+import org.apache.maven.plugins.shade.resource.ResourceTransformer;
+
+/**
+ * {@link ResourceTransformer} to fix formatter preference files.
+ *
+ * @author Phillip Webb
+ */
+public class PrefsResourceTransformer implements ResourceTransformer {
+
+ private final Map> transformedResources = new LinkedHashMap<>();
+
+ @Override
+ public boolean canTransformResource(String resource) {
+ return resource.endsWith("formatter.prefs");
+ }
+
+ @Override
+ public void processResource(String resource, InputStream is, List relocators) throws IOException {
+ List trandformedLines = new ArrayList<>();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ String line = reader.readLine();
+ while (line != null) {
+ trandformedLines.add(transformLine(line, relocators));
+ line = reader.readLine();
+ }
+ this.transformedResources.put(resource, trandformedLines);
+ }
+
+ private String transformLine(String line, List relocators) {
+ int splitIndex = line.lastIndexOf('=');
+ if (splitIndex == -1) {
+ return line;
+ }
+ String key = line.substring(0, splitIndex);
+ String value = line.substring(splitIndex + 1);
+ return relocateKey(key, relocators) + "=" + value;
+ }
+
+ private String relocateKey(String key, List relocators) {
+ for (Relocator relocator : relocators) {
+ if (relocator.canRelocateClass(key)) {
+ return relocator.relocateClass(key);
+ }
+ }
+ return key;
+ }
+
+ @Override
+ public boolean hasTransformedResource() {
+ return true;
+ }
+
+ @Override
+ public void modifyOutputStream(JarOutputStream os) throws IOException {
+ for (Map.Entry> entry : this.transformedResources.entrySet()) {
+ write(os, entry.getKey(), entry.getValue());
+ }
+ }
+
+ private void write(JarOutputStream os, String resource, List lines) throws IOException {
+ os.putNextEntry(new JarEntry(resource));
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os));
+ for (String line : lines) {
+ writer.write(line);
+ writer.write("\n");
+ }
+ writer.flush();
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml b/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml
new file mode 100644
index 00000000..1f72a67a
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-test-support/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-test-support
+ Spring JavaFormat Formatter Test Support
+
+ ${basedir}/../..
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ ${project.version}
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-runtime
+ ${project.version}
+ provided
+
+
+
diff --git a/spring-javaformat/spring-javaformat-formatter-test-support/src/main/java/io/spring/javaformat/formatter/FormatterApp.java b/spring-javaformat/spring-javaformat-formatter-test-support/src/main/java/io/spring/javaformat/formatter/FormatterApp.java
new file mode 100644
index 00000000..ca679983
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-test-support/src/main/java/io/spring/javaformat/formatter/FormatterApp.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017-present 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;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Test app used to format something in a test container.
+ *
+ * @author Phillip Webb
+ */
+public final class FormatterApp {
+
+ private FormatterApp() {
+ }
+
+ public static void main(String[] args) throws Exception, BadLocationException {
+ JavaBaseline javaBaseline = JavaBaseline.valueOf(args[0]);
+ Formatter formatter = new Formatter(JavaFormatConfig.of(javaBaseline, IndentationStyle.TABS));
+ String source = "public class Test {}";
+ TextEdit edit = formatter.format(source);
+ IDocument document = new Document(source);
+ edit.apply(document);
+ String formatted = document.get();
+ System.out.println(formatted);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/pom.xml b/spring-javaformat/spring-javaformat-formatter-tests/pom.xml
new file mode 100644
index 00000000..30ea6a7e
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ io.spring.javaformat
+ spring-javaformat
+ 0.0.48-SNAPSHOT
+
+ spring-javaformat-formatter-tests
+ Spring JavaFormat Formatter Tests
+
+ ${basedir}/../..
+ 17
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ ${project.version}
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-eclipse-runtime
+ ${project.version}
+ provided
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter-test-support
+ ${project.version}
+ test
+
+
+ org.apache.logging.log4j
+ log4j-api
+ test
+
+
+ org.apache.logging.log4j
+ log4j-core
+ test
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ test
+
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+
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
new file mode 100644
index 00000000..1af21b70
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/AbstractFormatterTests.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.io.File;
+import java.io.IOException;
+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;
+import io.spring.javaformat.config.JavaFormatConfig;
+
+/**
+ * Base class for formatter tests.
+ *
+ * @author Phillip Webb
+ */
+public abstract class AbstractFormatterTests {
+
+ protected final void print(String name, String content) {
+ System.out.println(name + ":");
+ System.out.println();
+ System.out.println("----------------------------------------");
+ System.out.println(content);
+ System.out.println("----------------------------------------");
+ System.out.println();
+ System.out.println();
+ }
+
+ protected final String read(File file) throws Exception {
+ return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+ }
+
+ protected static Item[] items(String expectedOverride) {
+ List items = new ArrayList<>();
+ File sourceDir = new File("src/test/resources/source");
+ File expectedDir = new File("src/test/resources/expected");
+ File configDir = new File("src/test/resources/config");
+ File expectedOverrideDir = new File("src/test/resources/" + expectedOverride);
+ for (File source : sourceDir.listFiles((dir, name) -> !name.startsWith("."))) {
+ File config = new File(configDir, source.getName());
+ for (JavaBaseline javaBaseline : JavaBaseline.values()) {
+ File expected = getExpected(source, javaBaseline, expectedOverrideDir, expectedDir);
+ addItem(items, javaBaseline, source, expected, config);
+ }
+ }
+ items.sort(Comparator.comparing(Item::getName));
+ return items.toArray(new Item[0]);
+ }
+
+ private static File getExpected(File source, JavaBaseline javaBaseline, File... expectedDirs) {
+ for (File expectedDir : expectedDirs) {
+ File versionSpecificExpectedDir = new File(expectedDir, javaBaseline.toString().toLowerCase());
+ File expected = new File(versionSpecificExpectedDir, source.getName());
+ expected = (!expected.exists()) ? new File(expectedDir, source.getName()) : expected;
+ if (expected.exists()) {
+ return expected;
+ }
+ }
+ throw new IllegalStateException("Unable to find expected file");
+ }
+
+ private static void addItem(List items, JavaBaseline javaBaseline, File source, File expected, File config) {
+ if (source.getName().contains("lineendings")) {
+ items.add(new Item(javaBaseline, copy(source, LineEnding.CR), copy(expected, LineEnding.CR), config));
+ items.add(new Item(javaBaseline, copy(source, LineEnding.LF), copy(expected, LineEnding.LF), config));
+ items.add(new Item(javaBaseline, copy(source, LineEnding.CRLF), copy(expected, LineEnding.CRLF), config));
+ }
+ else {
+ items.add(new Item(javaBaseline, source, expected, config));
+ }
+ }
+
+ private static File copy(File file, LineEnding lineEnding) {
+ try {
+ String[] name = file.getName().split("\\.");
+ File result = File.createTempFile(name[0] + "_" + lineEnding + "_", "." + name[1]);
+ String content = Files.readString(file.toPath());
+ content = content.replace("\r\n", "\n").replace('\r', '\n').replace("\n", lineEnding.ending());
+ Files.writeString(result.toPath(), content);
+ return result;
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ enum LineEnding {
+
+ CR("\r"), LF("\n"), CRLF("\r\n");
+
+ private final String ending;
+
+ LineEnding(String ending) {
+ this.ending = ending;
+ }
+
+ String ending() {
+ return this.ending;
+ }
+
+ };
+
+ static class Item {
+
+ private final JavaBaseline javaBaseline;
+
+ private final File source;
+
+ private final File expected;
+
+ private final JavaFormatConfig config;
+
+ Item(JavaBaseline javaBaseline, File source, File expected, File config) {
+ this.javaBaseline = javaBaseline;
+ this.source = source;
+ this.expected = expected;
+ this.config = loadConfig(javaBaseline, config);
+ }
+
+ private JavaFormatConfig loadConfig(JavaBaseline javaBaseline, File configFile) {
+ JavaFormatConfig config = (!configFile.exists()) ? JavaFormatConfig.DEFAULT
+ : JavaFormatConfig.load(configFile);
+ return JavaFormatConfig.of(javaBaseline, config.getIndentationStyle());
+ }
+
+ String getName() {
+ return this.source.getName();
+ }
+
+ public File getSource() {
+ return this.source;
+ }
+
+ public File getExpected() {
+ return this.expected;
+ }
+
+ public JavaFormatConfig getConfig() {
+ return this.config;
+ }
+
+ @Override
+ public String toString() {
+ return this.javaBaseline + " " + this.source.getName();
+ }
+
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FileEditTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileEditTests.java
similarity index 70%
rename from spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FileEditTests.java
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileEditTests.java
index ac53f345..015b9eb7 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FileEditTests.java
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileEditTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -24,10 +24,9 @@
import java.nio.file.StandardCopyOption;
import org.eclipse.text.edits.TextEdit;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import static org.assertj.core.api.Assertions.assertThat;
@@ -40,8 +39,8 @@ public class FileEditTests {
private static final Charset UTF_8 = StandardCharsets.UTF_8;
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ @TempDir
+ public File temp;
private File source;
@@ -51,31 +50,31 @@ public class FileEditTests {
private FileEdit fileEdit;
- @Before
- public void setup() throws IOException {
- this.source = this.temp.newFile("source.txt");
- this.expected = this.temp.newFile("expected.txt");
- Files.copy(new File("src/test/resources/source/javadoc-top.txt").toPath(),
- this.source.toPath(), StandardCopyOption.REPLACE_EXISTING);
- Files.copy(new File("src/test/resources/expected/javadoc-top.txt").toPath(),
- this.expected.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ @BeforeEach
+ void setup() throws IOException {
+ this.source = new File(this.temp, "source.txt");
+ this.expected = new File(this.temp, "expected.txt");
+ Files.copy(new File("src/test/resources/source/javadoc-top.txt").toPath(), this.source.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(new File("src/test/resources/expected/javadoc-top.txt").toPath(), this.expected.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
String content = read(this.source);
this.textEdit = new Formatter().format(content);
this.fileEdit = new FileEdit(this.source, UTF_8, content, this.textEdit);
}
@Test
- public void getFileShouldReturnFile() throws Exception {
+ void getFileReturnsFile() throws Exception {
assertThat(this.fileEdit.getFile()).isEqualTo(this.source);
}
@Test
- public void hasEditsWhenHasEditsShouldReturnTrue() throws Exception {
+ void hasEditsWhenHasEditsReturnsTrue() throws Exception {
assertThat(this.fileEdit.hasEdits()).isTrue();
}
@Test
- public void hasEditsWhenHasNoEditsShouldReturnFalse() throws Exception {
+ void hasEditsWhenHasNoEditsReturnsFalse() throws Exception {
String content = read(this.expected);
this.textEdit = new Formatter().format(content);
this.fileEdit = new FileEdit(this.source, UTF_8, content, this.textEdit);
@@ -83,7 +82,7 @@ public void hasEditsWhenHasNoEditsShouldReturnFalse() throws Exception {
}
@Test
- public void saveShouldSaveContent() throws Exception {
+ void saveSavesContent() throws Exception {
String expected = read(this.expected);
assertThat(read(this.source)).isNotEqualTo(expected);
this.fileEdit.save();
@@ -91,7 +90,7 @@ public void saveShouldSaveContent() throws Exception {
}
@Test
- public void getFormattedContentShouldReturnFormattedContent() throws Exception {
+ void getFormattedContentReturnsFormattedContent() throws Exception {
String expected = read(this.expected);
assertThat(this.fileEdit.getFormattedContent()).isEqualTo(expected);
}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileFormatterTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileFormatterTests.java
new file mode 100644
index 00000000..f9d14f7c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FileFormatterTests.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link FileFormatter}.
+ *
+ * @author Phillip Webb
+ */
+public class FileFormatterTests extends AbstractFormatterTests {
+
+ private static final boolean RUNNING_ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatFilesFromIteratorFormatsFile(Item item) throws Exception {
+ FileEdit edit = new FileFormatter(item.getConfig())
+ .formatFiles(Arrays.asList(item.getSource()), StandardCharsets.UTF_8)
+ .findFirst()
+ .get();
+ assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
+ }
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatFilesFromStreamFormatsFile(Item item) throws Exception {
+ FileEdit edit = new FileFormatter(item.getConfig())
+ .formatFiles(Arrays.asList(item.getSource()).stream(), StandardCharsets.UTF_8)
+ .findFirst()
+ .get();
+ assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
+ }
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatFileFormatsFile(Item item) throws Exception {
+ File source = item.getSource();
+ FileEdit edit = new FileFormatter(item.getConfig()).formatFile(source, StandardCharsets.UTF_8);
+ String formattedContent = edit.getFormattedContent();
+ String expected = read(item.getExpected());
+ if (!RUNNING_ON_WINDOWS) {
+ System.out.println(source);
+ System.out.println("----- got");
+ System.out.println(formattedContent);
+ System.out.println("----- expected");
+ System.out.println(expected);
+ System.out.println("-----");
+ }
+ assertThat(formattedContent).isEqualTo(expected);
+ }
+
+ static Item[] items() {
+ return items(null);
+ }
+
+}
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
new file mode 100644
index 00000000..383b07cd
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterIntegrationTests.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.testcontainers.containers.ContainerLaunchException;
+import org.testcontainers.containers.output.ToStringConsumer;
+import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.MountableFile;
+
+import io.spring.javaformat.config.JavaBaseline;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+/**
+ * Tests to ensure the formatter can run in different JVM versions.
+ *
+ * @author Phillip Webb
+ */
+@Testcontainers(disabledWithoutDocker = true)
+public class FormatterIntegrationTests {
+
+ @ParameterizedTest
+ @ValueSource(strings = { "8", "11", "17" })
+ void formatCodeWithV8BaselineCanFormatOnAllVersions(String version) throws Exception {
+ runFormatter(JavaBaseline.V8, version);
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = { "17" })
+ void formatCodeWithV11BaselineCanFormatOn11OrHigher(String version) throws Exception {
+ runFormatter(JavaBaseline.V17, version);
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = "8")
+ void formatCodeWithV11BaselineCannotFormatOn8(String version) throws Exception {
+ assertThatExceptionOfType(ContainerLaunchException.class)
+ .isThrownBy(() -> runFormatter(JavaBaseline.V17, version));
+ }
+
+ private void runFormatter(JavaBaseline baseline, String version) throws IOException, Exception {
+ try (JavaContainer container = new JavaContainer(version)) {
+ ToStringConsumer output = new ToStringConsumer();
+ container.withStartupCheckStrategy(new OneShotStartupCheckStrategy().withTimeout(Duration.ofMinutes(5)));
+ container.withLogConsumer(output);
+ String classpath = withCopyClasspathToContainer(container);
+ container.withCommand(
+ "java -cp " + classpath + " " + "io.spring.javaformat.formatter.FormatterApp" + " " + baseline);
+ container.start();
+ assertThat(output.toUtf8String()).isEqualTo("public class Test {\n\n}\n");
+ }
+ }
+
+ private String withCopyClasspathToContainer(JavaContainer container) throws IOException {
+ List classpath = new ArrayList<>();
+ for (String entry : System.getProperty("java.class.path").split(File.pathSeparator)) {
+ if (entry.contains("spring-javaformat")) {
+ String classpathEntry = withCopyClasspathEntryToContainer(container, entry);
+ if (classpathEntry != null) {
+ classpath.add(classpathEntry);
+ }
+ }
+ }
+ return classpath.stream().collect(Collectors.joining(":"));
+ }
+
+ private String withCopyClasspathEntryToContainer(JavaContainer container, String entry) throws IOException {
+ if (entry.endsWith(".jar")) {
+ return withCopyClasspathJarToContainer(container, new File(entry));
+ }
+ return withCopyClasspathFolderToContainer(container, new File(entry));
+ }
+
+ private String withCopyClasspathJarToContainer(JavaContainer container, File jarFile) {
+ container.withCopyFileToContainer(MountableFile.forHostPath(jarFile.toPath()), "/app/" + jarFile.getName());
+ return "/app/" + jarFile.getName();
+ }
+
+ private String withCopyClasspathFolderToContainer(JavaContainer container, File classesFolder) throws IOException {
+ String name = classesFolder.getName();
+ Path source = classesFolder.toPath();
+ if (!Files.exists(source)) {
+ return null;
+ }
+ try (Stream stream = Files.walk(source)) {
+ stream.forEach((child) -> {
+ try {
+ Path relative = source.relativize(child);
+ if (!child.toFile().isDirectory()) {
+ String containerPath = "/app/" + name + "/" + relative;
+ container.withCopyFileToContainer(MountableFile.forHostPath(child), containerPath);
+ }
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ });
+ }
+ return "/app/" + name;
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FormatterTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterTests.java
similarity index 50%
rename from spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FormatterTests.java
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterTests.java
index 7c4cdfa7..cc1c8b50 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/test/java/io/spring/javaformat/formatter/FormatterTests.java
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/FormatterTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017-2018 the original author or authors.
+ * Copyright 2017-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,14 +16,13 @@
package io.spring.javaformat.formatter;
-import java.io.File;
-import java.util.Collection;
-
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;
-import org.junit.Test;
-import org.junit.runners.Parameterized.Parameters;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import io.spring.javaformat.config.JavaFormatConfig;
import static org.assertj.core.api.Assertions.assertThat;
@@ -32,37 +31,32 @@
*/
public class FormatterTests extends AbstractFormatterTests {
- public FormatterTests(File source, File expected) {
- super(source, expected);
- }
-
- @Test
- public void format() throws Exception {
- String sourceContent = read(getSource());
- String expectedContent = read(getExpected());
- String formattedContent = format(sourceContent);
+ @ParameterizedTest
+ @MethodSource("items")
+ void format(Item item) throws Exception {
+ String sourceContent = read(item.getSource());
+ String expectedContent = read(item.getExpected());
+ String formattedContent = format(item.getConfig(), sourceContent);
if (!expectedContent.equals(formattedContent)) {
- System.out.println(
- "Formatted " + getSource() + " does not match " + getExpected());
- print("Source " + getSource(), sourceContent);
- print("Expected +" + getExpected(), expectedContent);
+ System.out.println("Formatted " + item.getSource() + " does not match " + item.getExpected());
+ print("Source " + item.getSource(), sourceContent);
+ print("Expected +" + item.getExpected(), expectedContent);
print("Got", formattedContent);
System.out.println("========================================");
- assertThat(expectedContent).isEqualTo(formattedContent)
- .describedAs("Formatted content does not match for " + getSource());
+ assertThat(formattedContent).isEqualTo(expectedContent)
+ .describedAs("Formatted content does not match for " + item.getSource());
}
}
- private String format(String sourceContent) throws Exception {
+ private String format(JavaFormatConfig config, String sourceContent) throws Exception {
IDocument document = new Document(sourceContent);
- TextEdit textEdit = new Formatter().format(sourceContent);
+ TextEdit textEdit = new Formatter(config).format(sourceContent);
textEdit.apply(document);
return document.get();
}
- @Parameters(name = "{0}")
- public static Collection files() {
- return AbstractFormatterTests.files("FormatterTests-expected");
+ static Item[] items() {
+ return items("FormatterTests-expected");
}
}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/JavaContainer.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/JavaContainer.java
new file mode 100644
index 00000000..8f847bbb
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/JavaContainer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present 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;
+
+import org.testcontainers.containers.GenericContainer;
+
+/**
+ * {@link GenericContainer} for Java.
+ *
+ * @author Phillip Webb
+ */
+public class JavaContainer extends GenericContainer {
+
+ JavaContainer(String version) {
+ super("bellsoft/liberica-openjdk-debian:" + version);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsEditTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsEditTests.java
new file mode 100644
index 00000000..b054f57d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsEditTests.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+
+import org.eclipse.text.edits.TextEdit;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link StreamsEdit}.
+ *
+ * @author Phillip Webb
+ */
+public class StreamsEditTests {
+
+ private static final Charset UTF_8 = StandardCharsets.UTF_8;
+
+ @TempDir
+ public File temp;
+
+ private File source;
+
+ private File expected;
+
+ private TextEdit textEdit;
+
+ private StreamsEdit streamsEdit;
+
+ @BeforeEach
+ void setup() throws IOException {
+ this.source = new File(this.temp, "source.txt");
+ this.expected = new File(this.temp, "expected.txt");
+ Files.copy(new File("src/test/resources/source/javadoc-top.txt").toPath(), this.source.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(new File("src/test/resources/expected/javadoc-top.txt").toPath(), this.expected.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+ String content = read(this.source);
+ this.textEdit = new Formatter().format(content);
+ this.streamsEdit = new StreamsEdit(content, this.textEdit);
+ }
+
+ @Test
+ void hasEditsWhenHasEditsReturnsTrue() throws Exception {
+ assertThat(this.streamsEdit.hasEdits()).isTrue();
+ }
+
+ @Test
+ void hasEditsWhenHasNoEditsReturnsFalse() throws Exception {
+ String content = read(this.expected);
+ this.textEdit = new Formatter().format(content);
+ this.streamsEdit = new StreamsEdit(content, this.textEdit);
+ assertThat(this.streamsEdit.hasEdits()).isFalse();
+ }
+
+ @Test
+ void writeToOutputStreamWritesContent() throws Exception {
+ String expected = read(this.expected);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ this.streamsEdit.writeTo(outputStream);
+ assertThat(outputStream.toByteArray()).isEqualTo(expected.getBytes(UTF_8));
+ }
+
+ @Test
+ void writeToOutputStreamWithCharsetWritesContent() throws IOException {
+ String expected = read(this.expected);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ this.streamsEdit.writeTo(outputStream, UTF_8);
+ assertThat(outputStream.toByteArray()).isEqualTo(expected.getBytes(UTF_8));
+ }
+
+ @Test
+ void writeToAppendableWritesContent() throws IOException {
+ String expected = read(this.expected);
+ StringBuilder output = new StringBuilder();
+ this.streamsEdit.writeTo(output);
+ assertThat(output.toString()).isEqualTo(expected);
+ }
+
+ @Test
+ void getFormattedContentReturnsFormattedContent() throws Exception {
+ String expected = read(this.expected);
+ assertThat(this.streamsEdit.getFormattedContent()).isEqualTo(expected);
+ }
+
+ private String read(File file) throws IOException {
+ return new String(Files.readAllBytes(file.toPath()), UTF_8);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsFormatterTests.java b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsFormatterTests.java
new file mode 100644
index 00000000..388c123c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/java/io/spring/javaformat/formatter/StreamsFormatterTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017-present 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;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link StreamsFormatter}.
+ *
+ * @author Phillip Webb
+ */
+public class StreamsFormatterTests extends AbstractFormatterTests {
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatInputStreamFormatsFile(Item item) throws Exception {
+ try (InputStream inputStream = new FileInputStream(item.getSource())) {
+ StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(inputStream);
+ assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatInputStreamWithCharsetFormatsFile(Item item) throws Exception {
+ try (InputStream inputStream = new FileInputStream(item.getSource())) {
+ StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(inputStream, StandardCharsets.UTF_8);
+ assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("items")
+ void formatReaderFormatsFile(Item item) throws Exception {
+ try (Reader reader = new InputStreamReader(new FileInputStream(item.getSource()))) {
+ StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(reader);
+ assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
+ }
+ }
+
+ static Item[] items() {
+ return items(null);
+ }
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/bin/src/test/resources/expected/javadoc-top-add.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/javadoc-top-add.txt
similarity index 100%
rename from spring-javaformat/spring-javaformat-formatter/bin/src/test/resources/expected/javadoc-top-add.txt
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/javadoc-top-add.txt
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/record-with-param.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/record-with-param.txt
new file mode 100644
index 00000000..57e16f3c
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/record-with-param.txt
@@ -0,0 +1,16 @@
+package simple;
+
+/**
+ * Settings that can be applied when creating a {@link ClientHttpRequestFactory}.
+ *
+ * @param connectTimeout the connect timeout
+ * @param readTimeout the read timeout
+ * @param bufferRequestBody if request body buffering is used
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @since 3.0.0
+ * @see ClientHttpRequestFactories
+ */
+public record Simple(String name) {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/test/resources/source/simple.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/simple.txt
similarity index 97%
rename from spring-javaformat/spring-javaformat-formatter/src/test/resources/source/simple.txt
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/simple.txt
index a12ac39e..63ca9a5c 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/test/resources/source/simple.txt
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/FormatterTests-expected/simple.txt
@@ -2,7 +2,7 @@ package simple;
/**
* Simple.
- *
+ *
* @author Phillip Webb
* @since 1.0.0
*/
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/config/spaces.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/config/spaces.txt
new file mode 100644
index 00000000..2588c596
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/config/spaces.txt
@@ -0,0 +1 @@
+indentation-style=spaces
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/annotation-attributes.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/annotation-attributes.txt
new file mode 100644
index 00000000..7dc4da2d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/annotation-attributes.txt
@@ -0,0 +1,15 @@
+class MyTest {
+
+ @SpringBootTest(properties = "spring.main.web-application-type=reactive", classes = {
+ WebTestClientSpringBootTestIntegrationTests.TestConfiguration.class, ExampleWebFluxApplication.class })
+ static class One {
+
+ }
+
+ @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "spring.jersey.type=filter",
+ "server.servlet.context-path=/app", "server.servlet.register-default-servlet=true" })
+ static class Two {
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation-gh-78.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation-gh-78.txt
new file mode 100644
index 00000000..f6b0421d
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation-gh-78.txt
@@ -0,0 +1,9 @@
+package sample;
+
+import sample.SpringBootTest.WebEnvironment;
+
+@SpringBootTest(classes = RibbonClientConfigurationIntegrationTests.TestLBConfig.class,
+ properties = "test.ribbon.ServerListRefreshInterval=999")
+public class SampleApplication {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation.txt
new file mode 100644
index 00000000..3d055ddf
--- /dev/null
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex-annotation.txt
@@ -0,0 +1,9 @@
+package sample;
+
+import sample.SpringBootTest.WebEnvironment;
+
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "management.server.port=0",
+ "management.server.address=127.0.0.1", "management.server.servlet.context-path:/admin" })
+public class SampleApplication {
+
+}
diff --git a/spring-javaformat/spring-javaformat-formatter/src/test/resources/expected/complex.txt b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex.txt
similarity index 91%
rename from spring-javaformat/spring-javaformat-formatter/src/test/resources/expected/complex.txt
rename to spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex.txt
index b66b83f8..a874b5bd 100644
--- a/spring-javaformat/spring-javaformat-formatter/src/test/resources/expected/complex.txt
+++ b/spring-javaformat/spring-javaformat-formatter-tests/src/test/resources/expected/complex.txt
@@ -1,11 +1,11 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -256,8 +256,7 @@ public class SpringApplication {
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment = deduceWebEnvironment();
- setInitializers((Collection) getSpringFactoriesInstances(
- ApplicationContextInitializer.class));
+ setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
@@ -301,22 +300,18 @@ public class SpringApplication {
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(
- args);
- ConfigurableEnvironment environment = prepareEnvironment(listeners,
- applicationArguments);
+ ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
+ ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
- prepareContext(context, environment, listeners, applicationArguments,
- printedBanner);
+ prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
- new StartupInfoLogger(this.mainApplicationClass)
- .logStarted(getApplicationLog(), stopWatch);
+ new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
return context;
}
@@ -326,8 +321,7 @@ public class SpringApplication {
}
}
- private ConfigurableEnvironment prepareEnvironment(
- SpringApplicationRunListeners listeners,
+ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
@@ -339,9 +333,8 @@ public class SpringApplication {
return environment;
}
- private void prepareContext(ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
+ private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
+ SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
@@ -352,8 +345,7 @@ public class SpringApplication {
}
// Add boot specific singleton beans
- context.getBeanFactory().registerSingleton("springApplicationArguments",
- applicationArguments);
+ context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
@@ -378,49 +370,44 @@ public class SpringApplication {
}
private void configureHeadlessProperty() {
- System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
- SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
+ System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
+ System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
- return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
- SpringApplicationRunListener.class, types, this, args));
+ return new SpringApplicationRunListeners(logger,
+ getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
private Collection extends T> getSpringFactoriesInstances(Class type) {
return getSpringFactoriesInstances(type, new Class>[] {});
}
- private Collection extends T> getSpringFactoriesInstances(Class type,
- Class>[] parameterTypes, Object... args) {
+ private Collection extends T> getSpringFactoriesInstances(Class type, Class>[] parameterTypes,
+ Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
- Set names = new LinkedHashSet(
- SpringFactoriesLoader.loadFactoryNames(type, classLoader));
- List instances = createSpringFactoriesInstances(type, parameterTypes,
- classLoader, args, names);
+ Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
+ List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
@SuppressWarnings("unchecked")
- private List createSpringFactoriesInstances(Class type,
- Class>[] parameterTypes, ClassLoader classLoader, Object[] args,
- Set names) {
+ private