diff --git a/.github/scripts/sign-osx-distro-file.sh b/.github/scripts/sign-osx-distro-file.sh index 9c6613d063..db94dd6e57 100755 --- a/.github/scripts/sign-osx-distro-file.sh +++ b/.github/scripts/sign-osx-distro-file.sh @@ -48,11 +48,6 @@ do codesign --verbose --deep --force --timestamp --entitlements "${entitlements}" --options=runtime --keychain "${KEYCHAIN}" -s "${MACOS_CERTIFICATE_ID}" $f done -# These end being inside osx distro tar.gz file built on Linux -rm -rf ${dir}/${destination_folder_name}/SpringToolSuite4.app/plugins -rm -rf ${dir}/${destination_folder_name}/SpringToolSuite4.app/p2 -rm -f ${dir}/${destination_folder_name}/SpringToolSuite4.app/artifacts.xml - # Sign the app ls -la ${dir}/${destination_folder_name}/SpringToolSuite4.app/ codesign --verbose --deep --force --timestamp --entitlements "${entitlements}" --options=runtime --keychain "${KEYCHAIN}" -s "${MACOS_CERTIFICATE_ID}" ${dir}/${destination_folder_name}/SpringToolSuite4.app @@ -71,7 +66,7 @@ echo ' "format": "UDZO"' >> dmg-config.json echo '}' >> dmg-config.json cat ./dmg-config.json dmg_filename=${filename%.*.*}.dmg -aboyko-appdmg ./dmg-config.json ../${dmg_filename} +appdmg ./dmg-config.json ../${dmg_filename} cd .. rm -rf ./${destination_folder_name} diff --git a/.github/workflows/create-gh-release.yml b/.github/workflows/create-gh-release.yml index f65e34da80..698c19084a 100644 --- a/.github/workflows/create-gh-release.yml +++ b/.github/workflows/create-gh-release.yml @@ -1,7 +1,7 @@ name: Create Release on: - workflow_dispatch: + workflow_call: inputs: version: description: Github release marker, i.e. 4.20.1.RELEASE @@ -64,4 +64,4 @@ jobs: release_name: ${{ inputs.version }} body_path: ${{ github.workspace }}/gen-changelog.md draft: true - prerelease: false \ No newline at end of file + prerelease: false diff --git a/.github/workflows/eclipse-ls-extensions-build.yml b/.github/workflows/eclipse-ls-extensions-build.yml index 81c753a752..cf413c3e7b 100644 --- a/.github/workflows/eclipse-ls-extensions-build.yml +++ b/.github/workflows/eclipse-ls-extensions-build.yml @@ -14,7 +14,7 @@ on: eclipse_profile: description: Eclipse profile 'e429' etc required: false - default: 'e429' + default: 'e430' type: string skip_tests: description: skip ls tests execution @@ -113,14 +113,14 @@ jobs: run: | invalid_urls=`aws s3 ls s3://tools-spring-io/${{ steps.upload-p2-to-akamai.outputs.p2_path }}/ --recursive | awk '{$1=$2=$3=""; print $0}' | sed -e 's/^[ \t]*/https:\/\/cdn.spring.io\/spring-tools\//' | paste -sd' ' -` echo "invalid_urls=$invalid_urls" >> $GITHUB_OUTPUT - - name: Verify Eclipse LS Extensions on e431 + - name: Verify Eclipse LS Extensions on e432 if: ${{ inputs.build_type == 'snapshot' }} run: | cd eclipse-language-servers if command -v xvfb-run ; then - xvfb-run ./mvnw --batch-mode clean package -Pe431 -P${{ inputs.build_type }} -Dhttpclient.retry-max=20 -Declipse.p2.mirrors=false -Dmaven.test.skip=true -Dtycho.localArtifacts=ignore + xvfb-run ./mvnw --batch-mode clean package -Pe432 -P${{ inputs.build_type }} -Dhttpclient.retry-max=20 -Declipse.p2.mirrors=false -Dmaven.test.skip=true -Dtycho.localArtifacts=ignore else - ./mvnw --batch-mode clean package -Pe431 -P${{ inputs.build_type }} -Dhttpclient.retry-max=20 -Declipse.p2.mirrors=false -Dmaven.test.skip=true -Dtycho.localArtifacts=ignore + ./mvnw --batch-mode clean package -Pe432 -P${{ inputs.build_type }} -Dhttpclient.retry-max=20 -Declipse.p2.mirrors=false -Dmaven.test.skip=true -Dtycho.localArtifacts=ignore fi purge_cache: diff --git a/.github/workflows/gh-hosted-eclipse-distro-build.yml b/.github/workflows/gh-hosted-eclipse-distro-build.yml index d03a0dead7..c484c8476b 100644 --- a/.github/workflows/gh-hosted-eclipse-distro-build.yml +++ b/.github/workflows/gh-hosted-eclipse-distro-build.yml @@ -235,7 +235,7 @@ jobs: sign-osx-distros: needs: [ eclipse-distro-build ] - runs-on: macos-latest-xl + runs-on: macos-14 steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 with: @@ -264,7 +264,7 @@ jobs: - name: Install appdmg run: | python3 -m pip install setuptools - npm install -g aboyko-appdmg + npm install -g appdmg - name: Cloudgate S3 Configuration uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a with: diff --git a/.github/workflows/publish-eclipse-release.yml b/.github/workflows/publish-eclipse-release.yml index e4cfe92eef..36d4692ff9 100644 --- a/.github/workflows/publish-eclipse-release.yml +++ b/.github/workflows/publish-eclipse-release.yml @@ -38,11 +38,11 @@ jobs: latest: ${{ inputs.eclipse_latest }} secrets: inherit -# create-github-release: -# uses: ./.github/workflows/create-gh-release.yml -# with: -# version: ${{ inputs.release_version }}.RELEASE -# secrets: inherit + create-github-release: + uses: ./.github/workflows/create-gh-release.yml + with: + version: ${{ inputs.release_version }}.RELEASE + secrets: inherit # announce-release: # needs: [ aggregate-ls-extension-update-site, aggregate-distro-update-site, create-github-release ] diff --git a/.github/workflows/release-eclipse-distro-build.yml b/.github/workflows/release-eclipse-distro-build.yml index f7953d46b5..7732eef7e2 100644 --- a/.github/workflows/release-eclipse-distro-build.yml +++ b/.github/workflows/release-eclipse-distro-build.yml @@ -14,30 +14,29 @@ on: jobs: - e429-distro: + e430-distro: uses: ./.github/workflows/gh-hosted-eclipse-distro-build.yml with: - eclipse_profile: 'e429' + eclipse_profile: 'e430' build_type: 'release' p2-qualifier: 'RELEASE' sts4-language-servers-version: ${{ inputs.sts4-language-servers-version }} secrets: inherit - e430-distro: + e431-distro: uses: ./.github/workflows/gh-hosted-eclipse-distro-build.yml with: - eclipse_profile: 'e430' + eclipse_profile: 'e431' build_type: 'release' p2-qualifier: 'RELEASE' sts4-language-servers-version: ${{ inputs.sts4-language-servers-version }} secrets: inherit - e431-distro: + e432-distro: uses: ./.github/workflows/gh-hosted-eclipse-distro-build.yml with: - eclipse_profile: 'e431' + eclipse_profile: 'e432' build_type: 'release' p2-qualifier: 'RELEASE' sts4-language-servers-version: ${{ inputs.sts4-language-servers-version }} secrets: inherit - diff --git a/.github/workflows/snapshot-e429-eclipse-distro-build.yml b/.github/workflows/snapshot-e432-eclipse-distro-build.yml similarity index 76% rename from .github/workflows/snapshot-e429-eclipse-distro-build.yml rename to .github/workflows/snapshot-e432-eclipse-distro-build.yml index fea313f83f..8d8483ec15 100644 --- a/.github/workflows/snapshot-e429-eclipse-distro-build.yml +++ b/.github/workflows/snapshot-e432-eclipse-distro-build.yml @@ -1,7 +1,7 @@ -name: Snapshot - 4.29 Eclipse STS Distribution Build +name: Snapshot - 4.32 Eclipse STS Distribution Build concurrency: - group: e429-snapshot + group: e432-snapshot cancel-in-progress: true on: @@ -13,10 +13,10 @@ on: # workflow_dispatch: jobs: - e429-distro: + e432-distro: if: ${{ github.event.workflow_run.conclusion == 'success' }} uses: ./.github/workflows/gh-hosted-eclipse-distro-build.yml with: - eclipse_profile: 'e429' + eclipse_profile: 'e432' build_type: 'snapshot' secrets: inherit \ No newline at end of file diff --git a/.github/workflows/snapshot-eclipse-ls-extensions-build.yml b/.github/workflows/snapshot-eclipse-ls-extensions-build.yml index f8b8a879df..2ed075b31d 100644 --- a/.github/workflows/snapshot-eclipse-ls-extensions-build.yml +++ b/.github/workflows/snapshot-eclipse-ls-extensions-build.yml @@ -14,6 +14,6 @@ jobs: eclipse-ls-extensions: uses: ./.github/workflows/eclipse-ls-extensions-build.yml with: - eclipse_profile: 'e429' + eclipse_profile: 'e430' build_type: 'snapshot' secrets: inherit diff --git a/concourse/pipeline.yml b/concourse/pipeline.yml index 046579e5e5..af2e0955f1 100644 --- a/concourse/pipeline.yml +++ b/concourse/pipeline.yml @@ -268,19 +268,6 @@ resources: # secret_access_key: ((s3_prod_secretkey)) # region_name: ((s3_prod_region)) # regexp: release/STS4/fatjars/spring-boot-language-server-(.*).jar -- name: vscode-snapshot-website - type: s3-multi - icon: content-save-outline - source: - bucket: ((s3_prod_bucket)) - access_key_id: ((s3_svc_accesskey)) - secret_access_key: ((s3_svc_secretkey)) - aws_role_arn: arn:aws:iam::((s3_svc_account_id)):role/((s3_svc_user)) - region_name: ((s3_region)) - path: snapshot/STS4/vscode-extensions - change_dir_to: website - options: - - "--acl public-read" - name: vscode-snapshot-website-akamai type: s3-multi icon: content-save-outline @@ -1139,7 +1126,6 @@ jobs: - task: build-website file: sts4/concourse/tasks/build-vscode-website.yml - in_parallel: - - put: vscode-snapshot-website - put: vscode-snapshot-website-akamai # - name: build-fatjars # plan: diff --git a/eclipse-distribution/common/html/nightly-distributions.html b/eclipse-distribution/common/html/nightly-distributions.html index cc27a57d20..a0f449e111 100644 --- a/eclipse-distribution/common/html/nightly-distributions.html +++ b/eclipse-distribution/common/html/nightly-distributions.html @@ -23,9 +23,9 @@

Eclipse p2 repositories

STS4 Distribution:

@@ -40,7 +40,13 @@

Eclipse p2 repositories

Eclipse-based Distribution Builds

-

Spring Tool Suite 4 - based on Eclipse 2024-03 Milestone Builds (4.31.0)

+

Spring Tool Suite 4 - based on Eclipse 2023-06 Milestone Builds (4.32.0)

+
+ + +

Spring Tool Suite 4 - based on Eclipse 2024-03 Release (4.31.0)

-

Spring Tool Suite 4 - based on Eclipse 2023-09 Release (4.29.0)

-
- -

Spring Tools 4 - Visual Studio Code Extensions

diff --git a/eclipse-distribution/org.springframework.boot.ide.branding.feature/feature.xml b/eclipse-distribution/org.springframework.boot.ide.branding.feature/feature.xml index a444008b70..07d3601be7 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding.feature/feature.xml +++ b/eclipse-distribution/org.springframework.boot.ide.branding.feature/feature.xml @@ -2,7 +2,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/META-INF/MANIFEST.MF b/eclipse-distribution/org.springframework.boot.ide.branding/META-INF/MANIFEST.MF index e36fb92aa0..049eb11ee3 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding/META-INF/MANIFEST.MF +++ b/eclipse-distribution/org.springframework.boot.ide.branding/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.springframework.boot.ide.branding;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: %providerName Require-Bundle: org.eclipse.ui, org.eclipse.equinox.p2.ui, diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/pom.xml b/eclipse-distribution/org.springframework.boot.ide.branding/pom.xml index 649a45eb39..aedc3128ce 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding/pom.xml +++ b/eclipse-distribution/org.springframework.boot.ide.branding/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e430/org.springframework.boot.ide.product b/eclipse-distribution/org.springframework.boot.ide.product.e430/org.springframework.boot.ide.product index cf34a943b4..9a6709aeae 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e430/org.springframework.boot.ide.product +++ b/eclipse-distribution/org.springframework.boot.ide.product.e430/org.springframework.boot.ide.product @@ -1,6 +1,6 @@ - + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e430/pom.xml b/eclipse-distribution/org.springframework.boot.ide.product.e430/pom.xml index 96c6397c67..6ecce1823d 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e430/pom.xml +++ b/eclipse-distribution/org.springframework.boot.ide.product.e430/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml @@ -190,7 +190,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs @@ -211,7 +211,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e431/org.springframework.boot.ide.product b/eclipse-distribution/org.springframework.boot.ide.product.e431/org.springframework.boot.ide.product index cf34a943b4..9a6709aeae 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e431/org.springframework.boot.ide.product +++ b/eclipse-distribution/org.springframework.boot.ide.product.e431/org.springframework.boot.ide.product @@ -1,6 +1,6 @@ - + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e431/pom.xml b/eclipse-distribution/org.springframework.boot.ide.product.e431/pom.xml index 96c6397c67..6ecce1823d 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e431/pom.xml +++ b/eclipse-distribution/org.springframework.boot.ide.product.e431/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml @@ -190,7 +190,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs @@ -211,7 +211,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e429/category.xml b/eclipse-distribution/org.springframework.boot.ide.product.e432/category.xml similarity index 98% rename from eclipse-distribution/org.springframework.boot.ide.product.e429/category.xml rename to eclipse-distribution/org.springframework.boot.ide.product.e432/category.xml index 3bbccead80..14fd547bb2 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e429/category.xml +++ b/eclipse-distribution/org.springframework.boot.ide.product.e432/category.xml @@ -131,7 +131,7 @@ - + @@ -140,6 +140,7 @@ + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e429/org.springframework.boot.ide.product b/eclipse-distribution/org.springframework.boot.ide.product.e432/org.springframework.boot.ide.product similarity index 97% rename from eclipse-distribution/org.springframework.boot.ide.product.e429/org.springframework.boot.ide.product rename to eclipse-distribution/org.springframework.boot.ide.product.e432/org.springframework.boot.ide.product index cf34a943b4..629deca7de 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e429/org.springframework.boot.ide.product +++ b/eclipse-distribution/org.springframework.boot.ide.product.e432/org.springframework.boot.ide.product @@ -1,6 +1,6 @@ - + @@ -69,7 +69,7 @@ - + diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e429/p2.inf b/eclipse-distribution/org.springframework.boot.ide.product.e432/p2.inf similarity index 100% rename from eclipse-distribution/org.springframework.boot.ide.product.e429/p2.inf rename to eclipse-distribution/org.springframework.boot.ide.product.e432/p2.inf diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e429/pom.xml b/eclipse-distribution/org.springframework.boot.ide.product.e432/pom.xml similarity index 98% rename from eclipse-distribution/org.springframework.boot.ide.product.e429/pom.xml rename to eclipse-distribution/org.springframework.boot.ide.product.e432/pom.xml index 0003dc929f..db77a7d465 100644 --- a/eclipse-distribution/org.springframework.boot.ide.product.e429/pom.xml +++ b/eclipse-distribution/org.springframework.boot.ide.product.e432/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml @@ -15,7 +15,7 @@ eclipse-repository - https://download.eclipse.org/justj/jres/17/updates/release/latest/ + https://download.eclipse.org/justj/jres/21/updates/release/latest/ @@ -97,6 +97,7 @@ + org.eclipse.tycho.extras tycho-eclipserun-plugin @@ -189,7 +190,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/x86_64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs @@ -210,7 +211,7 @@ org.eclipse.equinox.p2.director -nosplash -destination - ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app + ${project.build.directory}/products/org.springframework.boot.ide.branding.sts4/macosx/cocoa/aarch64/SpringToolSuite4.app/Contents/Eclipse -repository ${justj.repository} -installIUs @@ -339,6 +340,7 @@ run + generate-s3-upload-info verify @@ -383,6 +385,7 @@ run + diff --git a/eclipse-distribution/pom.xml b/eclipse-distribution/pom.xml index 054402487b..2eb1740c38 100644 --- a/eclipse-distribution/pom.xml +++ b/eclipse-distribution/pom.xml @@ -4,7 +4,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT pom @@ -130,31 +130,38 @@ - e429 + e430 - e4.29.0 - e4.29 - 2023-09 - 2023-09 (4.29) - 2023-09 - 4.29 - e429 + e4.30.0 + e4.30 + 2023-12 + 2023-12 (4.30) + 2023-12 + 4.30 + e430 - 2023-09 + 2023-12 p2 - https://download.eclipse.org/releases/2023-09/ + https://download.eclipse.org/releases/2023-12/ orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-09 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12 - + + buildship + p2 + + https://download.eclipse.org/buildship/updates/latest + + m2e p2 https://download.eclipse.org/technology/m2e/releases/latest/ + latest-m2e-wtp-release @@ -194,13 +201,13 @@ lsp4e p2 - https://download.eclipse.org/lsp4e/releases/0.24.1/ + https://download.eclipse.org/lsp4e/releases/0.25.0/ tm4e-snapshots p2 - https://download.eclipse.org/tm4e/releases/0.8.1/ + https://download.eclipse.org/tm4e/releases/latest/ - org.springframework.boot.ide.product.e429 + org.springframework.boot.ide.product.e430 - e430 + e431 - e4.30.0 - e4.30 - 2023-12 - 2023-12 (4.30) - 2023-12 - 4.30 - e430 + e4.31.0 + e4.31 + 2024-03 + 2024-03 (4.31) + 2024-03 + 4.31 + e431 2023-12 p2 - https://download.eclipse.org/releases/2023-12/ + https://download.eclipse.org/releases/2024-03/ orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-03 - buildship + buildship-snapshots p2 https://download.eclipse.org/buildship/updates/latest - + m2e p2 https://download.eclipse.org/technology/m2e/releases/latest/ @@ -294,7 +301,7 @@ lsp4e p2 - + https://download.eclipse.org/lsp4e/snapshots/ @@ -317,32 +324,39 @@ ../eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64 ../eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64 --> - org.springframework.boot.ide.product.e430 + org.springframework.boot.ide.product.e431 - e431 + e432 - e4.31.0 - e4.31 - 2024-03 - 2024-03 (4.31) - 2024-03 - 4.31 - e431 + e4.32.0 + e4.32 + 2024-06 + 2024-06 (4.32) + 2024-06 + 4.32 + e432 2023-12 p2 - https://download.eclipse.org/staging/2024-03/ + https://download.eclipse.org/staging/2024-06/ + + + 2023-12-i-builds + p2 + https://download.eclipse.org/eclipse/updates/4.32-I-builds/ + + orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-03 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-06 buildship-snapshots @@ -394,8 +408,8 @@ lsp4e p2 - - https://download.eclipse.org/lsp4e/snapshots/ + + https://download.eclipse.org/lsp4e/snapshots/ tm4e-snapshots @@ -417,7 +431,7 @@ ../eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64 ../eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64 --> - org.springframework.boot.ide.product.e431 + org.springframework.boot.ide.product.e432 diff --git a/eclipse-extensions/org.springframework.boot.ide.main.feature/feature.xml b/eclipse-extensions/org.springframework.boot.ide.main.feature/feature.xml index 83977431fe..8361608477 100644 --- a/eclipse-extensions/org.springframework.boot.ide.main.feature/feature.xml +++ b/eclipse-extensions/org.springframework.boot.ide.main.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-extensions/org.springframework.boot.ide.main.feature/pom.xml b/eclipse-extensions/org.springframework.boot.ide.main.feature/pom.xml index a6ca5e6fa0..a34d411595 100644 --- a/eclipse-extensions/org.springframework.boot.ide.main.feature/pom.xml +++ b/eclipse-extensions/org.springframework.boot.ide.main.feature/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/META-INF/MANIFEST.MF index 8860bde757..61109f6a6d 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Live Beans Tree Bundle-SymbolicName: org.springframework.ide.eclipse.beans.ui.live;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Export-Package: org.springframework.ide.eclipse.beans.ui.live, org.springframework.ide.eclipse.beans.ui.live.actions, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/pom.xml index 7554878239..ed36c873f8 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.beans.ui.live/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/META-INF/MANIFEST.MF index 328e2de6ca..8ebb5273cc 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.springframework.ide.eclipse.boot.dash.azure;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware, Inc Bundle-Name: Spring Boot Dash CF Support Require-Bundle: org.eclipse.ui, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/pom.xml index a92cd58a77..37cc6143ea 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.azure/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/META-INF/MANIFEST.MF index 0baf2e42af..f4807315c0 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: org.springframework.ide.eclipse.boot.dash.docker Bundle-SymbolicName: org.springframework.ide.eclipse.boot.dash.docker;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.boot.dash.docker Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.springframework.ide.eclipse.boot.dash, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/pom.xml index 272adb4305..bf2a355331 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/feature.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/feature.xml index 60d8ff54cb..8e77653d41 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/feature.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/feature.xml @@ -14,7 +14,7 @@ diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/pom.xml index 87ab2c80b3..c6b106036c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.feature/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/META-INF/MANIFEST.MF index da7fcb0df6..68c0e8c42f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Test Bundle-SymbolicName: org.springframework.ide.eclipse.boot.dash.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware, Inc Require-Bundle: org.junit, org.eclipse.core.resources, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/pom.xml index 9a5c5103a3..73a220aa4f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/META-INF/MANIFEST.MF index 526def1cb9..eaadd2969d 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Boot Dashboard integration with Xterm view Bundle-SymbolicName: org.springframework.ide.eclipse.boot.dash.xterm;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.boot.dash.xterm Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.core.runtime, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/pom.xml index 4b27e6ec76..a4eb630d8f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.xterm/pom.xml @@ -6,7 +6,7 @@ org.springframework.ide.eclipse org.springframework.ide.eclipse.parent - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../pom.xml eclipse-plugin diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/META-INF/MANIFEST.MF index c1de2f626f..1b074c55b4 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Spring Boot Dashboard View Bundle-SymbolicName: org.springframework.ide.eclipse.boot.dash;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springframework.ide.eclipse.boot.dash.BootDashActivator Bundle-Vendor: VMware, Inc Require-Bundle: org.eclipse.ui, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/pom.xml index c421a7e42b..64a03caa05 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java index 5ee35b2b4f..f612b07020 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Pivotal Software, Inc. + * Copyright (c) 2019, 2024 Pivotal Software, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,11 +16,8 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import org.eclipse.lsp4e.LanguageServers; -import org.eclipse.lsp4e.LanguageServers.LanguageServerProjectExecutor; -import org.eclipse.lsp4e.LanguageServersRegistry; -import org.eclipse.lsp4j.ExecuteCommandOptions; import org.eclipse.lsp4j.ExecuteCommandParams; +import org.springframework.ide.eclipse.boot.launch.BootLsCommandUtils; import com.google.common.collect.ImmutableList; @@ -35,7 +32,7 @@ public final class DefaultLiveProcessCommandExecutor implements LiveProcessComma @SuppressWarnings("unchecked") @Override public Flux listCommands() { - List>> futures = getLanguageServers().computeAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( + List>> futures = BootLsCommandUtils.getLanguageServers(CMD_LIST_PROCESSES).computeAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( CMD_LIST_PROCESSES, ImmutableList.of() )).thenApply(o -> { @@ -54,21 +51,10 @@ public Flux listCommands() { @Override public Mono executeCommand(CommandInfo cmd) { - return Mono.fromFuture(getLanguageServers().collectAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( + return Mono.fromFuture(BootLsCommandUtils.getLanguageServers(cmd.command).collectAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( cmd.command, ImmutableList.of(cmd.info) - ))).thenAccept(null)); + ))).thenAccept(l -> {})); } - private LanguageServerProjectExecutor getLanguageServers() { - return LanguageServers.forProject(null).withFilter(cap -> { - ExecuteCommandOptions commandCap = cap.getExecuteCommandProvider(); - if (commandCap!=null) { - List supportedCommands = commandCap.getCommands(); - return supportedCommands!=null && supportedCommands.contains(CMD_LIST_PROCESSES); - } - return false; - }).withPreferredServer(LanguageServersRegistry.getInstance() - .getDefinition("org.eclipse.languageserver.languages.springboot")); - } } \ No newline at end of file diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/META-INF/MANIFEST.MF index 1cb6388a15..ad782d44c2 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/META-INF/MANIFEST.MF @@ -2,7 +2,9 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Boot Launch Tests Bundle-SymbolicName: org.springframework.ide.eclipse.boot.launch.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier +Import-Package: org.apache.commons.io, + org.apache.commons.lang3 Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.junit, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/pom.xml index d14108fa70..6637d1bb2d 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch.test/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.classpath b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.classpath index 43b986286a..8d8612144f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.classpath +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.classpath @@ -1,6 +1,6 @@ - + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.settings/org.eclipse.jdt.core.prefs b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.settings/org.eclipse.jdt.core.prefs index 9f6ece88bd..59fe89dce4 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.settings/org.eclipse.jdt.core.prefs +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,15 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=17 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/META-INF/MANIFEST.MF index 3ef31d1665..a3f6415594 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Boot Launch Bundle-SymbolicName: org.springframework.ide.eclipse.boot.launch;singleton:=true Bundle-Vendor: VMware, Inc -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.core.resources, @@ -29,7 +29,11 @@ Require-Bundle: org.eclipse.ui, org.eclipse.jface.text, org.eclipse.jdt.ui, org.eclipse.ui.genericeditor, - org.eclipse.ui.ide + org.eclipse.ui.ide, + org.eclipse.lsp4e, + org.eclipse.lsp4j, + com.google.gson, + org.eclipse.jdt.junit.core Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Export-Package: org.springframework.ide.eclipse.boot.launch, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/plugin.xml index ed7ec551c2..c09175773f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/plugin.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/plugin.xml @@ -221,6 +221,11 @@ id="org.springframework.ide.eclipse.boot.commands.editStartersCommand" name="Edit Starters"> + + org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLaunchActivator.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLaunchActivator.java index f17c71a7bf..cd40c5ecd9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLaunchActivator.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLaunchActivator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Pivotal, Inc. + * Copyright (c) 2015, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; @@ -37,7 +38,8 @@ public BootLaunchActivator() { @Override public void start(BundleContext context) throws Exception { super.start(context); - workspaceListener = new BootLaunchConfDeleter(ResourcesPlugin.getWorkspace(), DebugPlugin.getDefault().getLaunchManager()); + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + workspaceListener = new BootLaunchConfDeleter(ResourcesPlugin.getWorkspace(), launchManager); instance = this; IPreferenceStore myStore = instance.getPreferenceStore(); @@ -45,6 +47,8 @@ public void start(BundleContext context) throws Exception { setPreference("org.eclipse.jdt.debug.ui", "org.eclipse.jdt.debug.ui.prompt_unable_to_install_breakpoint", false); myStore.setValue("cglib.breakpoint.warning.disabled", true); } + + TestJarSupport.start(); } private void setPreference(String plugin, String key, boolean value) { @@ -70,6 +74,7 @@ public void stop(BundleContext context) throws Exception { if (workspaceListener!=null) { workspaceListener.dispose(); } + TestJarSupport.stop(); super.stop(context); } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLsCommandUtils.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLsCommandUtils.java new file mode 100644 index 0000000000..e51285df85 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/BootLsCommandUtils.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.launch; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4e.LanguageServers; +import org.eclipse.lsp4e.LanguageServers.LanguageServerProjectExecutor; +import org.eclipse.lsp4e.LanguageServersRegistry; +import org.eclipse.lsp4j.ExecuteCommandOptions; +import org.eclipse.lsp4j.ExecuteCommandParams; + +import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +@SuppressWarnings("restriction") +public class BootLsCommandUtils { + + private static Gson GSON = new Gson(); + + public static LanguageServerProjectExecutor getLanguageServers(String command) { + return LanguageServers.forProject(null).withFilter(cap -> { + ExecuteCommandOptions commandCap = cap.getExecuteCommandProvider(); + if (commandCap!=null) { + List supportedCommands = commandCap.getCommands(); + return supportedCommands!=null && supportedCommands.contains(command); + } + return false; + }).withPreferredServer(LanguageServersRegistry.getInstance() + .getDefinition("org.eclipse.languageserver.languages.springboot")); + } + + public static CompletableFuture> executeCommand(TypeToken resType, String cmd, Object... params) { + return getLanguageServers(cmd).computeFirst(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( + cmd, + ImmutableList.of(params) + ))).thenApply(o -> o.map(v -> GSON.fromJson(GSON.toJsonTree(v), resType))); + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarLaunchListener.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarLaunchListener.java new file mode 100644 index 0000000000..989850c9bc --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarLaunchListener.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.launch; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchDelegate; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.ILaunchesListener2; +import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; +import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate; +import org.springsource.ide.eclipse.commons.livexp.util.Log; + +import com.google.gson.reflect.TypeToken; + +@SuppressWarnings("restriction") +class TestJarLaunchListener implements ILaunchesListener2 { + + private static final Pattern TESTJAR_PATTERN = Pattern.compile("^spring-boot-testjars-\\d+\\.\\d+\\.\\d+(.*)?.jar$"); + + private static final String TESTJAR_ARTIFACTS = "spring.boot.test-jar-artifacts"; + + public record ExecutableProject(String name, String uri, String gav, String mainClass, Collection classpath) {} + + public void launchRemoved(ILaunch launch) { + clearTestJarWorkspaceProjectFiles(launch.getLaunchConfiguration()); + } + + private void clearTestJarWorkspaceProjectFiles(ILaunchConfiguration configuration) { + try { + if (JUnitLaunchConfigurationConstants.ID_JUNIT_APPLICATION.equals(configuration.getType().getIdentifier())) { + Map oldTestJarArtifacts = configuration.getAttribute(TESTJAR_ARTIFACTS, Collections.emptyMap()); + Map env = new HashMap<>(configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, Collections.emptyMap())); + for (Map.Entry testJarArtifactEnvEntry : oldTestJarArtifacts.entrySet()) { + env.remove(testJarArtifactEnvEntry.getKey()); + try { + Files.deleteIfExists(Paths.get(testJarArtifactEnvEntry.getValue())); + } catch (IOException e) { + Log.log(e); + } + } + ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); + wc.removeAttribute(TESTJAR_ARTIFACTS); + if (env.isEmpty()) { + wc.removeAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES); + } else { + wc.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, env); + } + wc.doSave(); + } + } catch (CoreException e) { + Log.log(e); + } + } + + private void setupTestJarWorkspaceProjectFiles(ILaunchConfiguration configuration, Map testJarArtifactsEnvMap) { + try { + Map originalEnv = new HashMap<>(configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, Collections.emptyMap())); + Map oldTestJarArtifacts = configuration.getAttribute(TESTJAR_ARTIFACTS, Collections.emptyMap()); + for (Map.Entry envEntry : oldTestJarArtifacts.entrySet()) { + try { + Files.deleteIfExists(Paths.get(envEntry.getValue())); + } catch (IOException e) { + Log.log(e); + } + originalEnv.remove(envEntry.getKey()); + } + for (String envVar : originalEnv.keySet()) { + testJarArtifactsEnvMap.remove(envVar); + } + originalEnv.putAll(testJarArtifactsEnvMap); + ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); + wc.setAttribute(TESTJAR_ARTIFACTS, testJarArtifactsEnvMap); + wc.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, originalEnv); + wc.doSave(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + + public void launchAdded(ILaunch launch) { + try { + ILaunchConfiguration configuration = launch.getLaunchConfiguration(); + if (JUnitLaunchConfigurationConstants.ID_JUNIT_APPLICATION.equals(configuration.getType().getIdentifier())) { + ILaunchDelegate[] delegates = configuration.getType().getDelegates(Set.of(launch.getLaunchMode())); + if (delegates.length > 0) { + JUnitLaunchConfigurationDelegate delegate = (JUnitLaunchConfigurationDelegate) delegates[0].getDelegate(); + String[] classpath = delegate.getClasspathAndModulepath(configuration)[0]; + if (isTestJarsOnClasspath(classpath)) { + try { + getTestJarArtifactsMap() + .thenAccept(testJarArtifactsEnvMap -> setupTestJarWorkspaceProjectFiles(configuration, testJarArtifactsEnvMap)) + .get(3000000, TimeUnit.SECONDS); + } catch (Exception e) { + Log.log(e); + } + } + } + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + + private static String createTestJarArtifactEnvKey(String gav) { + return "TESTJARS_ARTIFACT_%s".formatted(gav.replace(":", "_")); + } + + private static boolean isTestJarsOnClasspath(String[] classpath) { + for (String cpe : classpath) { + Path p = Paths.get(cpe); + if (Files.isRegularFile(p) && TESTJAR_PATTERN.matcher(p.getFileName().toString()).matches()) { + return true; + } + } + return false; + } + + private CompletableFuture> getTestJarArtifactsMap() { + try { + Optional opt = BootLsCommandUtils.executeCommand(TypeToken.getParameterized(List.class, ExecutableProject.class), "sts/spring-boot/executableBootProjects").get(3, TimeUnit.SECONDS); + if (opt.isPresent() && opt.get() instanceof List projects) { + Map gavToFile = new ConcurrentHashMap<>(); + CompletableFuture[] futures = projects.stream().map(ExecutableProject.class::cast).map(p -> CompletableFuture.runAsync(() -> { + try { + Path file = Files.createTempFile("%s_".formatted(p.gav().replace(":", "_")), UUID.randomUUID().toString()); + Files.write(file, List.of( + "# the main class to invoke", + "main=%s".formatted(p.mainClass()), + "# the classpath to use delimited by the OS specific delimiters", + "classpath=%s".formatted(String.join(File.pathSeparator, p.classpath()) + ))); + gavToFile.put(createTestJarArtifactEnvKey(p.gav()), file.toFile().toString()); + } catch (IOException e) { + Log.log(e); + } + })).toArray(CompletableFuture[]::new); + return CompletableFuture.allOf(futures).thenApply(v -> gavToFile); + } + } catch (InterruptedException | ExecutionException | TimeoutException e) { + Log.log(e); + } + + return CompletableFuture.completedFuture(Collections.emptyMap()); + } + + @Override + public void launchesRemoved(ILaunch[] launches) { + // nothing to do + } + + @Override + public void launchesAdded(ILaunch[] launches) { + for (ILaunch l : launches) { + launchAdded(l); + } + } + + @Override + public void launchesChanged(ILaunch[] launches) { + // nothing to do + } + + @Override + public void launchesTerminated(ILaunch[] launches) { + for (ILaunch l : launches) { + clearTestJarWorkspaceProjectFiles(l.getLaunchConfiguration()); + } + } + + void clearTestJarArtifactEnvKeyFromLaunches(ILaunchManager launchManager) { + for (ILaunch l : launchManager.getLaunches()) { + if (!l.isTerminated() && l.getLaunchConfiguration() != null) { + clearTestJarWorkspaceProjectFiles(l.getLaunchConfiguration()); + } + } + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarSupport.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarSupport.java new file mode 100644 index 0000000000..1b7831da6e --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/TestJarSupport.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.launch; + +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.springframework.ide.eclipse.boot.core.BootActivator; +import org.springframework.ide.eclipse.boot.core.BootPreferences; + +public class TestJarSupport { + + private static final TestJarLaunchListener LAUNCHES_LISTENER = new TestJarLaunchListener(); + + private static final IPropertyChangeListener PREFERENCE_LISTENER = propertyChange -> { + if (BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT.equals(propertyChange.getProperty())) { + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + if (BootActivator.getDefault().getPreferenceStore().getBoolean(BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT)) { + // TestJars support ON + launchManager.addLaunchListener(LAUNCHES_LISTENER); + } else { + // TestJars support OFF + launchManager.removeLaunchListener(LAUNCHES_LISTENER); + LAUNCHES_LISTENER.clearTestJarArtifactEnvKeyFromLaunches(launchManager); + } + } + }; + + public static void start() { + if (BootActivator.getDefault().getPreferenceStore().getBoolean(BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT)) { + BootActivator.getDefault().getPreferenceStore().addPropertyChangeListener(PREFERENCE_LISTENER); + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + launchManager.addLaunchListener(LAUNCHES_LISTENER); + } + + } + + public static void stop() { + if (BootActivator.getDefault().getPreferenceStore().getBoolean(BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT)) { + BootActivator.getDefault().getPreferenceStore().removePropertyChangeListener(PREFERENCE_LISTENER); + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + launchManager.removeLaunchListener(LAUNCHES_LISTENER); + LAUNCHES_LISTENER.clearTestJarArtifactEnvKeyFromLaunches(launchManager); + } + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/META-INF/MANIFEST.MF index ccbf795971..b4ff7573e9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Test Fragment-Host: org.springframework.ide.eclipse.boot.refactoring;bundle-version="3.7.3" Bundle-SymbolicName: org.springframework.ide.eclipse.boot.refactoring.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware, Inc Require-Bundle: org.eclipse.core.runtime, org.junit, @@ -13,11 +13,9 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.jdt.core, org.springsource.ide.eclipse.commons.livexp, org.springsource.ide.eclipse.commons.frameworks.core, - org.springsource.ide.eclipse.commons.frameworks.test.util, org.springframework.ide.eclipse.boot.launch, org.eclipse.jdt.launching, org.eclipse.debug.ui, - org.mockito, org.springframework.ide.eclipse.boot, org.eclipse.core.expressions, org.springframework.ide.eclipse.boot.test, @@ -26,7 +24,6 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.equinox.security, org.reactivestreams.reactive-streams;bundle-version="1.0.2", io.projectreactor.reactor-core;bundle-version="[3.3.1,3.3.2)", - javax.ws.rs;bundle-version="2.0.1", org.eclipse.osgi, org.hamcrest.library Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/pom.xml index 0a17eba60f..ab327c3fe2 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlTest.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlRefactoringTest.java similarity index 99% rename from eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlTest.java rename to eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlRefactoringTest.java index e2ec85e27c..ca412e565f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlTest.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertPropertiesToYamlRefactoringTest.java @@ -38,7 +38,7 @@ import org.springsource.ide.eclipse.commons.frameworks.core.util.IOUtil; import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil; -public class ConvertPropertiesToYamlTest { +public class ConvertPropertiesToYamlRefactoringTest { public interface Checker { void check(T it) throws Exception; diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertYamlToPropertiesRefactoringTest.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertYamlToPropertiesRefactoringTest.java new file mode 100644 index 0000000000..582039e74c --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring.test/src/org/springframework/ide/eclipse/boot/refactoring/test/ConvertYamlToPropertiesRefactoringTest.java @@ -0,0 +1,315 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.refactoring.test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.assertContains; +import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.createFile; + +import java.util.concurrent.CompletableFuture; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.PerformChangeOperation; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; +import org.junit.Before; +import org.junit.Test; +import org.springframework.ide.eclipse.boot.refactoring.ConvertYamlToPropertiesRefactoring; +import org.springframework.ide.eclipse.boot.refactoring.test.ConvertPropertiesToYamlRefactoringTest.Checker; +import org.springframework.ide.eclipse.boot.test.BootProjectTestHarness; +import org.springsource.ide.eclipse.commons.frameworks.core.util.IOUtil; +import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil; + +public class ConvertYamlToPropertiesRefactoringTest { + + BootProjectTestHarness projects = new BootProjectTestHarness(getWorkspace()); + + protected IWorkspace getWorkspace() { + return ResourcesPlugin.getWorkspace(); + } + + @Before public void setup() throws Exception { + StsTestUtil.deleteAllProjects(); + } + + private void do_conversionTest(String input, String expectedOutput) throws Exception { + do_conversionTest(input, expectedOutput, (status) -> { + assertEquals(RefactoringStatus.OK, status.getSeverity()); + }); + } + + private void do_conversionTest(String input, String expectedOutput, Checker statusChecker) throws Exception { + IProject project = projects.createProject("conversionTestProject"); + IFile yamlFile = createFile(project, "application.yml", input); + IFile propsFile = project.getFile("application.properties"); + if (propsFile.exists()) { + propsFile.delete(true, new NullProgressMonitor()); + } + + assertTrue(yamlFile.exists()); + assertFalse(propsFile.exists()); + + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(yamlFile); + statusChecker.check(refactoring.checkAllConditions(new NullProgressMonitor())); + perform(refactoring); + + assertFalse(yamlFile.exists()); + assertTrue(propsFile.exists()); + + assertEquals(expectedOutput, IOUtil.toString(propsFile.getContents())); + } + + private void assertFile(IProject project, String path, String expectedContents) throws Exception { + IFile file = project.getFile(path); + assertTrue(file.getFullPath().toString(), file.exists()); + assertEquals(expectedContents, IOUtil.toString(file.getContents())); + } + + private void perform(ConvertYamlToPropertiesRefactoring refactoring) throws Exception { + Change change = refactoring.createChange(new NullProgressMonitor()); + IWorkspace workspace = getWorkspace(); + CompletableFuture result = new CompletableFuture<>(); + Job job = new Job(refactoring.getName()) { + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + workspace.run(new PerformChangeOperation(change), monitor); + result.complete(null); + } catch (Throwable e) { + result.completeExceptionally(e); + } + return Status.OK_STATUS; + } + }; + job.setRule(workspace.getRuleFactory().buildRule()); + job.schedule(); + result.get(); + } + + private ConvertYamlToPropertiesRefactoring do_hasComments_test(IProject project, String comment) throws Exception { + IFile yamlFile = createFile(project, "src/main/resources/application.yml", + "some:\n property: somevalue\n"+ + comment +"\n" + + "other:\n property: othervalue" + ); + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(yamlFile); + assertOkStatus(refactoring.checkInitialConditions(new NullProgressMonitor())); + assertStatus(refactoring.checkFinalConditions(new NullProgressMonitor()), RefactoringStatus.WARNING, "has comments, which will be lost"); + return refactoring; + } + + private ConvertYamlToPropertiesRefactoring do_hasInlineComments_test(IProject project, String comment) throws Exception { + IFile yamlFile = createFile(project, "src/main/resources/application.yml", + "some:\n property: somevalue\n"+ + "foo: bar " + comment +"\n" + + "other:\n property: othervalue" + ); + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(yamlFile); + assertOkStatus(refactoring.checkInitialConditions(new NullProgressMonitor())); + assertStatus(refactoring.checkFinalConditions(new NullProgressMonitor()), RefactoringStatus.WARNING, "has comments, which will be lost"); + return refactoring; + } + + private void assertOkStatus(RefactoringStatus s) { + assertEquals(RefactoringStatus.OK, s.getSeverity()); + } + + private void assertStatus(RefactoringStatus status, int expectedSeverity, String expectedMessageFragment) { + assertEquals(expectedSeverity, status.getSeverity()); + StringBuilder allMessages = new StringBuilder(); + for (RefactoringStatusEntry entry : status.getEntries()) { + allMessages.append(entry.getMessage()); + allMessages.append("\n-------------\n"); + } + assertContains(expectedMessageFragment, allMessages.toString()); + } + + @Test public void fileIsInTheWay() throws Exception { + IProject project = projects.createBootProject("fileIsInTheWay"); + IFile yamlFile = createFile(project, "src/main/resources/application.yml", "someting: already-in-here"); + IFile propsFile = project.getFile("src/main/resources/application.properties"); + assertTrue(propsFile.exists()); + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(yamlFile); + + RefactoringStatus status = refactoring.checkInitialConditions(new NullProgressMonitor()); + assertStatus(status, RefactoringStatus.FATAL, "'/fileIsInTheWay/src/main/resources/application.properties' already exists"); + } + + @Test public void hasLineComments() throws Exception { + IProject project = projects.createBootProject("hasComments"); + IFile propsFile = project.getFile("src/main/resources/application.properties"); + if (propsFile.exists()) { + propsFile.delete(true, new NullProgressMonitor()); + } + + do_hasComments_test(project, "#comment"); + ConvertYamlToPropertiesRefactoring refactoring = do_hasComments_test(project, " #!comment"); + + perform(refactoring); //Despite the warning, the refactoring should be executable. + assertFalse(project.getFile("src/main/resources/application.yml").exists()); + assertFile(project, "src/main/resources/application.properties", + "some.property=somevalue\n" + + "other.property=othervalue\n" + ); + } + + @Test public void hasInlineComments() throws Exception { + IProject project = projects.createBootProject("hasComments"); + IFile propsFile = project.getFile("src/main/resources/application.properties"); + if (propsFile.exists()) { + propsFile.delete(true, new NullProgressMonitor()); + } + + do_hasInlineComments_test(project, "#comment"); + ConvertYamlToPropertiesRefactoring refactoring = do_hasInlineComments_test(project, " #!comment"); + + perform(refactoring); //Despite the warning, the refactoring should be executable. + assertFalse(project.getFile("src/main/resources/application.yml").exists()); + assertFile(project, "src/main/resources/application.properties", + "some.property=somevalue\n" + + "foo=bar\n" + + "other.property=othervalue\n" + ); + } + + @Test public void almostHasComments() throws Exception { + do_conversionTest( + "my:\n" + + " goodbye: 'See ya # later'\n" + + " hello: Good morning!\n" + , // ==> + "my.goodbye=See ya \\# later\n" + + "my.hello=Good morning\\!\n" + ); + } + + @Test public void conversionWithListItems() throws Exception { + do_conversionTest( + "some:\n" + + " thing:\n" + + " - a: first-a\n" + + " b: first-b\n" + + " - a: second-a\n" + + " b: second-b\n" + , // ==> + "some.thing[0].a=first-a\n" + + "some.thing[0].b=first-b\n" + + "some.thing[1].a=second-a\n" + + "some.thing[1].b=second-b\n" + ); + } + + @Test public void simpleConversion() throws Exception { + do_conversionTest( + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + , // ==> + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + ); + } + + @Test public void emptyFileConversion() throws Exception { + do_conversionTest( + "" + , // ==> + "" + ); + } + + @Test public void unusualName() throws Exception { + IProject project = projects.createProject("unusualName"); + IFile input = createFile(project, "no-extension", + "server:\n port: 6789\n" + ); + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(input); + assertOkStatus(refactoring.checkAllConditions(new NullProgressMonitor())); + perform(refactoring); + assertEquals( + "server.port=6789\n", + IOUtil.toString(project.getFile("no-extension.properties").getContents()) + ); + } + + @Test public void list() throws Exception { + do_conversionTest( + "some:\n" + + " property:\n" + + " - something\n" + + " - something-else\n" + , // ==> + "some.property[0]=something\n" + + "some.property[1]=something-else\n" + ); + } + + @Test public void mapAndSequenceConflict() throws Exception { + do_conversionTest( + "some:\n" + + " property:\n" + + " '0': zero\n" + + " '1': one\n" + + " abc: val1\n" + + " def: val2\n" + , + "some.property.0=zero\n" + + "some.property.1=one\n" + + "some.property.abc=val1\n" + + "some.property.def=val2\n" + ); + } + + @Test public void multipleDocsConversion() throws Exception { + do_conversionTest( + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + + "\n" + + "---\n" + + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + + "\n" + + "---\n" + + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + , // ==> + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + + "#---\n" + + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + + "#---\n" + + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + ); + } + + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.classpath b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.classpath index 43b986286a..8d8612144f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.classpath +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.classpath @@ -1,6 +1,6 @@ - + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.settings/org.eclipse.jdt.core.prefs b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.settings/org.eclipse.jdt.core.prefs index 87b7a7a3a6..9478cb1653 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.settings/org.eclipse.jdt.core.prefs +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/.settings/org.eclipse.jdt.core.prefs @@ -1,13 +1,15 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/META-INF/MANIFEST.MF index 2d47ebb82d..dcc147bd4e 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Localization: plugin Bundle-SymbolicName: org.springframework.ide.eclipse.boot.refactoring;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springframework.ide.eclipse.boot.refactoring.SpringBootRefactoringPlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml index 3ff429fb95..600093450a 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml @@ -10,7 +10,14 @@ id="org.springframework.ide.eclipse.boot.properties.editor.convertPropertiesToYaml" name="Convert .properties to .yaml"> + + + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/pom.xml index a5840629d8..30478e188e 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java index 13a14d42b7..96a70a0f34 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java @@ -24,7 +24,6 @@ import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; import org.eclipse.ui.handlers.HandlerUtil; import org.springsource.ide.eclipse.commons.livexp.util.Log; -import org.eclipse.ltk.core.refactoring.RefactoringContext; public class ConvertPropertiesToYamlHandler extends AbstractHandler { diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesHandler.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesHandler.java new file mode 100644 index 0000000000..52e19471e2 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesHandler.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.refactoring; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.LocationKind; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ltk.ui.refactoring.RefactoringWizard; +import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; +import org.eclipse.ui.handlers.HandlerUtil; +import org.springsource.ide.eclipse.commons.livexp.util.Log; + +public class ConvertYamlToPropertiesHandler extends AbstractHandler { + + private static ITextFileBuffer getDirtyFileBuffer(IFile file) { + ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(file.getFullPath(), LocationKind.IFILE); + if (buffer!=null && buffer.isDirty()) { + return buffer; + } + return null; + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IFile file = getTarget(event); + try { + if (file!=null) { + ITextFileBuffer dirtyBuffer = getDirtyFileBuffer(file); + if (dirtyBuffer!=null) { + dirtyBuffer.commit(null, true); + } + ConvertYamlToPropertiesRefactoring refactoring = new ConvertYamlToPropertiesRefactoring(file); + RefactoringWizard wizard = new RefactoringWizard(refactoring, + RefactoringWizard.DIALOG_BASED_USER_INTERFACE | + RefactoringWizard.CHECK_INITIAL_CONDITIONS_ON_OPEN | + RefactoringWizard.NO_BACK_BUTTON_ON_STATUS_DIALOG + ) { + + @Override + protected void addUserInputPages() { + //no inputs required + } + }; + new RefactoringWizardOpenOperation(wizard).run(HandlerUtil.getActiveShell(event), "Convert '"+file.getName()+"' to .properties"); + } + } catch (Exception e) { + Log.log(e); + } + return null; + } + + private IFile getTarget(ExecutionEvent event) { + ISelection selection = HandlerUtil.getActiveMenuSelection(event); + IStructuredSelection ss = null; + if (selection instanceof IStructuredSelection) { + ss = (IStructuredSelection) selection; + } else { + selection = HandlerUtil.getActiveMenuEditorInput(event); + if (selection instanceof IStructuredSelection) { + ss = (IStructuredSelection) selection; + } + } + if (ss!=null && !ss.isEmpty()) { + return asFile(ss.getFirstElement()); + } + return null; + } + + private IFile asFile(Object selectedElement) { + if (selectedElement instanceof IFile) { + return (IFile) selectedElement; + } + if (selectedElement instanceof IAdaptable) { + return ((IAdaptable) selectedElement).getAdapter(IFile.class); + } + return null; + } +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesRefactoring.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesRefactoring.java new file mode 100644 index 0000000000..8fbde189ac --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertYamlToPropertiesRefactoring.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.refactoring; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; +import java.util.Properties; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.TextFileChange; +import org.eclipse.ltk.core.refactoring.resource.RenameResourceChange; +import org.eclipse.text.edits.ReplaceEdit; +import org.springsource.ide.eclipse.commons.frameworks.core.util.IOUtil; +import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.comments.CommentType; +import org.yaml.snakeyaml.events.CommentEvent; +import org.yaml.snakeyaml.events.Event; +import org.yaml.snakeyaml.events.StreamEndEvent; + +public class ConvertYamlToPropertiesRefactoring extends Refactoring { + + private static final String YAML_EXT = ".yml"; + private static final String PROPERTIES_EXT = ".properties"; + + private IFile propsFile; + private final IFile yamlFile; + private StringBuilder propsContent; + private int inputTextLen; + + public ConvertYamlToPropertiesRefactoring(IFile yamlFile) { + this.yamlFile = yamlFile; + this.propsContent = new StringBuilder(); + } + + @Override + public String getName() { + return "Convert .yaml to .properties"; + } + + @Override + public RefactoringStatus checkInitialConditions(IProgressMonitor pm) + throws CoreException, OperationCanceledException { + if (!yamlFile.isAccessible()) { + return RefactoringStatus.createFatalErrorStatus("The resource '"+yamlFile.getFullPath()+"' is not accessible"); + } + this.propsFile = propsFileFor(yamlFile); + if (propsFile.exists()) { + return RefactoringStatus.createFatalErrorStatus("File '"+propsFile.getFullPath()+"' already exists!"); + } + return new RefactoringStatus(); + } + + private static IFile propsFileFor(IFile yamlFile) { + IContainer container = yamlFile.getParent(); + String name = yamlFile.getName(); + if (name.endsWith(YAML_EXT)) { + name = name.substring(0, name.length()-YAML_EXT.length())+PROPERTIES_EXT; + } else { + name = name + PROPERTIES_EXT; + } + return container.getFile(Path.EMPTY.append(name)); + } + + @Override + public RefactoringStatus checkFinalConditions(IProgressMonitor pm) + throws CoreException, OperationCanceledException { + RefactoringStatus status = new RefactoringStatus(); + String yamlContent = null; + try { + yamlContent = IOUtil.toString(yamlFile.getContents()); + } catch (Exception e) { + status.merge(RefactoringStatus.create(ExceptionUtil.status(e, "Problems reading file: "+yamlFile.getFullPath()))); + return status; + } + + if (hasComments(yamlContent)) { + status.merge(RefactoringStatus.createWarningStatus("The yaml file has comments, which will be lost in the refactoring!")); + } + + for (Object d : new Yaml().loadAll(new StringReader(yamlContent))) { + if (d instanceof Map) { + // Add doc divider if not empty + @SuppressWarnings("unchecked") + Map o = (Map) d; + try { + YamlToPropertiesConverter converter = new YamlToPropertiesConverter(o); + Properties props = converter.getProperties(); + StringWriter write = new StringWriter(); + props.store(write, null); + write.flush(); + write.close(); + if (!propsContent.isEmpty()) { + propsContent.append("#---\n"); + } + // Skip over the date header. Comments are not present but date header is. + if (write.getBuffer().charAt(0) == '#') { + int idx = write.getBuffer().indexOf("\n"); + this.propsContent.append(idx >= 0 && idx < write.getBuffer().length() ? write.getBuffer().substring(idx + 1) : write.getBuffer().toString()); + } else { + this.propsContent.append(write.getBuffer().toString()); + } + status.merge(converter.getStatus()); + } catch (IOException e) { + status.merge(RefactoringStatus.create(ExceptionUtil.status(e, "Problems writing to .properties file: "+propsFile.getFullPath()))); + } + } else if (d == null) { + if (!propsContent.isEmpty()) { + propsContent.append("#---\n"); + } + } + } + return status; + } + + private boolean hasComments(String yamlContent) { + LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setProcessComments(true); + boolean hasComments = false; + for (Event e : new Yaml(loaderOptions).parse(new StringReader(yamlContent))) { + if (e instanceof StreamEndEvent) { + inputTextLen = e.getEndMark().getIndex(); + } + if (!hasComments && e instanceof CommentEvent ce) { + if (ce.getCommentType() == CommentType.BLANK_LINE) { + // document separator + } else { + hasComments = true; + } + } + } + return hasComments; + } + + @Override + public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { + CompositeChange changes = new CompositeChange(getName()); + TextFileChange textChange = new TextFileChange(getName(), yamlFile); + textChange.setEdit(new ReplaceEdit(0, inputTextLen, propsContent.toString())); + changes.add(textChange); + changes.add(new RenameResourceChange(yamlFile.getFullPath(), propsFile.getName())); + changes.initializeValidationData(pm); + return changes; + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/YamlToPropertiesConverter.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/YamlToPropertiesConverter.java new file mode 100644 index 0000000000..2d15a8bd4e --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/YamlToPropertiesConverter.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.refactoring; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public class YamlToPropertiesConverter { + + private final RefactoringStatus status; + + private final Properties properties; + + + public YamlToPropertiesConverter(Map yaml) { + this.status = new RefactoringStatus(); + this.properties = new Properties() { + + private static final long serialVersionUID = 1L; + + private LinkedHashMap delegate = new LinkedHashMap<>(); + + @Override + public synchronized Object put(Object key, Object value) { + delegate.put(key, value); + return super.put(key, value); + } + + @Override + public Set> entrySet() { + return delegate.entrySet(); + } + + }; + + for (Map.Entry e : yaml.entrySet()) { + readProperties(e.getValue(), e.getKey()); + } + } + + private void readPropertiesFromYamlMap(Map map, String prefix) { + for (Map.Entry e : map.entrySet()) { + readProperties(e.getValue(), "%s.%s".formatted(prefix, e.getKey())); + } + } + + private void readPropertiesFromYamlList(List l, String prefix) { + for (int i = 0; i < l.size(); i++) { + readProperties(l.get(i), "%s[%d]".formatted(prefix, i)); + } + } + + @SuppressWarnings("unchecked") + private void readProperties(Object o, String prefix) { + if (o instanceof Map) { + readPropertiesFromYamlMap((Map) o, prefix); + } else if ( o instanceof List) { + readPropertiesFromYamlList((List) o, prefix); + } else { + properties.put(prefix, o.toString()); + } + } + + public RefactoringStatus getStatus() { + return status; + } + + public Properties getProperties() { + return properties; + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/META-INF/MANIFEST.MF index 728a53248e..9ff661fa21 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.springframework.ide.eclipse.boot.restart;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware, Inc Bundle-Name: Spring Boot Devtools Easy Restart Require-Bundle: org.eclipse.ui, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/pom.xml index 4b40bbbdf1..b78622b1cb 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.restart/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/META-INF/MANIFEST.MF index 0def051dab..f3896089b2 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Templates Bundle-SymbolicName: org.springframework.ide.eclipse.boot.templates;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.core, org.eclipse.text, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/pom.xml index 1a676f106c..8696e39024 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.templates/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.test/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.test/META-INF/MANIFEST.MF index 27dbaf6766..94167f3a76 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.test/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Boot Tests Bundle-SymbolicName: org.springframework.ide.eclipse.boot.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Require-Bundle: org.eclipse.ui, org.junit, org.springsource.ide.eclipse.commons.livexp, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.test/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.test/pom.xml index c49fbedf17..1934a3cb1f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.test/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.test/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/META-INF/MANIFEST.MF index 8632c23fad..da68cba274 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Validation Bundle-SymbolicName: org.springframework.ide.eclipse.boot.validation;singleton:=true Bundle-Vendor: VMware, Inc -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springframework.ide.eclipse.boot.validation.BootValidationActivator Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/pom.xml index 1431f9ba43..a007168bc6 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.classpath b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.classpath index 43b986286a..29fc6a38a1 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.classpath +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.classpath @@ -1,6 +1,6 @@ - + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.settings/org.eclipse.jdt.core.prefs b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.settings/org.eclipse.jdt.core.prefs index 9f6ece88bd..8aabe8df87 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.settings/org.eclipse.jdt.core.prefs +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,14 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=16 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=16 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=16 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/META-INF/MANIFEST.MF index be4688fd94..d4a6cc20c9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Boot UI Support Bundle-SymbolicName: org.springframework.ide.eclipse.boot.wizard;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.ui, org.springsource.ide.eclipse.commons.livexp;bundle-version="3.8.4", diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/plugin.xml index 55ef78cc64..83406514de 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/plugin.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/plugin.xml @@ -142,6 +142,10 @@ + + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/pom.xml index 2cced44a84..94382627f4 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/AddBootStartersHandler2.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/AddBootStartersHandler2.java new file mode 100644 index 0000000000..3eb99e1cdc --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/AddBootStartersHandler2.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.wizard; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; +import org.springframework.ide.eclipse.boot.wizard.starters.AddStartersWizard; + +public class AddBootStartersHandler2 extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + IEditorInput input = HandlerUtil.getActiveEditorInput(event); + if (input instanceof IFileEditorInput fileInput) { + AddStartersWizard.openFor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), fileInput.getFile().getProject()); + return null; + } + } catch (Exception e) { + throw new ExecutionException("", e); + } + throw new ExecutionException("Current active editor is not for pom.xml"); + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/starters/eclipse/ResourceCompareInput.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/starters/eclipse/ResourceCompareInput.java index 1315481abd..1a56b6a901 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/starters/eclipse/ResourceCompareInput.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.wizard/src/org/springframework/ide/eclipse/boot/wizard/starters/eclipse/ResourceCompareInput.java @@ -42,11 +42,16 @@ import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareUI; +import org.eclipse.compare.CompareViewerPane; import org.eclipse.compare.CompareViewerSwitchingPane; import org.eclipse.compare.IStreamContentAccessor; import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.Splitter; +import org.eclipse.compare.contentmergeviewer.ContentMergeViewer; import org.eclipse.compare.contentmergeviewer.TextMergeViewer; +import org.eclipse.compare.internal.AbstractViewer; import org.eclipse.compare.internal.BufferedResourceNode; +import org.eclipse.compare.internal.CompareContentViewerSwitchingPane; import org.eclipse.compare.internal.CompareMessages; import org.eclipse.compare.internal.CompareUIPlugin; import org.eclipse.compare.internal.IMergeViewerTestAdapter; @@ -684,12 +689,17 @@ public void acceptAllChanges() { Shell shell = new Shell(); shell.setVisible(false); // Content difference - TextMergeViewer contentViewer = (TextMergeViewer) CompareUI.findContentViewer(new NullViewer(shell), + ContentMergeViewer contentViewer = (ContentMergeViewer) CompareUI.findContentViewer(new NullViewer(shell), n, shell, getCompareConfiguration()); if (contentViewer != null) { contentViewer.setInput(n); try { - Method method = TextMergeViewer.class.getDeclaredMethod("copy", boolean.class); + Method method; + try { + method = contentViewer.getClass().getDeclaredMethod("copy", boolean.class); + } catch (Exception e) { + method = TextMergeViewer.class.getDeclaredMethod("copy", boolean.class); + } method.setAccessible(true); method.invoke(contentViewer, true); contentViewer.flush(new NullProgressMonitor()); @@ -731,6 +741,48 @@ public Viewer getMergeContentViewer() { } } + class CustomNullViewer extends AbstractViewer { + + private final Control fDummy; + private final Composite parent; + private boolean firstSetInput = true; + + public CustomNullViewer(Composite parent) { + this.parent = parent; + fDummy= new Tree(parent, SWT.NULL); + + } + + @Override + public void setInput(Object input) { + if (!parent.isDisposed() && firstSetInput) { + CompareViewerPane.clearToolBar(parent); + } + super.setInput(input); + firstSetInput = false; + } + + @Override + public Control getControl() { + return fDummy; + } + } + + @Override + protected CompareViewerSwitchingPane createContentViewerSwitchingPane(Splitter parent, int style, CompareEditorInput cei) { + return new CompareContentViewerSwitchingPane(parent, style, cei) { + @Override + protected Viewer getViewer(Viewer oldViewer, Object input) { + if (input instanceof MyDiffNode n) { + if (ITypedElement.FOLDER_TYPE.equals(n.getId().getType())) { + return new CustomNullViewer(this); + } + } + return super.getViewer(oldViewer, input); + } + }; + } + @Override public Viewer createDiffViewer(Composite parent) { fDiffViewer= new CustomDiffTreeViewer(parent, getCompareConfiguration()); diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.boot/META-INF/MANIFEST.MF index a158dfc7e4..601fb1bf16 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Boot Bundle-SymbolicName: org.springframework.ide.eclipse.boot;singleton:=true Bundle-Vendor: VMware, Inc -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springframework.ide.eclipse.boot.core.BootActivator Require-Bundle: org.eclipse.core.resources, org.eclipse.m2e.core, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot/pom.xml index 8731eeda1d..db357a1be0 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/BootPreferences.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/BootPreferences.java index a91c358cd8..68be24ed46 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/BootPreferences.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/BootPreferences.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2017 Pivotal, Inc. + * Copyright (c) 2015, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -44,6 +44,9 @@ public class BootPreferences implements IPreferenceChangeListener { public static final String PREF_BOOT_FAST_STARTUP_JVM_ARGS = "org.springframework.ide.eclipse.boot.FastStartupJvmArgs"; public static final String BOOT_FAST_STARTUP_DEFAULT_JVM_ARGS = "-XX:TieredStopAtLevel=1"; + public static final String PREF_BOOT_TESTJARS_LAUNCH_SUPPORT = "org.springframework.ide.eclipse.boot.TestJarsLaunch"; + + // Boot Preference Page ID public static final String BOOT_PREFERENCE_PAGE_ID = "org.springframework.ide.eclipse.boot.ui.preferences.BootPreferencePage"; diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/initializr/InitializrService.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/initializr/InitializrService.java index ecaffc1658..d32a3ca6a9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/initializr/InitializrService.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/initializr/InitializrService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2016 Pivotal, Inc. + * Copyright (c) 2015, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,7 +17,7 @@ import java.util.Map; import java.util.function.Supplier; -import org.apache.maven.shared.utils.io.IOUtil; +import org.apache.commons.io.IOUtils; import org.springframework.ide.eclipse.boot.core.BootActivator; import org.springframework.ide.eclipse.boot.core.BootPreferences; import org.springframework.ide.eclipse.boot.core.SimpleUriBuilder; @@ -83,7 +83,7 @@ public String getPom(Map parameters) throws Exception { } URLConnection urlConnection = urlConnectionFactory.createConnection(new URL(builder.toString())); urlConnection.connect(); - return IOUtil.toString(urlConnection.getInputStream(), "UTF8"); + return IOUtils.toString(urlConnection.getInputStream(), "UTF8"); } }; } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/BootPreferencePage.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/BootPreferencePage.java index 1940d77e3a..ac5c2f714a 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/BootPreferencePage.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/BootPreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2023 Pivotal, Inc. + * Copyright (c) 2015, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_FAST_STARTUP_REMIND_MESSAGE; import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_THIN_WRAPPER; import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_IGNORE_SILENT_EXIT; +import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT; import org.eclipse.debug.internal.ui.preferences.BooleanFieldEditor2; import org.eclipse.jface.layout.GridDataFactory; @@ -71,6 +72,8 @@ protected void createFieldEditors() { thinLauncher.setErrorMessage("Thin launcher must be an existing file"); setTooltip(thinLauncherComposite, thinLauncher, "Thin boot launcher jar to use in Spring Boot Launch configuration (when that option is enabled in the launch config)"); addField(thinLauncher); + + addField(new BooleanFieldEditor2(PREF_BOOT_TESTJARS_LAUNCH_SUPPORT, "TestJars Support", SWT.CHECK, launchGroup)); } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/PreferencesInitializer.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/PreferencesInitializer.java index 9b300ab0cd..6ce574317f 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/PreferencesInitializer.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/PreferencesInitializer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 Pivotal, Inc. + * Copyright (c) 2016, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,6 +17,7 @@ import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_FAST_STARTUP_REMIND_MESSAGE; import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_FAST_STARTUP_JVM_ARGS; import static org.springframework.ide.eclipse.boot.core.BootPreferences.BOOT_FAST_STARTUP_DEFAULT_JVM_ARGS; +import static org.springframework.ide.eclipse.boot.core.BootPreferences.PREF_BOOT_TESTJARS_LAUNCH_SUPPORT; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; import org.eclipse.jface.preference.IPreferenceStore; @@ -25,7 +26,7 @@ /** * Initializer of default values for the Spring Boot support - * + * * @author Alex Boyko * */ @@ -34,7 +35,7 @@ public class PreferencesInitializer extends AbstractPreferenceInitializer { @Override public void initializeDefaultPreferences() { IPreferenceStore store = BootActivator.getDefault().getPreferenceStore(); - + /* * Note that line below cannot be moved to BootPreferencePage static * init method because the class has BooleanFieldEditor2 import that in @@ -42,13 +43,15 @@ public void initializeDefaultPreferences() { * because workbench may not be started in the case of a unit test */ store.setDefault(PREF_IGNORE_SILENT_EXIT, DEFAULT_PREF_IGNORE_SILENT_EXIT); - + store.setDefault(PREF_INITIALIZR_URL, StsProperties.getInstance().get("spring.initializr.json.url")); - + store.setDefault(PREF_BOOT_FAST_STARTUP_DEFAULT, true); store.setDefault(PREF_BOOT_FAST_STARTUP_REMIND_MESSAGE, true); store.setDefault(PREF_BOOT_FAST_STARTUP_JVM_ARGS, BOOT_FAST_STARTUP_DEFAULT_JVM_ARGS); + store.setDefault(BOOT_FAST_STARTUP_DEFAULT_JVM_ARGS, DEFAULT_PREF_IGNORE_SILENT_EXIT); + store.setDefault(PREF_BOOT_TESTJARS_LAUNCH_SUPPORT, true); } - + } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.buildship30/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.buildship30/META-INF/MANIFEST.MF index bdc0db2664..500639f44c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.buildship30/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.buildship30/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.springframework.ide.eclipse.buildship30;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: %providerName Bundle-RequiredExecutionEnvironment: JavaSE-17 Eclipse-LazyStart: true diff --git a/eclipse-extensions/org.springframework.ide.eclipse.buildship30/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.buildship30/pom.xml index 1b8bbf1c17..faf5e5ba9b 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.buildship30/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.buildship30/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.docker.client/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.docker.client/META-INF/MANIFEST.MF index 9e81c2945f..5e5a849129 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.docker.client/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.docker.client/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: org.springframework.ide.eclipse.docker.client.wrapper Bundle-SymbolicName: org.springframework.ide.eclipse.docker.client;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.docker.client.wrapper Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ClassPath: ., diff --git a/eclipse-extensions/org.springframework.ide.eclipse.docker.client/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.docker.client/pom.xml index 4a96826004..08563ca8a8 100755 --- a/eclipse-extensions/org.springframework.ide.eclipse.docker.client/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.docker.client/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.imports/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.imports/META-INF/MANIFEST.MF index 430256f060..02a5a6314e 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.imports/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.imports/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.springframework.ide.eclipse.imports;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Localization: plugin Bundle-Vendor: %providerName Bundle-Activator: org.springframework.ide.eclipse.imports.ImportsActivator diff --git a/eclipse-extensions/org.springframework.ide.eclipse.imports/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.imports/pom.xml index d189f744d6..f615ee3f39 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.imports/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.imports/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/META-INF/MANIFEST.MF index 7fcdd839b0..9fa75f7f03 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Maven POM Compare Tests Bundle-SymbolicName: org.springframework.ide.eclipse.maven.pom.tests -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.maven.pom.tests Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.junit, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/pom.xml index 55070a8cea..3b39fb94a6 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom.tests/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/META-INF/MANIFEST.MF index 511cffacb1..c8a2a8c02b 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Maven POM Compare Bundle-SymbolicName: org.springframework.ide.eclipse.maven.pom;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.maven.pom Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.compare, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/pom.xml index a7c42d9f53..c2dc563734 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.maven.pom/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/feature.xml b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/feature.xml index 4a29953b36..9dacf933b9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/feature.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/feature.xml @@ -14,7 +14,7 @@ diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/pom.xml index 7f306c5b2b..344765b8d9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces.feature/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/META-INF/MANIFEST.MF index b2b13d6855..ccf3f80b01 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/META-INF/MANIFEST.MF @@ -31,7 +31,7 @@ Import-Package: org.eclipse.core.commands.common, org.springsource.ide.eclipse.commons.ui, org.apache.commons.io Bundle-Activator: org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Export-Package: org.springframework.ide.eclipse.xml.namespaces, org.springframework.ide.eclipse.xml.namespaces.classpath, org.springframework.ide.eclipse.xml.namespaces.internal, diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/pom.xml index 60ea0deb0d..4b8f032215 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xml.namespaces/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/feature.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/feature.xml index 780efa9254..9f2a4e5d45 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/feature.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/pom.xml index d42d45f20c..76ff462038 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml org.springframework.ide.eclipse diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/META-INF/MANIFEST.MF index d4e7bb6a1e..aaf7808454 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Node-Xterm package for Linux Bundle-SymbolicName: org.springframework.ide.eclipse.xterm.linux.x86_64 -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware Fragment-Host: org.springframework.ide.eclipse.xterm;bundle-version="4.8.2" Automatic-Module-Name: org.springframework.ide.eclipse.xterm.linux.x86.64 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/pom.xml index ca3cf158ff..51fa583074 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.linux.x86_64/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml eclipse-plugin diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/META-INF/MANIFEST.MF index 45eaad91d6..7836965b75 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Node-Xterm package for Mac OSX Bundle-SymbolicName: org.springframework.ide.eclipse.xterm.macosx.x86_64 -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware Fragment-Host: org.springframework.ide.eclipse.xterm;bundle-version="4.8.2" Automatic-Module-Name: org.springframework.ide.eclipse.xterm.macosx.x86.64 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/pom.xml index a3e0d4b4f0..12def03e11 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.macosx.x86_64/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml eclipse-plugin diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/META-INF/MANIFEST.MF index 0c102f4dd0..6198e330d6 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Node-Xterm package for Windows Bundle-SymbolicName: org.springframework.ide.eclipse.xterm.win32.x86_64 -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: VMware Fragment-Host: org.springframework.ide.eclipse.xterm;bundle-version="4.8.2" Automatic-Module-Name: org.springframework.ide.eclipse.xterm.win32.x86.64 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/pom.xml index 4f5bd1bcfa..9c75b71700 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm.win32.x86_64/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml eclipse-plugin diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm/META-INF/MANIFEST.MF b/eclipse-extensions/org.springframework.ide.eclipse.xterm/META-INF/MANIFEST.MF index a2474edf88..81d4d944d3 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm/META-INF/MANIFEST.MF +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: org.springframework.ide.eclipse.xterm Bundle-SymbolicName: org.springframework.ide.eclipse.xterm;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.ide.eclipse.xterm Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-Activator: org.springframework.ide.eclipse.xterm.XtermPlugin diff --git a/eclipse-extensions/org.springframework.ide.eclipse.xterm/pom.xml b/eclipse-extensions/org.springframework.ide.eclipse.xterm/pom.xml index ffdf0aa1fc..1247cdc7fd 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.xterm/pom.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.xterm/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../../eclipse-distribution/pom.xml eclipse-plugin diff --git a/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/META-INF/MANIFEST.MF index 2267107318..ca0c3d2042 100644 --- a/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.springframework.ide.eclipse.editor.support -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springframework.ide.eclipse.editor.support.EditorSupportActivator Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, diff --git a/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/pom.xml b/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/pom.xml index ab52367384..8aef0955cc 100644 --- a/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/pom.xml +++ b/eclipse-language-servers/org.springframework.ide.eclipse.editor.support/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/feature.xml index a46d55ad34..326e856d46 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/pom.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/pom.xml index eff432818f..a04bba9789 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF index aa6d30424d..6f0e21db39 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Spring Boot Language Server Bundle-Vendor: Broadcom Bundle-SymbolicName: org.springframework.tooling.boot.ls;singleton:=true -Bundle-Version: 1.53.0.qualifier +Bundle-Version: 1.54.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png b/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png new file mode 100644 index 0000000000..de88ef0d5c Binary files /dev/null and b/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png differ diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml index 9942e4a07f..1d944e022a 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml @@ -82,6 +82,10 @@ --> + + @@ -173,6 +177,17 @@ file-names="spring.factories,aot.factories" file-patterns="*.factories"> + + + + @@ -292,6 +319,34 @@ id="org.springframework.tooling.boot.ls.modulith.metadata.refresh" name="Refresh Modulith Metadata"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml org.springframework.tooling.boot.ls - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT eclipse-plugin diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java index 0d018ff978..5d177cb8df 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -44,4 +44,7 @@ public class Constants { public static final String PREF_START_LS_EARLY = "start.boot-ls.early"; public static final String PREF_COMMON_PROPS_METADATA = "boot-java.common.properties-metadata"; + + public static final String PREF_MODULITH = "boot-java.modulith-project-tracking"; + } diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java index 9243794ff5..c97921f530 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -212,6 +212,7 @@ private void sendConfiguration() { bootJavaObj.put("change-detection", bootChangeDetection); bootJavaObj.put("validation", validation); bootJavaObj.put("remote-apps", getAllRemoteApps()); + bootJavaObj.put("modulith-project-tracking", preferenceStore.getBoolean(Constants.PREF_MODULITH)); bootJavaObj.put("rewrite", Map.of( "recipe-filters", StringListEditor.decode(preferenceStore.getString(Constants.PREF_REWRITE_RECIPE_FILTERS)), diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/SpringBootLanguageServer.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/SpringBootLanguageServer.java index 9d3aeb983a..e17c26c702 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/SpringBootLanguageServer.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/SpringBootLanguageServer.java @@ -45,7 +45,6 @@ private List getJVMArgs() { // args.add("-Xrunjdwp:server=y,transport=dt_socket,address=1044,suspend=n"); args.add("-Dlsp.completions.indentation.enable=true"); args.add("-Xmx1024m"); - args.add("-XX:+HeapDumpOnOutOfMemoryError"); args.add("-XX:TieredStopAtLevel=1"); addCustomJVMArgs(args); diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/AddStartersHandler.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/AddStartersHandler.java new file mode 100644 index 0000000000..402127060b --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/AddStartersHandler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.tooling.boot.ls.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.handlers.IHandlerService; + +public class AddStartersHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + IWorkbenchWindow workbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final IHandlerService service = workbenchWindow.getService(IHandlerService.class); + return service.executeCommand("org.springframework.ide.eclipse.boot.commands.editStartersCommand2", null); + } catch (Exception e) { + throw new ExecutionException("", e); + } + } + +} diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/ConvertBootPropertiesHanlder.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/ConvertBootPropertiesHanlder.java new file mode 100644 index 0000000000..296516f910 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/ConvertBootPropertiesHanlder.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.tooling.boot.ls.commands; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.lsp4e.LanguageServers; +import org.eclipse.lsp4e.LanguageServersRegistry; +import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition; +import org.eclipse.lsp4j.ExecuteCommandParams; +import org.eclipse.ui.handlers.HandlerUtil; +import org.springframework.tooling.boot.ls.BootLanguageServerPlugin; + +@SuppressWarnings("restriction") +public abstract class ConvertBootPropertiesHanlder extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IFile sourceFile = getSourceFile(event); + IProject project = sourceFile.getProject(); + if (project != null) { + + // No replace functionality for Eclipse due to issues with undoing the change + final boolean replace = false; + +// ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(sourceFile.getFullPath(), LocationKind.IFILE); +// if (buffer != null && buffer.isDirty()) { +// try { +// buffer.commit(null, true); +// } catch (CoreException e) { +// BootLanguageServerPlugin.getDefault().getLog().log(e.getStatus()); +// } +// } +// +// final boolean replace = BootLanguageServerPlugin.getDefault().getPreferenceStore().getBoolean(Constants.PREF_REPLACE_CONVERTED_PROPS_FILE); +// +// if (replace) { +// // Workaround: LSP4E LSPTextEdit doesn't work well with non opened files in the workspace in this particular case +// // Therefore, open the file in an editor thus changes are applied to the document. +// try { +// IDE.openEditor(UI.getActivePage(), sourceFile); +// } catch (PartInitException e) { +// BootLanguageServerPlugin.getDefault().getLog().error("", e); +// } +// } + + IFile targetFile = getTargetFile(sourceFile, getTargetExtension()); + + LanguageServerDefinition def = LanguageServersRegistry.getInstance().getDefinition(BootLanguageServerPlugin.BOOT_LS_DEFINITION_ID); + Assert.isLegal(def != null, "No definition found for Boot Language Server"); + + ExecuteCommandParams commandParams = new ExecuteCommandParams(); + commandParams.setCommand(getCommandId()); + commandParams.setArguments(List.of( + sourceFile.getLocationURI().toASCIIString(), + targetFile.getLocationURI().toASCIIString(), + replace + )); + + LanguageServers.forProject(project).withPreferredServer(def).computeFirst(ls -> ls.getWorkspaceService().executeCommand(commandParams)); + + } + + return null; + } + + abstract protected String getTargetExtension(); + + abstract protected String getCommandId(); + + private IFile getTargetFile(IFile sourceFile, String ext) { + IProject project = sourceFile.getProject(); + IPath eclipsePath = sourceFile.getProjectRelativePath(); + IPath dir = eclipsePath.removeLastSegments(1); + String fileName = sourceFile.getName(); + String fileNoExt = fileName.substring(0, fileName.length() - sourceFile.getFileExtension().length() - 1); + IFile target = project.getFile(dir.append("%s.%s".formatted(fileNoExt, ext))); + for (int i = 1; i < Integer.MAX_VALUE && target.exists(); i++) { + target = project.getFile(dir.append("%s-%d.%s".formatted(fileNoExt, i, ext))); + } + return target; + } + + private IFile getSourceFile(ExecutionEvent event) { + ISelection selection = HandlerUtil.getActiveMenuSelection(event); + IStructuredSelection ss = null; + if (selection instanceof IStructuredSelection) { + ss = (IStructuredSelection) selection; + } else { + selection = HandlerUtil.getActiveMenuEditorInput(event); + if (selection instanceof IStructuredSelection) { + ss = (IStructuredSelection) selection; + } + } + if (ss!=null && !ss.isEmpty()) { + return asFile(ss.getFirstElement()); + } + return null; + } + + private IFile asFile(Object selectedElement) { + if (selectedElement instanceof IFile) { + return (IFile) selectedElement; + } + if (selectedElement instanceof IAdaptable) { + return ((IAdaptable) selectedElement).getAdapter(IFile.class); + } + return null; + } + + public static class ConvertPropertiesToYamlHandler extends ConvertBootPropertiesHanlder { + + @Override + protected String getTargetExtension() { + return "yml"; + } + + @Override + protected String getCommandId() { + return "sts/boot/props-to-yaml"; + } + + } + + public static class ConvertYamlToPropertiesHanlder extends ConvertBootPropertiesHanlder { + + @Override + protected String getTargetExtension() { + return "properties"; + } + + @Override + protected String getCommandId() { + return "sts/boot/yaml-to-props"; + } + + } + + +} diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java index 2d2109326b..8cec47a468 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -42,6 +42,9 @@ protected void createFieldEditors() { addField(new BooleanFieldEditor(Constants.PREF_SCAN_JAVA_TEST_SOURCES, "Scan Java test sources", fieldEditorParent)); addField(new BooleanFieldEditor(Constants.PREF_CHANGE_DETECTION, "Live Boot Change Detection", fieldEditorParent)); + + // Experimental Modulith support + addField(new BooleanFieldEditor(Constants.PREF_MODULITH, "Spring Boot Modulith automatic project tracking and metadata update", fieldEditorParent)); Composite c = new Composite(fieldEditorParent, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).applyTo(c); diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java index 48cb942d0f..391c91baeb 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java @@ -50,8 +50,7 @@ public void initializeDefaultPreferences() { preferenceStore.setDefault(Constants.PREF_REWRITE_RECIPE_FILTERS, StringListEditor.encode(new String[] { "org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration", - "org.openrewrite.java.spring.boot2.SpringBoot2BestPractices", - "org.openrewrite.java.spring.boot2.SpringBoot1To2Migration", + "org.openrewrite.java.spring.boot3.SpringBoot3BestPractices", "org.openrewrite.java.testing.junit5.JUnit5BestPractices", "org.openrewrite.java.testing.junit5.JUnit4to5Migration", "org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7", @@ -60,6 +59,9 @@ public void initializeDefaultPreferences() { "org.springframework.rewrite.test.*", "rewrite.test.*" })); + + preferenceStore.setDefault(Constants.PREF_MODULITH, true); + } } diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/feature.xml index ac41efbaa8..2943e79546 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/pom.xml b/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/pom.xml index 76586fcab5..159d7321cc 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF index aeba3517e0..f48bd96027 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: BOSH Manifest Language Server Bundle-Vendor: Broadcom Bundle-SymbolicName: org.springframework.tooling.bosh.ls;singleton:=true -Bundle-Version: 1.53.0.qualifier +Bundle-Version: 1.54.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml index bfcf687023..814b938e52 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/pom.xml @@ -7,12 +7,12 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml org.springframework.tooling.bosh.ls - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT eclipse-plugin diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/feature.xml index d188528bbb..8304bf69da 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/pom.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/pom.xml index c872b4e4c8..1072f3dce8 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/feature.xml index 6fd260bc0a..5106ca8d35 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/pom.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/pom.xml index 157c755365..afa1e3228c 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/META-INF/MANIFEST.MF index 0e58249721..a6785b80be 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Cloud Foundry Manifest Language Server Generic Editor Integration Bundle-Vendor: Broadcom Bundle-SymbolicName: org.springframework.tooling.cloudfoundry.manifest.ls.integration;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/pom.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/pom.xml index 8e3c173756..d21fad55f1 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls.integration/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF index 9ac544286a..e7351cf310 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Cloud Foundry Manifest Language Server Bundle-Vendor: Broadcom Bundle-SymbolicName: org.springframework.tooling.cloudfoundry.manifest.ls;singleton:=true -Bundle-Version: 1.53.0.qualifier +Bundle-Version: 1.54.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml index a074593f0d..025a69fda0 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/pom.xml @@ -7,12 +7,12 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml org.springframework.tooling.cloudfoundry.manifest.ls - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT eclipse-plugin diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/feature.xml index 34a4b7ca2c..a2e406c691 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/pom.xml b/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/pom.xml index cb87b8d5b5..6264f99c3a 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls.feature/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF index 25f31f80e6..11a52d2f03 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Concourse Pipeline Language Server Bundle-Vendor: Broadcom Bundle-SymbolicName: org.springframework.tooling.concourse.ls;singleton:=true -Bundle-Version: 1.53.0.qualifier +Bundle-Version: 1.54.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.core.runtime;bundle-version="3.12.0", diff --git a/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml b/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml index be74407563..deecd1b00f 100644 --- a/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.concourse.ls/pom.xml @@ -7,12 +7,12 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml org.springframework.tooling.concourse.ls - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT eclipse-plugin diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/META-INF/MANIFEST.MF index 223d695877..d6ff1439e9 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Test Bundle-SymbolicName: org.springframework.tooling.ls.eclipse.commons.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.tooling.ls.eclipse.commons.test Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.junit, @@ -19,4 +19,5 @@ Require-Bundle: org.junit, Import-Package: com.google.gson, com.google.gson.annotations, com.google.gson.reflect, - com.google.gson.stream + com.google.gson.stream, + org.apache.commons.io diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/pom.xml index e9f76003bb..bd1f69a684 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF index e86cc48151..0d45612c47 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Language Server Commons Bundle-SymbolicName: org.springframework.tooling.ls.eclipse.commons;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: Broadcom Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0", org.eclipse.ui, diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml index 97768f2f1c..29e12b623a 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightsCodeLensProvider.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightsCodeLensProvider.java index fda4ce1684..bad0449f4a 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightsCodeLensProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightsCodeLensProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2023 Pivotal, Inc. + * Copyright (c) 2018, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -48,14 +48,19 @@ public class HighlightsCodeLensProvider extends AbstractCodeMiningProvider { private static final Map>> ACTION_MAP = new HashMap<>(); static { ACTION_MAP.put("sts.open.url", (cmd) -> { - return (me) -> { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - if (!cmd.getArguments().isEmpty() && cmd.getArguments().get(0) instanceof JsonPrimitive) { - String url = ((JsonPrimitive)cmd.getArguments().get(0)).getAsString(); - LSPEclipseUtils.open(url, page, null); - } - }; + return (me) -> opneUrlCommand(cmd); }); + ACTION_MAP.put("vscode-spring-boot.open.url", (cmd) -> { + return (me) -> opneUrlCommand(cmd); + }); + } + + private static void opneUrlCommand(Command cmd) { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + if (!cmd.getArguments().isEmpty() && cmd.getArguments().get(0) instanceof JsonPrimitive) { + String url = ((JsonPrimitive)cmd.getArguments().get(0)).getAsString(); + LSPEclipseUtils.open(url, page, null); + } } private static Consumer action(Command cmd) { diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF index 5719dabe79..53c67c4231 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Goto Symbol Popup Bundle-SymbolicName: org.springframework.tooling.ls.eclipse.gotosymbol;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Require-Bundle: org.eclipse.ui, org.eclipse.ui.workbench.texteditor, org.eclipse.lsp4e;bundle-version="0.13.12", diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/pom.xml index cb1a4e76ae..c729e2dcbd 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/pom.xml index 5ad5239b3a..41e6342f57 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springframework.tooling.ls.repository/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.repository/pom.xml index 30f3f2f242..fe1182ebaf 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.repository/pom.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.repository/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF index 5b5e1bca02..ccb094b0fc 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Spring Tool Suite Common UI Components Bundle-SymbolicName: org.springsource.ide.eclipse.commons.boot.ls;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: Broadcom Require-Bundle: org.eclipse.core.resources, org.springsource.ide.eclipse.commons.livexp diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml index b7cce9c944..a1e1dd9051 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF index a4a2f154c9..4c6cf2bd84 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SpringSource Tool Suite (Core) Bundle-SymbolicName: org.springsource.ide.eclipse.commons.core;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springsource.ide.eclipse.commons.internal.core.CorePlugin Bundle-Vendor: Broadcom Require-Bundle: org.eclipse.core.resources, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml index f19dc4671b..bd9504b6f5 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/META-INF/MANIFEST.MF index 9b1a6ef0f5..d8aa03be52 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.springsource.ide.eclipse.commons.frameworks.core;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springsource.ide.eclipse.commons.frameworks.core.FrameworkCoreActivator Bundle-Vendor: %providerName Require-Bundle: org.eclipse.ui, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/pom.xml index 0c149d6784..a2002f4b3d 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/META-INF/MANIFEST.MF index ada272683a..5f1c9f7706 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: com.springsource.sts.frameworks.test.util Bundle-SymbolicName: org.springsource.ide.eclipse.commons.frameworks.test.util;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-ActivationPolicy: lazy Bundle-Vendor: Broadcom Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/pom.xml index 62368e30e4..0787ab790e 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.test.util/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/META-INF/MANIFEST.MF index 1beaff5a95..83d436096c 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.springsource.ide.eclipse.commons.frameworks.ui;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springsource.ide.eclipse.commons.frameworks.ui.FrameworkUIActivator Bundle-Vendor: %providerName Require-Bundle: org.eclipse.ui, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/pom.xml index 1d558cfda2..e08b8d3d8a 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.ui/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/META-INF/MANIFEST.MF index 724c0effe0..5ff5612e21 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SpringSource Tool Suite (JDK Tools) Bundle-SymbolicName: org.springsource.ide.eclipse.commons.jdk_tools;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ClassPath: external:$java.home$/../lib/tools.jar Export-Package: com.sun.tools.attach diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/pom.xml index ccb050a091..56b484739e 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.jdk_tools/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/META-INF/MANIFEST.MF index 721a00915a..d10bd7a44d 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Integration Commands - Livexp Bundle-SymbolicName: org.springsource.ide.eclipse.commons.livexp -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Activator: org.springsource.ide.eclipse.commons.livexp.Activator Require-Bundle: org.eclipse.jface, org.eclipse.ui.workbench, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/pom.xml index 088f162986..1860a542e4 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.livexp/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/META-INF/MANIFEST.MF index a58c605fd6..456ffeb7a5 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SpringSource Tool Suite Test Utilities Bundle-SymbolicName: org.springsource.ide.eclipse.commons.tests.util;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: Broadcom Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/pom.xml index 7b9e1c5a90..ba8b3d066e 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/META-INF/MANIFEST.MF index 60b3922212..f2419714f2 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Spring Tool Suite Common UI Components Bundle-SymbolicName: org.springsource.ide.eclipse.commons.ui;singleton:=true -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: Broadcom Require-Bundle: org.eclipse.core.resources, org.eclipse.ui, diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/pom.xml index ef5b0d0a1b..983eff5b7a 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/pom.xml +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.ui/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT ../pom.xml diff --git a/eclipse-language-servers/pom.xml b/eclipse-language-servers/pom.xml index ba1d3df8de..1d0fec63f3 100644 --- a/eclipse-language-servers/pom.xml +++ b/eclipse-language-servers/pom.xml @@ -4,7 +4,7 @@ org.springframework.boot.ide org.springframework.boot.ide.servers - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT pom @@ -139,26 +139,26 @@ - e429 + e430 - e4.29.0 - e4.29 - 2023-09 - 2023-09 (4.29) - 2023-09 - 4.29 - e429 + e4.30.0 + e4.30 + 2023-12 + 2023-12 (4.30) + 2023-12 + 4.30 + e430 - 2023-09 + 2023-12 p2 - https://download.eclipse.org/releases/2023-09/ + https://download.eclipse.org/releases/2023-12/ orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-09 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12 + + https://download.eclipse.org/lsp4e/snapshots tm4e p2 - https://download.eclipse.org/tm4e/releases/0.8.1/ - + + https://download.eclipse.org/tm4e/snapshots wwd @@ -192,26 +192,26 @@ - e430 + e431 - e4.30.0 - e4.30 - 2023-12 - 2023-12 (4.30) - 2023-12 - 4.30 - e430 + e4.31.0 + e4.31 + 2024-03 + 2024-03 (4.31) + 2024-03 + 4.31 + e431 2023-12 p2 - https://download.eclipse.org/releases/2023-12/ + https://download.eclipse.org/staging/2024-03/ orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-03 + https://download.eclipse.org/lsp4e/snapshots @@ -245,47 +245,42 @@ - e431 + e432 - e4.31.0 - e4.31 - 2024-03 - 2024-03 (4.31) - 2024-03 - 4.31 - e431 + e4.32.0 + e4.32 + 2024-06 + 2024-06 (4.32) + 2024-06 + 4.32 + e432 - 2023-12 + 2024-06 p2 - https://download.eclipse.org/staging/2024-03/ + https://download.eclipse.org/staging/2024-06/ orbit p2 - https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-03 + https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-06 - mylyn-markdown p2 - https://download.eclipse.org/mylyn/docs/releases/3.0.45/ + https://download.eclipse.org/mylyn/docs/releases/3.0.48/ lsp4e p2 - + https://download.eclipse.org/lsp4e/snapshots tm4e p2 - + https://download.eclipse.org/tm4e/snapshots @@ -296,7 +291,6 @@ - diff --git a/headless-services/bosh-language-server/pom.xml b/headless-services/bosh-language-server/pom.xml index 2cd25a4c52..dc3532d7c5 100644 --- a/headless-services/bosh-language-server/pom.xml +++ b/headless-services/bosh-language-server/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/commons/commons-cf/pom.xml b/headless-services/commons/commons-cf/pom.xml index 49a23fdb62..1b91bb5bde 100644 --- a/headless-services/commons/commons-cf/pom.xml +++ b/headless-services/commons/commons-cf/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-gradle/pom.xml b/headless-services/commons/commons-gradle/pom.xml index 929f2e184e..307ae6a69d 100644 --- a/headless-services/commons/commons-gradle/pom.xml +++ b/headless-services/commons/commons-gradle/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java index 3d1c06c416..13ed398ec3 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -35,7 +35,7 @@ public class GradleJavaProject extends LegacyJavaProject { private static final Logger log = LoggerFactory.getLogger(GradleJavaProject.class); private GradleJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File gradleFile, JavadocService javadocService) { - super(fileObserver, gradleFile.getParentFile().toURI(), projectDataCache, classpath, javadocService, IProjectBuild.create(ProjectBuild.GRADLE_PROJECT_TYPE, gradleFile.toURI())); + super(fileObserver, gradleFile.getParentFile().toURI(), projectDataCache, classpath, javadocService, IProjectBuild.create(ProjectBuild.GRADLE_PROJECT_TYPE, gradleFile.toURI(), null)); } public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File gradleFile, Path projectDataCache, JavadocService javadocService) { diff --git a/headless-services/commons/commons-java/pom.xml b/headless-services/commons/commons-java/pom.xml index 3d31261d11..0643ca34c1 100644 --- a/headless-services/commons/commons-java/pom.xml +++ b/headless-services/commons/commons-java/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IGav.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IGav.java new file mode 100644 index 0000000000..e6ebc2ddbb --- /dev/null +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IGav.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.java; + +import org.springframework.ide.vscode.commons.protocol.java.Gav; + +public interface IGav { + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + static IGav create(Gav gav) { + return new IGav() { + + @Override + public String getVersion() { + return gav.version(); + } + + @Override + public String getGroupId() { + return gav.groupId(); + } + + @Override + public String getArtifactId() { + return gav.artifactId(); + } + }; + } +} diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IProjectBuild.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IProjectBuild.java index 5c73235c56..880bccbefe 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IProjectBuild.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IProjectBuild.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 VMware, Inc. + * Copyright (c) 2022, 2024 VMware, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,13 +12,17 @@ import java.net.URI; +import org.springframework.ide.vscode.commons.protocol.java.Gav; + public interface IProjectBuild { String getType(); URI getBuildFile(); - static IProjectBuild create(String type, URI buildFile) { + IGav getGav(); + + static IProjectBuild create(String type, URI buildFile, Gav gav) { return new IProjectBuild() { @Override @@ -30,6 +34,10 @@ public String getType() { public URI getBuildFile() { return buildFile; } + + public IGav getGav() { + return IGav.create(gav); + } }; } diff --git a/headless-services/commons/commons-language-server/pom.xml b/headless-services/commons/commons-language-server/pom.xml index f8b400c60b..3deb4ab094 100644 --- a/headless-services/commons/commons-language-server/pom.xml +++ b/headless-services/commons/commons-language-server/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java index 43414c6a31..c095971ed0 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2022 Pivotal, Inc. + * Copyright (c) 2018, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,34 +10,45 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.languageserver.composable; +import java.net.URI; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.CodeActionCapabilities; import org.eclipse.lsp4j.CodeActionContext; +import org.eclipse.lsp4j.CodeLens; +import org.eclipse.lsp4j.CodeLensParams; import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.DocumentSymbolParams; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.HoverParams; +import org.eclipse.lsp4j.InlayHint; +import org.eclipse.lsp4j.InlayHintParams; import org.eclipse.lsp4j.WorkspaceSymbol; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.springframework.context.ApplicationContext; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine; import org.springframework.ide.vscode.commons.languageserver.util.CodeActionHandler; +import org.springframework.ide.vscode.commons.languageserver.util.CodeLensHandler; import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler; import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler; +import org.springframework.ide.vscode.commons.languageserver.util.InlayHintHandler; +import org.springframework.ide.vscode.commons.languageserver.util.LanguageComputer; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; -import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.util.text.IRegion; import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.LazyTextDocument; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableMap; @@ -45,45 +56,52 @@ public class CompositeLanguageServerComponents implements LanguageServerComponents { public static class Builder { - private Map componentsByLanguageId = new HashMap<>(); + private Map> componentsByLanguageId = new HashMap<>(); public void add(LanguageServerComponents components) { for (LanguageId language : components.getInterestingLanguages()) { - //Multiple associations to a single language id not yet supported. - Assert.isLegal(!componentsByLanguageId.containsKey(language)); - componentsByLanguageId.put(language, components); + List list = componentsByLanguageId.get(language); + if (list == null) { + list = new ArrayList<>(1); + componentsByLanguageId.put(language, list); + } + list.add(components); } } - public CompositeLanguageServerComponents build(SimpleLanguageServer server) { - return new CompositeLanguageServerComponents(server, this); + public CompositeLanguageServerComponents build(ApplicationContext appContext) { + return new CompositeLanguageServerComponents(appContext, this); } } - private final Map componentsByLanguageId; + private final Map> componentsByLanguageId; private final IReconcileEngine reconcileEngine; private final HoverHandler hoverHandler; private final CodeActionHandler codeActionHandler; + private final CodeLensHandler codeLensHandler; private final DocumentSymbolHandler docSymbolHandler; + private final InlayHintHandler inlayHintHandler; - public CompositeLanguageServerComponents(SimpleLanguageServer server, Builder builder) { + public CompositeLanguageServerComponents(ApplicationContext appContext, Builder builder) { + SimpleLanguageServer server = appContext.getBean(SimpleLanguageServer.class); this.componentsByLanguageId = ImmutableMap.copyOf(builder.componentsByLanguageId); //Create composite Reconcile engine - if (componentsByLanguageId.values().stream().map(LanguageServerComponents::getReconcileEngine).anyMatch(Optional::isPresent)) { + if (componentsByLanguageId.values().stream().flatMap(l -> l.stream()).map(LanguageServerComponents::getReconcileEngine).anyMatch(Optional::isPresent)) { this.reconcileEngine = new IReconcileEngine() { @Override public void reconcile(IDocument document, IProblemCollector problemCollector) { LanguageId language = document.getLanguageId(); - LanguageServerComponents subComponents = componentsByLanguageId.get(language); + List subComponents = componentsByLanguageId.get(language); if (subComponents!=null) { - Optional subEngine = subComponents.getReconcileEngine(); - if (subEngine.isPresent()) { - subEngine.get().reconcile(document, problemCollector); - return; + for (LanguageServerComponents subComponent : subComponents) { + Optional subEngine = subComponent.getReconcileEngine(); + if (subEngine.isPresent()) { + subEngine.get().reconcile(document, problemCollector); + } } } - //No applicable subEngine... but we still have to obey the IReconcileEngine contract! - IReconcileEngine.NULL.reconcile(document, problemCollector); +// //No applicable subEngine... but we still have to obey the IReconcileEngine contract! +// IReconcileEngine.NULL.reconcile(document, problemCollector); } }; } else { @@ -95,11 +113,13 @@ public void reconcile(IDocument document, IProblemCollector problemCollector) { public Hover handle(CancelChecker cancelToken, HoverParams params) { TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri()); LanguageId language = doc.getLanguageId(); - LanguageServerComponents subComponents = componentsByLanguageId.get(language); + List subComponents = componentsByLanguageId.get(language); if (subComponents != null) { - HoverHandler subEngine = subComponents.getHoverProvider(); - if (subEngine != null) { - return subEngine.handle(cancelToken, params); + for (LanguageServerComponents subComponent : subComponents) { + HoverHandler subEngine = subComponent.getHoverProvider(); + if (subEngine != null) { + return subEngine.handle(cancelToken, params); + } } } //No applicable subEngine... @@ -113,11 +133,51 @@ public Hover handle(CancelChecker cancelToken, HoverParams params) { public List> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region) { LanguageId language = doc.getLanguageId(); - LanguageServerComponents subComponents = componentsByLanguageId.get(language); + List subComponents = componentsByLanguageId.get(language); if (subComponents != null) { - return subComponents.getCodeActionProvider() - .map(subEngine -> subEngine.handle(cancelToken, capabilities, context, doc, region)) - .orElse(Collections.emptyList()); + return subComponents.stream() + .map(sc -> sc.getCodeActionProvider()) + .filter(provider -> provider.isPresent()) + .flatMap(se -> se.get().handle(cancelToken, capabilities, context, doc, region).stream()) + .collect(Collectors.toList()); + } + // No applicable subEngine... + return Collections.emptyList(); + } + }; + + this.codeLensHandler = new CodeLensHandler() { + + @Override + public List handle(CancelChecker cancelToken, CodeLensParams params) { + TextDocument doc = getDoc(appContext, params.getTextDocument().getUri()); + LanguageId language = doc.getLanguageId(); + List subComponents = componentsByLanguageId.get(language); + if (subComponents != null) { + return subComponents.stream() + .map(sc -> sc.getCodeLensHandler()) + .filter(h -> h.isPresent()) + .flatMap(h -> h.get().handle(cancelToken, params).stream()) + .collect(Collectors.toList()); + } + // No applicable subEngine... + return Collections.emptyList(); + } + }; + + this.inlayHintHandler = new InlayHintHandler() { + + @Override + public List handle(CancelChecker token, InlayHintParams params) { + TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri()); + LanguageId language = doc.getLanguageId(); + List subComponents = componentsByLanguageId.get(language); + if (subComponents != null) { + return subComponents.stream() + .map(sc -> sc.getInlayHintHandler()) + .filter(h -> h.isPresent()) + .flatMap(h -> h.get().handle(token, params).stream()) + .collect(Collectors.toList()); } // No applicable subEngine... return Collections.emptyList(); @@ -128,14 +188,15 @@ public List> handle(CancelChecker cancelToken, @Override public List handle(DocumentSymbolParams params) { - TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri()); + TextDocument doc = getDoc(appContext, params.getTextDocument().getUri()); LanguageId language = doc.getLanguageId(); - LanguageServerComponents subComponents = componentsByLanguageId.get(language); + List subComponents = componentsByLanguageId.get(language); if (subComponents != null) { - DocumentSymbolHandler subHandler = subComponents.getDocumentSymbolProvider().orElse(null); - if (subHandler != null) { - return subHandler.handle(params); - } + return subComponents.stream() + .map(sc -> sc.getDocumentSymbolProvider()) + .filter(ds -> ds.isPresent()) + .flatMap(ds -> ds.get().handle(params).stream()) + .collect(Collectors.toList()); } //No applicable subEngine... return Collections.emptyList(); @@ -163,14 +224,13 @@ public Optional getDocumentSymbolProvider() { return Optional.ofNullable(docSymbolHandler); } - @SuppressWarnings("unchecked") public C get(Class subComponentsType) { - for (LanguageServerComponents subcomp : this.componentsByLanguageId.values()) { - if (subComponentsType.isInstance(subcomp)) { - return (C) subcomp; - } - } - return null; + return this.componentsByLanguageId.values().stream() + .flatMap(l -> l.stream()) + .filter(subComponentsType::isInstance) + .map(subComponentsType::cast) + .findFirst() + .orElse(null); } @Override @@ -178,4 +238,31 @@ public Optional getCodeActionProvider() { return Optional.of(codeActionHandler); } + @Override + public Optional getCodeLensHandler() { + return Optional.of(codeLensHandler); + } + + @Override + public Optional getInlayHintHandler() { + return Optional.of(inlayHintHandler); + } + + private static TextDocument getDoc(ApplicationContext appContext, String uri) { + + TextDocument doc = appContext.getBean(SimpleLanguageServer.class).getTextDocumentService().getLatestSnapshot(uri); + + if (doc == null) { + LanguageComputer languageComputer = appContext.getBean(LanguageComputer.class); + if (languageComputer != null) { + LanguageId language = languageComputer.computeLanguage(URI.create(uri)); + if (language != null) { + doc = new LazyTextDocument(uri, language); + } + } + } + + return doc; + } + } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/LanguageServerComponents.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/LanguageServerComponents.java index 9925d3113e..257426106f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/LanguageServerComponents.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/LanguageServerComponents.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2022 Pivotal, Inc. + * Copyright (c) 2018, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,15 +15,19 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine; import org.springframework.ide.vscode.commons.languageserver.util.CodeActionHandler; +import org.springframework.ide.vscode.commons.languageserver.util.CodeLensHandler; import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler; import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler; +import org.springframework.ide.vscode.commons.languageserver.util.InlayHintHandler; import org.springframework.ide.vscode.commons.util.text.LanguageId; public interface LanguageServerComponents { Set getInterestingLanguages(); default Optional getReconcileEngine() { return Optional.empty(); } - HoverHandler getHoverProvider(); + default HoverHandler getHoverProvider() { return null; } default Optional getCodeActionProvider() { return Optional.empty(); } default Optional getDocumentSymbolProvider() { return Optional.empty(); } + default Optional getCodeLensHandler() { return Optional.empty(); } + default Optional getInlayHintHandler() { return Optional.empty(); } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ExecuteCommandHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ExecuteCommandHandler.java index 826f4da176..fceb2b74f1 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ExecuteCommandHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ExecuteCommandHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,6 @@ import org.eclipse.lsp4j.ExecuteCommandParams; @FunctionalInterface -public interface ExecuteCommandHandler { - CompletableFuture handle(ExecuteCommandParams params); +public interface ExecuteCommandHandler { + CompletableFuture handle(ExecuteCommandParams params); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/InlayHintHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/InlayHintHandler.java new file mode 100644 index 0000000000..6c9c09f060 --- /dev/null +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/InlayHintHandler.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.languageserver.util; + +import java.util.List; + +import org.eclipse.lsp4j.InlayHint; +import org.eclipse.lsp4j.InlayHintParams; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; + +public interface InlayHintHandler { + + List handle(CancelChecker token, InlayHintParams params); + +} diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index 4745b7c5d9..adec2806ce 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -521,6 +521,9 @@ protected final ServerCapabilities getServerCapabilities() { codeLensOptions.setResolveProvider(hasCodeLensResolveProvider()); c.setCodeLensProvider(codeLensOptions ); } + if (hasInlayHintHandler()) { + c.setInlayHintProvider(true); + } if (hasExecuteCommandSupport && ( hasQuickFixes() || !commands.isEmpty() @@ -566,6 +569,10 @@ private boolean hasDocumentHighlightHandler() { private boolean hasCodeLensHandler() { return getTextDocumentService().hasCodeLensHandler(); } + + private boolean hasInlayHintHandler() { + return getTextDocumentService().hasInlayHintHandler(); + } private boolean hasCodeLensResolveProvider() { return getTextDocumentService().hasCodeLensResolveProvider(); diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java index 06d0b4ee8e..7c0f377f4c 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java @@ -52,6 +52,8 @@ import org.eclipse.lsp4j.DocumentSymbolParams; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.HoverParams; +import org.eclipse.lsp4j.InlayHint; +import org.eclipse.lsp4j.InlayHintParams; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.LocationLink; import org.eclipse.lsp4j.PublishDiagnosticsParams; @@ -119,6 +121,7 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE private CodeLensHandler codeLensHandler; private CodeLensResolveHandler codeLensResolveHandler; private CodeActionHandler codeActionHandler; + private InlayHintHandler inlayHintHandler; final private ApplicationContext appContext; @@ -531,6 +534,18 @@ public CompletableFuture> codeLens(CodeLensParams param } return CompletableFuture.completedFuture(Collections.emptyList()); } + + @Override + public CompletableFuture> inlayHint(InlayHintParams params) { + InlayHintHandler handler = this.inlayHintHandler; + + if (handler != null) { + return CompletableFutures.computeAsync(messageWorkerThreadPool, cancelToken -> { + return handler.handle(cancelToken, params); + }); + } + return CompletableFuture.completedFuture(Collections.emptyList()); + } @Override public CompletableFuture resolveCodeLens(CodeLens unresolved) { @@ -665,10 +680,19 @@ public synchronized void onCodeAction(CodeActionHandler h) { Assert.isNull("A code action handler is already set, multiple handlers not supported yet", codeActionHandler); this.codeActionHandler = h; } + + public synchronized void onInlayHint(InlayHintHandler h) { + Assert.isNull("A inlay hint handler is already set, multiple handlers not supported yet", inlayHintHandler); + this.inlayHintHandler = h; + } public boolean hasCodeLensHandler() { return this.codeLensHandler != null; } + + public boolean hasInlayHintHandler() { + return this.inlayHintHandler != null; + } public synchronized void onCodeLensResolve(CodeLensResolveHandler h) { Assert.isNull("A code lens resolve handler is already set, multiple handlers not supported yet", codeLensResolveHandler); diff --git a/headless-services/commons/commons-lsp-extensions/pom.xml b/headless-services/commons/commons-lsp-extensions/pom.xml index b9b7c8cb28..6bc120c33a 100644 --- a/headless-services/commons/commons-lsp-extensions/pom.xml +++ b/headless-services/commons/commons-lsp-extensions/pom.xml @@ -7,7 +7,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/Gav.java b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/Gav.java new file mode 100644 index 0000000000..6c2afbf66c --- /dev/null +++ b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/Gav.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.protocol.java; + +public record Gav(String groupId, String artifactId, String version) { + +} diff --git a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/ProjectBuild.java b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/ProjectBuild.java index c2caa2a7bc..adb0158943 100644 --- a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/ProjectBuild.java +++ b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/ProjectBuild.java @@ -10,39 +10,24 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.protocol.java; -public class ProjectBuild { +public record ProjectBuild(String type, String buildFile, Gav gav) { public static final String MAVEN_PROJECT_TYPE = "maven"; public static final String GRADLE_PROJECT_TYPE = "gradle"; - private String type; - - private String buildFile; - - public ProjectBuild(String type, String buildFile) { - this.type = type; - this.buildFile = buildFile; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getBuildFile() { - return buildFile; + public static ProjectBuild createMavenBuild(String buildFile, Gav gav) { + return new ProjectBuild(MAVEN_PROJECT_TYPE, buildFile, gav); } - - public void setBuildFile(String buildFile) { - this.buildFile = buildFile; + + public static ProjectBuild createGradleBuild(String buildFile, Gav gav) { + return new ProjectBuild(GRADLE_PROJECT_TYPE, buildFile, gav); } - + @Override public String toString() { - return "ProjectBuild [type=" + type + ", buildFile=" + buildFile + "]"; + return "ProjectBuild [type=" + type + ", buildFile=" + buildFile + "gav=" + gav + "]"; } + + } diff --git a/headless-services/commons/commons-maven/pom.xml b/headless-services/commons/commons-maven/pom.xml index 25171199d4..91e3ac29c9 100644 --- a/headless-services/commons/commons-maven/pom.xml +++ b/headless-services/commons/commons-maven/pom.xml @@ -11,7 +11,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java index 51c9dfc6f1..54e0118790 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2022 Pivotal, Inc. + * Copyright (c) 2016, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,7 @@ import java.io.File; import java.nio.file.Path; +import org.apache.maven.project.MavenProject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.commons.java.ClasspathFileBasedCache; @@ -22,9 +23,13 @@ import org.springframework.ide.vscode.commons.java.LegacyJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.maven.MavenCore; +import org.springframework.ide.vscode.commons.protocol.java.Gav; import org.springframework.ide.vscode.commons.protocol.java.ProjectBuild; import org.springframework.ide.vscode.commons.util.FileObserver; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + /** * Wrapper for Maven Core project * @@ -36,10 +41,13 @@ public class MavenJavaProject extends LegacyJavaProject { private static final Logger log = LoggerFactory.getLogger(MavenJavaProject.class); private final File pom; + + private Supplier gavSupplier; - private MavenJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File pom, JavadocService javadocService) { - super(fileObserver, pom.getParentFile().toURI(), projectDataCache, classpath, javadocService, IProjectBuild.create(ProjectBuild.MAVEN_PROJECT_TYPE, pom.toURI())); + private MavenJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File pom, JavadocService javadocService, Supplier gavSupplier) { + super(fileObserver, pom.getParentFile().toURI(), projectDataCache, classpath, javadocService, IProjectBuild.create(ProjectBuild.MAVEN_PROJECT_TYPE, pom.toURI(), null)); this.pom = pom; + this.gavSupplier = gavSupplier; } public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, Path projectDataCache, JavadocService javadocService) { @@ -51,7 +59,17 @@ public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven () -> new MavenProjectClasspath(maven, pom), fileBasedCache ); - return new MavenJavaProject(fileObserver, projectDataCache, classpath, pom, javadocService); + + + return new MavenJavaProject(fileObserver, projectDataCache, classpath, pom, javadocService, Suppliers.memoize(() -> { + try { + MavenProject p = maven.readProject(pom, false); + return new Gav(p.getGroupId(), p.getArtifactId(), p.getVersion()); + } catch (Exception e) { + log.error("", e); + return null; + } + })); } public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, JavadocService javadocService) { @@ -83,4 +101,10 @@ public File pom() { public String toString() { return "MavenJavaProject("+getElementName()+")"; } + + @Override + public IProjectBuild getProjectBuild() { + return IProjectBuild.create(ProjectBuild.MAVEN_PROJECT_TYPE, pom.toURI(), gavSupplier.get()); + } + } diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java index 532c50a42a..e3812f9fed 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2019 Pivotal, Inc. + * Copyright (c) 2016, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -156,23 +156,24 @@ private ImmutableList resolveClasspathEntries(MavenProject project) throws }); entries.add(cpe); } - { //test/java - File sourceFolder = new File(project.getBuild().getTestSourceDirectory()); - if (sourceFolder.exists()) { - File outputFolder = new File(project.getBuild().getTestOutputDirectory()); - CPE cpe = CPE.source(sourceFolder, outputFolder); - cpe.setOwn(true); - cpe.setTest(true); - cpe.setJavaContent(true); - safe(() -> { - String reportingDir = project.getModel().getReporting().getOutputDirectory(); - if (reportingDir!=null) { - File apidocs = new File(new File(reportingDir), "apidocs"); - cpe.setJavadocContainerUrl(apidocs.toURI().toURL()); - } - }); - entries.add(cpe); - } + { //test/java - duplicated down below without checking if folder exists + +// File sourceFolder = new File(project.getBuild().getTestSourceDirectory()); +// if (sourceFolder.exists()) { +// File outputFolder = new File(project.getBuild().getTestOutputDirectory()); +// CPE cpe = CPE.source(sourceFolder, outputFolder); +// cpe.setOwn(true); +// cpe.setTest(true); +// cpe.setJavaContent(true); +// safe(() -> { +// String reportingDir = project.getModel().getReporting().getOutputDirectory(); +// if (reportingDir!=null) { +// File apidocs = new File(new File(reportingDir), "apidocs"); +// cpe.setJavadocContainerUrl(apidocs.toURI().toURL()); +// } +// }); +// entries.add(cpe); +// } } { //main/resources for (Resource resource : project.getBuild().getResources()) { @@ -207,6 +208,8 @@ private ImmutableList resolveClasspathEntries(MavenProject project) throws File outputFolder = new File(project.getBuild().getTestOutputDirectory()); CPE cpe = CPE.source(sourceFolder, outputFolder); cpe.setOwn(true); + cpe.setTest(true); + cpe.setJavaContent(true); safe(() -> { String reportingDir = project.getModel().getReporting().getOutputDirectory(); if (reportingDir!=null) { diff --git a/headless-services/commons/commons-rewrite-test/pom.xml b/headless-services/commons/commons-rewrite-test/pom.xml index 95bc78c7c2..0c78d2a7fd 100644 --- a/headless-services/commons/commons-rewrite-test/pom.xml +++ b/headless-services/commons/commons-rewrite-test/pom.xml @@ -6,7 +6,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-rewrite/pom.xml b/headless-services/commons/commons-rewrite/pom.xml index ace882986a..632d7f0eef 100644 --- a/headless-services/commons/commons-rewrite/pom.xml +++ b/headless-services/commons/commons-rewrite/pom.xml @@ -7,7 +7,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/gradle/GradleIJavaProjectParser.java b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/gradle/GradleIJavaProjectParser.java index b8f0ea620d..d65f2707af 100644 --- a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/gradle/GradleIJavaProjectParser.java +++ b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/gradle/GradleIJavaProjectParser.java @@ -69,7 +69,7 @@ protected List getJavaProvenance(SourceFile buildFileAst, Path projectDi @Override protected List parseBuildFiles(Path projectDir, ExecutionContext ctx) { OpenRewriteModel openRewriteGradleModel = OpenRewriteModelBuilder.forProjectDirectory(projectDir.toFile(), Paths.get(jp.getProjectBuild().getBuildFile()).toFile()); - GradleProject gradleProject = GradleProject.fromToolingModel(openRewriteGradleModel.gradleProject()); + GradleProject gradleProject = org.openrewrite.gradle.toolingapi.GradleProject.toMarker(openRewriteGradleModel.gradleProject()); GradleParser gradleParser = GradleParser.builder().groovyParser(GroovyParser.builder()).build(); Path buildFilePath = Paths.get(jp.getProjectBuild().getBuildFile()); diff --git a/headless-services/commons/commons-util/pom.xml b/headless-services/commons/commons-util/pom.xml index 77197a6bdf..73169e6597 100644 --- a/headless-services/commons/commons-util/pom.xml +++ b/headless-services/commons/commons-util/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java index 9f3af82fa8..224c034729 100644 --- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 VMware, Inc. + * Copyright (c) 2022, 2024 VMware, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -39,12 +39,6 @@ public LazyTextDocument(String uri, LanguageId languageId) { }); } - @Override - public String get() { - // TODO Auto-generated method stub - return super.get(); - } - @Override protected synchronized Text getText() { if (!loaded) { diff --git a/headless-services/commons/commons-yaml/pom.xml b/headless-services/commons/commons-yaml/pom.xml index 9f8f444284..94202a9b85 100644 --- a/headless-services/commons/commons-yaml/pom.xml +++ b/headless-services/commons/commons-yaml/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java index 7844dd5f8a..62d72d0dcd 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2016 Pivotal, Inc. + * Copyright (c) 2015, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; import java.util.stream.Stream; import org.springframework.ide.vscode.commons.yaml.ast.NodeRef; @@ -22,6 +24,8 @@ import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.YamlPathSegmentType; +import com.google.common.collect.ImmutableList; + import reactor.core.publisher.Flux; /** @@ -74,14 +78,49 @@ public YamlPathSegment[] getSegments() { * Parse a YamlPath from a dotted property name. The segments are obtained * by spliting the name at each dot. */ +// public static YamlPath fromProperty(String propName) { +// ArrayList segments = new ArrayList(); +// for (String s : propName.split("\\.")) { +// segments.add(YamlPathSegment.valueAt(s)); +// } +// return new YamlPath(segments); +// } + /** + * Parse a YamlPath from a dotted property name. The segments are obtained + * by splitting the name at each dot. + */ public static YamlPath fromProperty(String propName) { - ArrayList segments = new ArrayList(); - for (String s : propName.split("\\.")) { - segments.add(YamlPathSegment.valueAt(s)); + ImmutableList.Builder segments = ImmutableList.builder(); + String delim = ".[]"; + StringTokenizer tokens = new StringTokenizer(propName, delim, true); + try { + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken(delim); + if (token.equals(".") || token.equals("]")) { + //Skip it silently + } else if (token.equals("[")) { + String bracketed = tokens.nextToken("]"); + if (bracketed.equals("]")) { + //empty string between []? Makes no sense, so ignore that. + } else { + try { + int index = Integer.parseInt(bracketed); + segments.add(YamlPathSegment.valueAt(index)); + } catch (NumberFormatException e) { + segments.add(YamlPathSegment.valueAt(bracketed)); + } + } + } else { + segments.add(YamlPathSegment.valueAt(token)); + } + } + } catch (NoSuchElementException e) { + //Ran out of tokens. } - return new YamlPath(segments); + return new YamlPath(segments.build()); } + /** * Create a YamlPath with a single segment (i.e. like 'fromProperty', but does * not parse '.' as segment separators. diff --git a/headless-services/commons/java-properties/pom.xml b/headless-services/commons/java-properties/pom.xml index 8fd9359404..94775e0b41 100644 --- a/headless-services/commons/java-properties/pom.xml +++ b/headless-services/commons/java-properties/pom.xml @@ -7,7 +7,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/language-server-starter/pom.xml b/headless-services/commons/language-server-starter/pom.xml index f25e94b7d8..9dd731d5e1 100644 --- a/headless-services/commons/language-server-starter/pom.xml +++ b/headless-services/commons/language-server-starter/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/language-server-test-harness/pom.xml b/headless-services/commons/language-server-test-harness/pom.xml index a663d890a2..c57e09e46e 100644 --- a/headless-services/commons/language-server-test-harness/pom.xml +++ b/headless-services/commons/language-server-test-harness/pom.xml @@ -8,7 +8,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../pom.xml diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java index cbcf3fd7e0..1703111c87 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java @@ -621,20 +621,24 @@ public String hoverString(Hover hover) { StringBuilder buf = new StringBuilder(); boolean first = true; Either>, MarkupContent> contents = hover.getContents(); - for (Either block : contents.getLeft()) { - if (!first) { - buf.append("\n\n"); - } - if (block.isLeft()) { - String s = block.getLeft(); - buf.append(s); - } else if (block.isRight()) { - MarkedString ms = block.getRight(); - buf.append("```"+ms.getLanguage()+"\n"); - buf.append(ms.getValue()); - buf.append("\n```"); + if (contents.isLeft()) { + for (Either block : contents.getLeft()) { + if (!first) { + buf.append("\n\n"); + } + if (block.isLeft()) { + String s = block.getLeft(); + buf.append(s); + } else if (block.isRight()) { + MarkedString ms = block.getRight(); + buf.append("```"+ms.getLanguage()+"\n"); + buf.append(ms.getValue()); + buf.append("\n```"); + } + first = false; } - first = false; + } else { + buf.append(contents.getRight().getValue()); } return buf.toString(); } diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java index 8287f9370a..c1bd119406 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2023 Pivotal, Inc. + * Copyright (c) 2016, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -87,6 +87,8 @@ import org.eclipse.lsp4j.RenameFile; import org.eclipse.lsp4j.ResourceOperation; import org.eclipse.lsp4j.ResourceOperationKind; +import org.eclipse.lsp4j.ShowDocumentParams; +import org.eclipse.lsp4j.ShowDocumentResult; import org.eclipse.lsp4j.ShowMessageRequestParams; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.TextDocumentClientCapabilities; @@ -442,6 +444,11 @@ public void indexUpdated() { public void liveProcessLogLevelUpdated(LiveProcessLoggersSummary processKey) { } + @Override + public CompletableFuture showDocument(ShowDocumentParams params) { + return CompletableFuture.completedFuture(new ShowDocumentResult(true)); + } + }); } @@ -810,15 +817,14 @@ public List getCodeActions(TextDocumentInfo doc, Range range, Diagno .collect(Collectors.toList()); } - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void perform(Command command) throws Exception { + public Object perform(Command command) throws Exception { List args = command.getArguments(); //Note convert the params to a 'typeless' Object because that is more representative on how it will be // received when we get it in a real client/server setting (i.e. parsed from json). JsonArray jsonArray = gson.toJsonTree(args).getAsJsonArray(); List untypedParams = new ArrayList<>(jsonArray.size()); jsonArray.forEach(e -> untypedParams.add(e)); - getServer().getWorkspaceService() + return getServer().getWorkspaceService() .executeCommand(new ExecuteCommandParams(command.getCommand(), untypedParams)) .get(); } diff --git a/headless-services/commons/pom.xml b/headless-services/commons/pom.xml index 534da5b6c9..1ec446ae96 100644 --- a/headless-services/commons/pom.xml +++ b/headless-services/commons/pom.xml @@ -7,13 +7,13 @@ org.springframework.ide.vscode commons-parent pom - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT commons-parent org.springframework.boot spring-boot-starter-parent - 3.2.2 + 3.2.3 @@ -118,10 +118,10 @@ 1.9.20 - 8.15.2 - 1.11.3 - 5.4.0 - 1.5.1 + 8.19.0 + 1.11.4 + 5.5.0 + 2.0.0 8.5 6.1.1 diff --git a/headless-services/concourse-language-server/pom.xml b/headless-services/concourse-language-server/pom.xml index c54d54c244..5bf4cf6223 100644 --- a/headless-services/concourse-language-server/pom.xml +++ b/headless-services/concourse-language-server/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/META-INF/MANIFEST.MF b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/META-INF/MANIFEST.MF index 55226e5d20..af9dafd4fd 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/META-INF/MANIFEST.MF +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Commons Bundle-SymbolicName: org.springframework.tooling.jdt.ls.commons.test -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Automatic-Module-Name: org.springframework.tooling.jdt.ls.commons.test Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.springframework.tooling.jdt.ls.commons, diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/pom.xml b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/pom.xml index 340518cc26..a1018ee65a 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/pom.xml +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons.test/pom.xml @@ -5,7 +5,7 @@ eclipse-test-plugin org.springframework.ide.vscode org.springframework.tooling.jdt.ls.commons.test - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT org.springframework.tooling.jdt.ls.commons.test diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/.classpath b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/.classpath index 3e9b046bcf..1ee696c636 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/.classpath +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/.classpath @@ -1,8 +1,8 @@ - - - + + + diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/META-INF/MANIFEST.MF b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/META-INF/MANIFEST.MF index 096852bda1..89803825a5 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/META-INF/MANIFEST.MF +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Client-side JDT extension for language servers Bundle-SymbolicName: org.springframework.tooling.jdt.ls.commons -Bundle-Version: 4.22.0.qualifier +Bundle-Version: 4.22.1.qualifier Bundle-Vendor: Broadcom Automatic-Module-Name: org.springframework.tooling.jdt.ls.commons Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -13,7 +13,9 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.lsp4j, org.eclipse.lsp4j.jsonrpc, io.projectreactor.reactor-core, - org.reactivestreams.reactive-streams + org.reactivestreams.reactive-streams, + org.eclipse.m2e.core, + org.eclipse.buildship.core Export-Package: org.springframework.ide.vscode.commons.protocol, org.springframework.ide.vscode.commons.protocol.java, org.springframework.ide.vscode.commons.protocol.spring, diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/pom.xml b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/pom.xml index d1f16f8e11..af15c99d93 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/pom.xml +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/pom.xml @@ -5,7 +5,7 @@ eclipse-plugin org.springframework.ide.vscode org.springframework.tooling.jdt.ls.commons - 4.22.0-SNAPSHOT + 4.22.1-SNAPSHOT org.springframework.tooling.jdt.ls.commons @@ -19,7 +19,7 @@ org.springframework.ide.vscode commons-lsp-extensions - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java index 961d4e85e6..836ff6be69 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java @@ -24,6 +24,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import org.eclipse.buildship.core.internal.configuration.GradleProjectNature; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; @@ -36,16 +37,19 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.JavaProject; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.embedder.ArtifactKey; +import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.springframework.ide.vscode.commons.protocol.java.Classpath; import org.springframework.ide.vscode.commons.protocol.java.Classpath.CPE; +import org.springframework.ide.vscode.commons.protocol.java.Gav; import org.springframework.ide.vscode.commons.protocol.java.ProjectBuild; import org.springframework.tooling.jdt.ls.commons.Logger; +@SuppressWarnings("restriction") public class ClasspathUtil { private static final Object JRE_CONTAINER_ID = "org.eclipse.jdt.launching.JRE_CONTAINER"; - private static final String GRADLE_CONTAINER_ID = "org.eclipse.buildship.core.gradleclasspathcontainer"; - private static final String MAVEN_CONTAINER_ID = "org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"; private static Set getSystemLibraryPaths(IJavaProject javaProject) { try { @@ -222,36 +226,40 @@ private static String toContentKind(IClasspathEntry entry) { } public static ProjectBuild createProjectBuild(IJavaProject jp) { - try { +// try { boolean likelyGradle = false; boolean likelyMaven = false; final Path home = System.getProperty("user.home") == null ? null : new File(System.getProperty("user.home")).toPath(); - for (IClasspathEntry e : jp.getRawClasspath()) { - switch (e.getPath().segment(0)) { - case MAVEN_CONTAINER_ID: - IFile f = jp.getProject().getFile("pom.xml"); - return new ProjectBuild(ProjectBuild.MAVEN_PROJECT_TYPE, f.exists() ? f.getLocationURI().toASCIIString() : null); - case GRADLE_CONTAINER_ID: - IFile g = jp.getProject().getFile("build.gradle"); - if (!g.exists()) { - g = jp.getProject().getFile("build.gradle.kts"); - } - return new ProjectBuild(ProjectBuild.GRADLE_PROJECT_TYPE, g.exists() ? g.getLocationURI().toASCIIString() : null); - default: - if (home != null && e.getPath() != null && e.getPath().toFile() != null) { - Path path = e.getPath().toFile().toPath(); - if (path.startsWith(home.resolve(".gradle"))) { - likelyGradle = true; - } else if (path.startsWith(home.resolve(".m2"))) { - likelyMaven = true; + if (MavenPlugin.isMavenProject(jp.getProject())) { + IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().getProject(jp.getProject()); + ArtifactKey artifact = facade.getArtifactKey(); + return ProjectBuild.createMavenBuild(facade.getPom().getLocationURI().toASCIIString(), new Gav(artifact.groupId(), artifact.artifactId(), artifact.version())); + } else if (GradleProjectNature.isPresentOn(jp.getProject())) { + IFile g = jp.getProject().getFile("build.gradle"); + if (!g.exists()) { + g = jp.getProject().getFile("build.gradle.kts"); + } + return new ProjectBuild(ProjectBuild.GRADLE_PROJECT_TYPE, g.exists() ? g.getLocationURI().toASCIIString() : null, null); + } else { + try { + for (IClasspathEntry e : jp.getRawClasspath()) { + if (home != null && e.getPath() != null && e.getPath().toFile() != null) { + Path path = e.getPath().toFile().toPath(); + if (path.startsWith(home.resolve(".gradle"))) { + likelyGradle = true; + } else if (path.startsWith(home.resolve(".m2"))) { + likelyMaven = true; + } } } + } catch (Exception e) { + // ignore } } if (likelyMaven) { IFile f = jp.getProject().getFile("pom.xml"); if (f.exists()) { - return new ProjectBuild(ProjectBuild.MAVEN_PROJECT_TYPE, f.getLocationURI().toASCIIString()); + return ProjectBuild.createMavenBuild(f.getLocationURI().toASCIIString(), null); } } else if (likelyGradle) { IFile g = jp.getProject().getFile("build.gradle"); @@ -259,12 +267,12 @@ public static ProjectBuild createProjectBuild(IJavaProject jp) { g = jp.getProject().getFile("build.gradle.kts"); } if (g.exists()) { - return new ProjectBuild(ProjectBuild.GRADLE_PROJECT_TYPE, g.getLocationURI().toASCIIString()); + return ProjectBuild.createGradleBuild(g.getLocationURI().toASCIIString(), null); } } - } catch (JavaModelException e) { - // ignore - } - return new ProjectBuild(null, null); +// } catch (JavaModelException e) { +// // ignore +// } + return new ProjectBuild(null, null, null); } } diff --git a/headless-services/manifest-yaml-language-server/pom.xml b/headless-services/manifest-yaml-language-server/pom.xml index 919a902c72..909adc0a54 100644 --- a/headless-services/manifest-yaml-language-server/pom.xml +++ b/headless-services/manifest-yaml-language-server/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/spring-boot-language-server/pom.xml b/headless-services/spring-boot-language-server/pom.xml index b12de4e706..170c8b25b3 100644 --- a/headless-services/spring-boot-language-server/pom.xml +++ b/headless-services/spring-boot-language-server/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../commons/pom.xml diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java index 1954686e5f..169cebe218 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -91,6 +91,11 @@ public boolean isScanJavaTestSourcesEnabled() { return enabled != null && enabled.booleanValue(); } + public boolean isModulithAutoProjectTrackingEnabled() { + Boolean enabled = settings.getBoolean("boot-java", "modulith-project-tracking"); + return enabled != null && enabled.booleanValue(); + } + public String[] xmlBeansFoldersToScan() { String foldersStr = settings.getString("boot-java", "support-spring-xml-config", "scan-folders"); if (foldersStr != null) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java index 431c206783..3f0ae69407 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2023 Pivotal, Inc. + * Copyright (c) 2018, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,8 +29,10 @@ import org.springframework.ide.vscode.boot.java.links.SourceLinks; import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveDataProvider; import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache; +import org.springframework.ide.vscode.boot.maven.PomLanguageServerComponents; import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider; import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents; +import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider; import org.springframework.ide.vscode.boot.xml.SpringXMLLanguageServerComponents; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.completion.CompositeCompletionEngine; @@ -119,14 +121,15 @@ public void afterPropertiesSet() throws Exception { new BootPropertiesLanguageServerComponents(server, params, javaElementLocationProvider, parser, yamlStructureProvider, yamlAssistContextProvider, sourceLinks), new BootJavaLanguageServerComponents(appContext), new SpringXMLLanguageServerComponents(server, springIndexer, params, config), - new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer, config) + new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer, config), + new PomLanguageServerComponents(server, projectFinder, params.projectObserver, appContext.getBean(SpringProjectsProvider.class)) ); for (LanguageServerComponents c : componentsList) { builder.add(c); } - components = builder.build(server); + components = builder.build(appContext); final SimpleTextDocumentService documents = server.getTextDocumentService(); @@ -144,7 +147,11 @@ public void afterPropertiesSet() throws Exception { components.getCodeActionProvider().ifPresent(documents::onCodeAction); + components.getCodeLensHandler().ifPresent(documents::onCodeLens); + components.getDocumentSymbolProvider().ifPresent(documents::onDocumentSymbol); + + components.getInlayHintHandler().ifPresent(documents::onInlayHint); startListeningToPerformReconcile(); @@ -164,8 +171,7 @@ public void afterPropertiesSet() throws Exception { documents.publishDiagnostics(d.getId(), Collections.emptyList()); } }); - - + } private void startListeningToPerformReconcile() { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/CommandsConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/CommandsConfig.java new file mode 100644 index 0000000000..dd84921707 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/CommandsConfig.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.app; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.ide.vscode.boot.java.commands.WorkspaceBootExecutableProjects; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; + +@Configuration(proxyBeanMethods = false) +public class CommandsConfig { + + @Bean WorkspaceBootExecutableProjects workspaceBootProjects(SimpleLanguageServer server, JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex) { + return new WorkspaceBootExecutableProjects(server, projectFinder, symbolIndex); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java index b13a24927d..783b6932fc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java @@ -174,7 +174,6 @@ public BootJavaLanguageServerComponents(ApplicationContext appContext) { sourceLinks); codeLensHandler = createCodeLensEngine(indexer); - documents.onCodeLens(codeLensHandler); highlightsEngine = createDocumentHighlightEngine(indexer); documents.onDocumentHighlight(highlightsEngine); @@ -218,8 +217,8 @@ public HoverHandler getHoverProvider() { return hoverProvider; } - public CodeLensHandler getCodeLensHandler() { - return codeLensHandler; + public Optional getCodeLensHandler() { + return Optional.of(codeLensHandler); } public DocumentHighlightHandler getDocumentHighlightHandler() { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjects.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjects.java new file mode 100644 index 0000000000..d5f1951fb5 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjects.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.commands; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.boot.app.SpringSymbolIndex; +import org.springframework.ide.vscode.boot.java.Annotations; +import org.springframework.ide.vscode.commons.java.IGav; +import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.java.SpringProjectUtil; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.protocol.java.Classpath; +import org.springframework.ide.vscode.commons.protocol.spring.Bean; +import org.springframework.ide.vscode.commons.protocol.spring.BeansParams; + +public class WorkspaceBootExecutableProjects { + + public record ExecutableProject(String name, String uri, String gav, String mainClass, Collection classpath) {} + + final static String CMD = "sts/spring-boot/executableBootProjects"; + + private final static Logger log = LoggerFactory.getLogger(WorkspaceBootExecutableProjects.class); + + final private JavaProjectFinder projectFinder; + final private SpringSymbolIndex symbolIndex; + + public WorkspaceBootExecutableProjects(SimpleLanguageServer server, JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex) { + this.projectFinder = projectFinder; + this.symbolIndex = symbolIndex; + server.onCommand(CMD, params -> findExecutableProjects()); + } + + private CompletableFuture> mapToExecProject(IJavaProject project) { + BeansParams params = new BeansParams(); + params.setProjectName(project.getElementName()); + return symbolIndex.beans(params).thenApply(beans -> { + List bootAppBeans = beans.stream() + .filter(b -> Arrays.asList(b.getAnnotations()).contains(Annotations.BOOT_APP)) + .limit(2) + .collect(Collectors.toList()); + if (bootAppBeans.size() == 1) { + try { + Bean appBean = bootAppBeans.get(0); + Collection classpath = project.getClasspath().getClasspathEntries().stream() + .filter(cpe -> !cpe.isTest() && !cpe.isSystem()) + .map(cpe -> Classpath.isSource(cpe) ? cpe.getOutputFolder() : cpe.getPath()) + .collect(Collectors.toSet()); + IGav gav = project.getProjectBuild().getGav(); + String gavStr = "%s:%s:%s".formatted(gav.getGroupId(), gav.getArtifactId(), gav.getVersion()); + return Optional.of(new ExecutableProject(project.getElementName(), project.getLocationUri().toASCIIString(), gavStr, appBean.getType(), classpath)); + } catch (Exception e) { + log.error("", e); + } + } + return Optional.empty(); + }); + } + + private CompletableFuture> findExecutableProjects() { + List>> futures = projectFinder.all().stream() + .filter(p -> p.getProjectBuild().getGav() != null) + .filter(p -> SpringProjectUtil.isBootProject(p)) + .map(this::mapToExecProject) + .collect(Collectors.toList()); + List executableProjects = Collections.synchronizedList(new ArrayList<>()); + futures.forEach(f -> f.thenAccept(opt -> opt.ifPresent(executableProjects::add))); + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).thenApply(v -> executableProjects); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReconcileEngine.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReconcileEngine.java index aa33a4b837..1f466d8063 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReconcileEngine.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReconcileEngine.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.handlers; +import java.net.URI; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.lsp4j.TextDocumentIdentifier; @@ -41,7 +42,8 @@ public BootJavaReconcileEngine(JavaProjectFinder projectFinder, JavaReconciler[] @Override public void reconcile(final IDocument doc, final IProblemCollector problemCollector) { IJavaProject project = projectFinder.find(new TextDocumentIdentifier(doc.getUri())).orElse(null); - if (project != null) { + URI docUri = URI.create(doc.getUri()); + if (project != null && "file".equals(docUri.getScheme())) { try { problemCollector.beginCollecting(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java index 6158985c28..f69d6149f6 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,8 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -26,8 +28,9 @@ import org.eclipse.lsp4j.CodeLens; import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.Hover; +import org.eclipse.lsp4j.MarkupContent; +import org.eclipse.lsp4j.MarkupKind; import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.handlers.HoverProvider; @@ -37,12 +40,14 @@ import org.springframework.ide.vscode.boot.java.livehover.v2.RequestMappingMetrics; import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveData; import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.languageserver.util.LspClient; import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.Renderables; import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; import reactor.util.function.Tuple2; import reactor.util.function.Tuples; @@ -286,7 +291,15 @@ private Hover createHoverWithContent(List renderableUrls = Arrays.stream(paths).flatMap(path -> { String url = UrlUtil.createUrl(urlScheme, host, port, path, contextPath); - return Stream.of(Renderables.link(url, url), Renderables.lineBreak()); + String text = url; + switch (LspClient.currentClient()) { + case VSCODE: + case THEIA: + url = "command:vscode-spring-boot.open.url?%s".formatted(URLEncoder.encode(new Gson().toJson(url), StandardCharsets.UTF_8)); + break; + default: + } + return Stream.of(Renderables.link(text, url), Renderables.lineBreak()); }) .collect(Collectors.toList()); @@ -318,7 +331,7 @@ private Hover createHoverWithContent(List loadRecipes() { recipes.put(r.getName(), r); // HACK: add Jakarta XML Bind migration recipe again as there are cases when maven dependency isn't added if (r.getName().startsWith("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_")) { - AddDependency addDepXmlBindDep = new AddDependency("jakarta.xml.bind", "jakarta.xml.bind-api", "latest.release", null, null, null, "javax.xml.bind..*", null, null, null, null, true); + AddDependency addDepXmlBindDep = new AddDependency("jakarta.xml.bind", "jakarta.xml.bind-api", "latest.release", null, null, null, "javax.xml.bind..*", null, null, null, null, false); r.getDescriptor().getRecipeList().add(addDepXmlBindDep.getDescriptor()); r.getRecipeList().add(addDepXmlBindDep); } @@ -423,13 +423,12 @@ CompletableFuture> computeWorkspaceEditAwareOfPreview(Re String changeAnnotationId = UUID.randomUUID().toString(); Optional we = computeWorkspaceEdit(r, sources, progressTask, changeAnnotationId); if (we.isPresent()) { - CompletableFuture editFuture = askForPreview ? askForPreview(we.get(), changeAnnotationId) : CompletableFuture.completedFuture(we.get()); - return editFuture.thenApply(Optional::of); + return askForPreview ? askForPreview(we.get(), changeAnnotationId) : CompletableFuture.completedFuture(we); } return CompletableFuture.completedFuture(Optional.empty()); } - private CompletableFuture askForPreview(WorkspaceEdit workspaceEdit, String changeAnnotationId) { + private CompletableFuture> askForPreview(WorkspaceEdit workspaceEdit, String changeAnnotationId) { return server.getClientCapabilities().thenApply(capabilities -> { WorkspaceEditChangeAnnotationSupportCapabilities changeAnnotationSupport = capabilities.getWorkspace().getWorkspaceEdit().getChangeAnnotationSupport(); return changeAnnotationSupport != null && changeAnnotationSupport.getGroupsOnLabel() != null && changeAnnotationSupport.getGroupsOnLabel().booleanValue(); @@ -439,17 +438,25 @@ private CompletableFuture askForPreview(WorkspaceEdit workspaceEd final MessageActionItem applyChanges = new MessageActionItem("Apply"); ShowMessageRequestParams messageParams = new ShowMessageRequestParams(); messageParams.setType(MessageType.Info); - messageParams.setMessage("Do you want to preview chnages before applying or apply right away?"); + messageParams.setMessage("Do you want to preview changes before applying or apply right away?"); messageParams.setActions(List.of(applyChanges, previewChanges)); - return server.getClient().showMessageRequest(messageParams).thenApply(previewChanges::equals); + return server.getClient().showMessageRequest(messageParams).thenApply(ma -> { + if (previewChanges.equals(ma) ) { + return Optional.of(true); + } else if (applyChanges.equals(ma)) { + return Optional.of(false); + } else { + return Optional.empty(); + } + }); } else { - return CompletableFuture.completedFuture(false); + return CompletableFuture.completedFuture(Optional.of(false)); } - }).thenApply(needsConfirmation -> { + }).thenApply(optNeedsConfirmation -> optNeedsConfirmation.map(needsConfirmation -> { ChangeAnnotation changeAnnotation = workspaceEdit.getChangeAnnotations().get(changeAnnotationId); changeAnnotation.setNeedsConfirmation(needsConfirmation); return workspaceEdit; - }); + })); } private CompletableFuture applyEdit(Optional we, IndefiniteProgressTask progressTask, String title) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java index a99deea8ff..4567e22d66 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java @@ -18,6 +18,7 @@ import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -238,8 +239,9 @@ public T withCompilationUnit(IJavaProject project, URI uri, Function requestCU(IJavaProject project, URI uri) throws ExecutionException { - return uriToCu.get(uri, () -> { - CompletableFuture future = CompletableFuture.supplyAsync(() -> { + CompletableFuture cuFuture = uriToCu.getIfPresent(uri); + if (cuFuture == null) { + cuFuture = CompletableFuture.supplyAsync(() -> { try { logger.info("Started parsing CU for " + uri); @@ -252,17 +254,25 @@ private synchronized CompletableFuture requestCU(IJavaProject p logger.info("Parsed successfully CU for " + uri); return cUnit; - } catch (Exception e) { - logger.warn("exception happened during parsing CU for " + uri + ": " + e); - return null; + } catch (Throwable t) { + // Complete future exceptionally + throw new CompletionException(t); } }, createCuExecutorThreadPool); - return future; - - }); + // Cache the future + uriToCu.put(uri, cuFuture); + // If CU future completed exceptionally invalidate the cache entry + cuFuture.exceptionally(t -> { + if (!(t instanceof CancellationException)) { + logger.error("", t); + } + uriToCu.invalidate(uri); + return null; + }); + } + return cuFuture; } - public static CompilationUnit parse2(char[] source, String docURI, String unitName, IJavaProject project) throws Exception { List classpaths = createClasspath(getClasspathEntries(project)); return parse2(source, docURI, unitName, classpaths, null); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java index a550dae7ea..8da636e52d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2023 Pivotal, Inc. + * Copyright (c) 2018, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -385,7 +385,7 @@ public void changed(Event event) { } private static IProjectBuild from(ProjectBuild projectBuild) { - return projectBuild == null ? null : IProjectBuild.create(projectBuild.getType(), projectBuild.getBuildFile() == null ? null : URI.create(projectBuild.getBuildFile())); + return projectBuild == null ? null : IProjectBuild.create(projectBuild.type(), projectBuild.buildFile() == null ? null : URI.create(projectBuild.buildFile()), projectBuild.gav()); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandler.java new file mode 100644 index 0000000000..4fe8c999ae --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandler.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.maven; + +import java.net.URI; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.dom.DOMElement; +import org.eclipse.lemminx.dom.DOMParser; +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.InlayHint; +import org.eclipse.lsp4j.InlayHintKind; +import org.eclipse.lsp4j.InlayHintLabelPart; +import org.eclipse.lsp4j.InlayHintParams; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.boot.validation.generations.GenerationsValidator; +import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider; +import org.springframework.ide.vscode.boot.validation.generations.VersionValidationUtils; +import org.springframework.ide.vscode.boot.validation.generations.json.Generation; +import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject; +import org.springframework.ide.vscode.commons.Version; +import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.java.SpringProjectUtil; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; +import org.springframework.ide.vscode.commons.languageserver.util.InlayHintHandler; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.util.text.TextDocument; + +public class PomInlayHintHandler implements InlayHintHandler { + + private static final String POM_XML = "pom.xml"; + + private static final Logger log = LoggerFactory.getLogger(PomInlayHintHandler.class); + + final private SimpleLanguageServer server; + final private JavaProjectFinder projectFinder; + final private SpringProjectsProvider generationsProvider; + + public PomInlayHintHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder, ProjectObserver projectObserver, SpringProjectsProvider generationsProvider) { + this.server = server; + this.projectFinder = projectFinder; + this.generationsProvider = generationsProvider; + + projectObserver.addListener(new ProjectObserver.Listener() { + + private void refreshOpenDocs(IJavaProject project) { + if (project.getProjectBuild() != null && project.getProjectBuild().getBuildFile() != null ) { + URI projectBuildFileUri = project.getProjectBuild().getBuildFile(); + if (projectBuildFileUri.toString().endsWith(POM_XML)) { + server.getTextDocumentService().getAll().stream() + .map(doc -> URI.create(doc.getId().getUri())) + .filter(projectBuildFileUri::equals) + .findFirst().ifPresent(docPath -> { + server.getClient().refreshInlayHints(); + }); + } + } + } + + @Override + public void deleted(IJavaProject project) { + refreshOpenDocs(project); + } + + @Override + public void created(IJavaProject project) { + refreshOpenDocs(project); + } + + @Override + public void changed(IJavaProject project) { + refreshOpenDocs(project); + } + }); + + } + + @Override + public List handle(CancelChecker token, InlayHintParams params) { + URI uri = URI.create(params.getTextDocument().getUri()); + if ("file".equals(uri.getScheme()) && POM_XML.equals(Paths.get(uri).getFileName().toString())) { + + Optional projectOpt = projectFinder.find(params.getTextDocument()); + if (projectOpt.isPresent()) { + + URI buildFileUri = projectOpt.get().getProjectBuild().getBuildFile(); + + if (buildFileUri.equals(uri) && SpringProjectUtil.isBootProject(projectOpt.get())) { + Version currentVersion = SpringProjectUtil.getSpringBootVersion(projectOpt.get()); + if (currentVersion != null) { + try { + ResolvedSpringProject genProject = generationsProvider.getProject(SpringProjectUtil.SPRING_BOOT); + if (genProject != null) { + Generation generation = GenerationsValidator.getGenerationForJavaProject(projectOpt.get(), genProject); + if (generation != null && VersionValidationUtils.isOssValid(generation)) { + TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri()); + + if (doc != null) { + String content = doc.get(); + + if (!content.isEmpty()) { + // if doc is not empty, dive into the details and provide more sophisticated content assist proposals + DOMParser parser = DOMParser.getInstance(); + DOMDocument dom = parser.parse(content, "", null); + + DOMElement project = dom.getDocumentElement(); + if (project != null && "project".equals(project.getTagName())) { + for (int j = 0; j < project.getChildNodes().getLength(); j++) { + var child = project.getChildNodes().item(j); + if ("dependencies".equals(child.getNodeName()) && child instanceof DOMElement dependencies) { + try { + Command command = new Command(); + command.setTitle("Add Spring Boot Starters"); + command.setCommand("spring.initializr.addStarters"); + + InlayHintLabelPart label = new InlayHintLabelPart("Add Spring Boot Starters..."); + label.setCommand(command); + + InlayHint hint = new InlayHint(); + hint.setPosition(doc.toPosition(dependencies.getStartTagCloseOffset() + 1)); + hint.setKind(InlayHintKind.Parameter); + hint.setPaddingLeft(true); + hint.setLabel(List.of(label)); + + return List.of(hint); + } catch (Exception e) { + log.error("", e); + break; + } + } + } + } + + + } + } + } + } + } catch (Exception e) { + log.error("", e); + } + + } + } + } + + } + return Collections.emptyList(); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomLanguageServerComponents.java new file mode 100644 index 0000000000..2c317a6fe6 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/maven/PomLanguageServerComponents.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.maven; + +import java.util.Optional; +import java.util.Set; + +import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider; +import org.springframework.ide.vscode.commons.languageserver.composable.LanguageServerComponents; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; +import org.springframework.ide.vscode.commons.languageserver.util.InlayHintHandler; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.util.text.LanguageId; + +public class PomLanguageServerComponents implements LanguageServerComponents{ + + private PomInlayHintHandler inlayHintHandler; + + public PomLanguageServerComponents(SimpleLanguageServer server, JavaProjectFinder projectFinder, ProjectObserver projectObserver, SpringProjectsProvider generationsProvider) { + this.inlayHintHandler = new PomInlayHintHandler(server, projectFinder, projectObserver, generationsProvider); + } + + @Override + public Set getInterestingLanguages() { + return Set.of(LanguageId.XML); + } + + @Override + public Optional getInlayHintHandler() { + return Optional.of(inlayHintHandler); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java index 091367b750..aa99c785e9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java @@ -76,11 +76,15 @@ public class ModulithService { private static final String CMD_LIST_MODULITH_PROJECTS = "sts/modulith/projects"; private final ExecutorService executor; + private final ProjectObserver.Listener projectListener; + private final ProjectObserver projectObserver; + private final JavaProjectFinder projectFinder; private SimpleLanguageServer server; private SpringSymbolIndex springIndex; private BootJavaReconcileEngine reconciler; private BootJavaConfig config; + private boolean autoTrackingProjects; private Map cache; private Map> metadataRequested; @@ -94,6 +98,8 @@ public ModulithService( BootJavaReconcileEngine reconciler, BootJavaConfig config ) { + this.projectFinder = projectFinder; + this.projectObserver = projectObserver; this.config = config; this.cache = new ConcurrentHashMap<>(); this.metadataRequested = new ConcurrentHashMap<>(); @@ -102,8 +108,9 @@ public ModulithService( this.springIndex = springIndex; this.reconciler = reconciler; this.executor = Executors.newCachedThreadPool(); + this.autoTrackingProjects = false; - projectObserver.addListener(new ProjectObserver.Listener() { + this.projectListener = new ProjectObserver.Listener() { @Override public void deleted(IJavaProject project) { @@ -113,13 +120,7 @@ public void deleted(IJavaProject project) { @Override public void created(IJavaProject project) { - if (isModulithDependentProject(project)) { - if (anyClassFilesPresent(project)) { - requestMetadata(project, DEBOUNCE_TIME).thenAccept(res -> startListening(project)); - } else { - startListening(project); - } - } + projectAdded(project); } @Override @@ -135,7 +136,7 @@ public void changed(IJavaProject project) { } } } - }); + }; server.onCommand(CMD_MODULITH_REFRESH, params -> { String uri = ((JsonElement) params.getArguments().get(0)).getAsString(); @@ -150,6 +151,31 @@ public void changed(IJavaProject project) { ); }); + config.addListener(v -> setAutoTrackingProjects(config.isModulithAutoProjectTrackingEnabled())); + + } + + private void projectAdded(IJavaProject project) { + if (isModulithDependentProject(project)) { + if (anyClassFilesPresent(project)) { + requestMetadata(project, DEBOUNCE_TIME).thenAccept(res -> startListening(project)); + } else { + startListening(project); + } + } + } + + private void setAutoTrackingProjects(boolean autoTrackingProjects) { + if (this.autoTrackingProjects != autoTrackingProjects) { + this.autoTrackingProjects = autoTrackingProjects; + if (autoTrackingProjects) { + projectObserver.addListener(projectListener); + projectFinder.all().forEach(this::projectAdded); + } else { + projectObserver.removeListener(projectListener); + projectFinder.all().forEach(this::stopListening); + } + } } private boolean startListening(IJavaProject project) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/BootPropertiesLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/BootPropertiesLanguageServerComponents.java index 99cd8658d0..51251ed4c9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/BootPropertiesLanguageServerComponents.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/BootPropertiesLanguageServerComponents.java @@ -105,7 +105,12 @@ public BootPropertiesLanguageServerComponents( }); }); }); - + + // Register YAML -> Props conversion command + new YamlToPropertiesCommand(server); + + // Register Props -> YAML conversion command + new PropertiesToYamlCommand(server); } @Override diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommand.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommand.java new file mode 100644 index 0000000000..5c28323862 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommand.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.regex.Pattern; + +import org.eclipse.lsp4j.ApplyWorkspaceEditParams; +import org.eclipse.lsp4j.ShowDocumentParams; +import org.eclipse.lsp4j.ShowDocumentResult; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.LazyTextDocument; +import org.springframework.ide.vscode.commons.util.text.TextDocument; + +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.gson.JsonElement; +import com.google.gson.internal.LinkedTreeMap; + +public class PropertiesToYamlCommand { + + static final String CMD_PROPS_TO_YAML = "sts/boot/props-to-yaml"; + + private static final Pattern COMMENT = Pattern.compile("(?m)^\\s*(\\#|\\!)"); + + private final SimpleLanguageServer server; + + PropertiesToYamlCommand(SimpleLanguageServer server) { + this.server = server; + server.onCommand(CMD_PROPS_TO_YAML, params -> execute(params.getArguments())); + } + + private CompletableFuture execute(List arguments) { + String propsUri = arguments.get(0) instanceof JsonElement ? ((JsonElement) arguments.get(0)).getAsString() : (String) arguments.get(0); + String yamlUri = arguments.get(1) instanceof JsonElement ? ((JsonElement) arguments.get(1)).getAsString() : (String) arguments.get(1); + Boolean replace = arguments.get(2) instanceof JsonElement ? ((JsonElement) arguments.get(2)).getAsBoolean() : (Boolean) arguments.get(2); + return CompletableFuture.supplyAsync(() -> { + try { + return createWorkspaceEdit(propsUri, yamlUri, replace); + } catch (IOException | BadLocationException e) { + throw new CompletionException(e); + } + }) + .thenCompose(we -> server.getClient().applyEdit(new ApplyWorkspaceEditParams(we, "Convert .properties to .yaml"))) + .thenCompose(res -> res.isApplied() ? server.getClient().showDocument(new ShowDocumentParams(yamlUri)) : CompletableFuture.completedFuture(new ShowDocumentResult(false))); + } + + private WorkspaceEdit createWorkspaceEdit(String propsUri, String yamlUri, Boolean replace) throws IOException, BadLocationException { + Path yamlFile = Paths.get(URI.create(yamlUri)); + if (Files.exists(yamlFile)) { + throw new IOException("File %s already exists!".formatted(yamlFile.toString())); + } + + TextDocument doc = getDocument(propsUri, LanguageId.BOOT_PROPERTIES); + String propsContent = doc.get(); + List errors = new ArrayList<>(); + List warnings = new ArrayList<>(); + + if (hasComments(propsContent)) { + warnings.add("The yaml file had comments which are lost in the refactoring!"); + } + + Multimap properties = load(new StringReader(propsContent)); + PropertiesToYamlConverter converter = new PropertiesToYamlConverter(properties); + + StringBuilder yamlContent = new StringBuilder(); + errors.addAll(converter.getErrors()); + warnings.addAll(converter.getWarnings()); + YamlToPropertiesCommand.addReportHeaderComment(yamlContent, errors, warnings); + yamlContent.append(converter.getYaml()); + + return replace ? YamlToPropertiesCommand.createReplaceFileWorkspaceEdit(propsUri, yamlUri, doc, yamlContent.toString()) : YamlToPropertiesCommand.createNewFileWorkspaceEdit(yamlUri, yamlContent.toString()); + } + + private Multimap load(Reader content) throws IOException { + Multimap map = Multimaps.newMultimap( + new LinkedTreeMap>(), + LinkedHashSet::new + ); + Properties loader = new Properties() { + private static final long serialVersionUID = 1L; + public synchronized Object put(Object key, Object value) { + map.put((String)key, (String)value); + return super.put(key, value); + } + }; + loader.load(content); + return map; + } + + private static boolean hasComments(String propsContent) { + return COMMENT.matcher(propsContent).find(); + } + + private TextDocument getDocument(String uri, LanguageId language) { + TextDocument doc = server.getTextDocumentService().getLatestSnapshot(uri); + return doc == null ? new LazyTextDocument(uri, language) : doc; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlConverter.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlConverter.java new file mode 100644 index 0000000000..833df23256 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlConverter.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.Assert; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; +import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment; +import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.AtIndex; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.representer.Representer; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimap; +import com.google.gson.internal.LinkedTreeMap; + +/** + * Helper class to convert (Spring Boot) .properties file content into equivalent + * .yml file content. + * + * @author Kris De Volder + */ +class PropertiesToYamlConverter { + + private String output; + private ImmutableList.Builder errors; + private ImmutableList.Builder warnings; + + class YamlBuilder { + final YamlPath path; + final List scalars = new ArrayList<>(); + final LinkedTreeMap listItems = new LinkedTreeMap<>(); + final LinkedTreeMap mapEntries = new LinkedTreeMap<>(); + + public YamlBuilder(YamlPath path) { + this.path = path; + } + + void addProperty(YamlPath path, String value) { + if (path.isEmpty()) { + scalars.add(objectify(value)); + } else { + YamlPathSegment segment = path.getSegment(0); + YamlBuilder subBuilder; + if (segment instanceof AtIndex) { + subBuilder = getSubBuilder(listItems, segment, segment.toIndex()); + } else { + subBuilder = getSubBuilder(mapEntries, segment, segment.toPropString()); + } + subBuilder.addProperty(path.dropFirst(1), value); + } + } + + private Object objectify(String value) { + if (value != null) { + Object parsed = null; + try { + parsed = new BigInteger(value); + } catch (NumberFormatException e) { + try { + parsed = new BigDecimal(value); + } catch (NumberFormatException e2) { + if (value.equals("true")) { + parsed = true; + } else if (value.equals("false")) { + parsed = false; + } + } + } + if (parsed!=null && parsed.toString().equals(value)) { + return parsed; + } + } + return value; + } + + private YamlBuilder getSubBuilder(LinkedTreeMap subBuilders, YamlPathSegment segment, T key) { + YamlBuilder existing = subBuilders.get(key); + if (existing==null) { + subBuilders.put(key, existing = new YamlBuilder(path.append(segment))); + } + return existing; + } + + public Object build() { + if (!scalars.isEmpty()) { + if (listItems.isEmpty() && mapEntries.isEmpty()) { + if (scalars.size()>1) { + warnings.add("Multiple values "+ scalars +" assigned to '"+path.toPropString()+"'. Values are merged into a yaml sequence node."); + return scalars; + } else { + return scalars.get(0); + } + } else { + if (!mapEntries.isEmpty()) { + errors.add( + "Direct assignment '"+path.toPropString()+"="+scalars.get(0)+"' can not be combined " + + "with sub-property assignment '"+path.toPropString()+"." + mapEntries.keySet().iterator().next()+"...'. "+ + "Direct assignment is dropped!" + ); + } else { + errors.add( + "Direct assignment '"+path.toPropString()+"="+scalars.get(0)+"' can not be combined " + + "with sequence assignment '"+path.toPropString()+"[" + listItems.keySet().iterator().next()+"]...'. "+ + "Direct assignments are dropped!" + ); + } + scalars.clear(); + } + } + Assert.isLegal(scalars.isEmpty()); + if (!listItems.isEmpty() && !mapEntries.isEmpty()) { + warnings.add("'"+path.toPropString()+"' has some entries that look like list items and others that look like map entries. " + + "All these entries are treated as map entries!"); + for (Entry listItem : listItems.entrySet()) { + mapEntries.put(listItem.getKey().toString(), listItem.getValue()); + } + listItems.clear(); + } + if (!listItems.isEmpty()) { + return listItems.values().stream() + .map(childBuilder -> childBuilder.build()) + .collect(Collectors.toList()); + } else { + LinkedTreeMap map = new LinkedTreeMap<>(); + for (Entry entry : mapEntries.entrySet()) { + map.put(entry.getKey(), entry.getValue().build()); + } + return map; + } + } + } + + public PropertiesToYamlConverter(Multimap properties) { + this.errors = ImmutableList.builder(); + this.warnings = ImmutableList.builder(); + if (properties.isEmpty()) { + output = ""; + return; + } + YamlBuilder root = new YamlBuilder(YamlPath.EMPTY); + for (Entry e : properties.entries()) { + root.addProperty(YamlPath.fromProperty(e.getKey()), e.getValue()); + } + Object object = root.build(); + + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setPrettyFlow(true); + + Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()), new Representer(options), options); + this.output = yaml.dump(object); + } + + public List getErrors() { + return errors.build(); + } + + public List getWarnings() { + return warnings.build(); + } + + public String getYaml() { + return output; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommand.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommand.java new file mode 100644 index 0000000000..8542bb1509 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommand.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +import org.eclipse.lsp4j.AnnotatedTextEdit; +import org.eclipse.lsp4j.ApplyWorkspaceEditParams; +import org.eclipse.lsp4j.ChangeAnnotation; +import org.eclipse.lsp4j.CreateFile; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.RenameFile; +import org.eclipse.lsp4j.ShowDocumentParams; +import org.eclipse.lsp4j.ShowDocumentResult; +import org.eclipse.lsp4j.TextDocumentEdit; +import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.LazyTextDocument; +import org.springframework.ide.vscode.commons.util.text.TextDocument; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.comments.CommentType; +import org.yaml.snakeyaml.events.CommentEvent; +import org.yaml.snakeyaml.events.Event; + +import com.google.gson.JsonElement; + +class YamlToPropertiesCommand { + + private static final String LABEL = "Convert .yaml to .properties"; + + static final String CMD_YAML_TO_PROPS = "sts/boot/yaml-to-props"; + + private final SimpleLanguageServer server; + + YamlToPropertiesCommand(SimpleLanguageServer server) { + this.server = server; + server.onCommand(CMD_YAML_TO_PROPS, params -> execute(params.getArguments())); + } + + private CompletableFuture execute(List arguments) { + String yamlUri = arguments.get(0) instanceof JsonElement ? ((JsonElement) arguments.get(0)).getAsString() : (String) arguments.get(0); + String propsUri = arguments.get(1) instanceof JsonElement ? ((JsonElement) arguments.get(1)).getAsString() : (String) arguments.get(1); + Boolean replace = arguments.get(2) instanceof JsonElement ? ((JsonElement) arguments.get(2)).getAsBoolean() : (Boolean) arguments.get(2); + return CompletableFuture.supplyAsync(() -> { + try { + return createWorkspaceEdit(yamlUri, propsUri, replace); + } catch (IOException | BadLocationException e) { + throw new CompletionException(e); + } + }) + .thenCompose(we -> server.getClient().applyEdit(new ApplyWorkspaceEditParams(we, LABEL))) + .thenCompose(res -> res.isApplied() ? server.getClient().showDocument(new ShowDocumentParams(propsUri)) : CompletableFuture.completedFuture(new ShowDocumentResult(false))); + } + + private WorkspaceEdit createWorkspaceEdit(String yamlUri, String propsUri, boolean replace) throws IOException, BadLocationException { + Path propsFile = Paths.get(URI.create(propsUri)); + if (Files.exists(propsFile)) { + throw new IOException("File %s already exists!".formatted(propsFile.toString())); + } + + List errors = new ArrayList<>(); + List warnings = new ArrayList<>(); + TextDocument doc = getDocument(server, yamlUri, LanguageId.BOOT_PROPERTIES_YAML); + String yamlContent = doc.get(); + + if (hasComments(yamlContent)) { + warnings.add("The yaml file had comments which are lost in the refactoring!"); + } + + StringBuilder propsContent = new StringBuilder(); + for (Object d : new Yaml().loadAll(new StringReader(yamlContent))) { + if (d instanceof Map) { + // Add doc divider if not empty + @SuppressWarnings("unchecked") + Map o = (Map) d; + YamlToPropertiesConverter converter = new YamlToPropertiesConverter(o); + Properties props = converter.getProperties(); + StringWriter write = new StringWriter(); + props.store(write, null); + if (!propsContent.isEmpty()) { + propsContent.append("#---\n"); + } else { + addReportHeaderComment(propsContent, errors, warnings); + } + // Skip over the date header. Comments are not present but date header is. + if (write.getBuffer().charAt(0) == '#') { + int idx = write.getBuffer().indexOf("\n"); + propsContent.append(idx >= 0 && idx < write.getBuffer().length() ? write.getBuffer().substring(idx + 1) : write.getBuffer().toString()); + } else { + propsContent.append(write.getBuffer().toString()); + } + } else if (d == null) { + if (!propsContent.isEmpty()) { + propsContent.append("#---\n"); + } + } + } + + return replace ? createReplaceFileWorkspaceEdit(yamlUri, propsUri, doc, propsContent.toString()) : createNewFileWorkspaceEdit(propsUri, propsContent.toString()); + } + + + private static boolean hasComments(String yamlContent) { + LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setProcessComments(true); + for (Event e : new Yaml(loaderOptions).parse(new StringReader(yamlContent))) { + if (e instanceof CommentEvent ce) { + if (ce.getCommentType() == CommentType.BLANK_LINE) { + // document separator + } else { + return true; + } + } + } + return false; + } + + static WorkspaceEdit createReplaceFileWorkspaceEdit(String sourceUri, String targetUri, TextDocument oldDoc, String newContent) throws BadLocationException { + String changeAnnotationId = UUID.randomUUID().toString(); + ChangeAnnotation changeAnnotation = new ChangeAnnotation(LABEL); + changeAnnotation.setNeedsConfirmation(true); + + RenameFile renameFile = new RenameFile(sourceUri, targetUri); + renameFile.setAnnotationId(changeAnnotationId); + WorkspaceEdit we = new WorkspaceEdit(List.of( + Either.forLeft(new TextDocumentEdit( + new VersionedTextDocumentIdentifier(sourceUri, oldDoc.getVersion()), + List.of(new AnnotatedTextEdit(oldDoc.toRange(0, oldDoc.getLength()), newContent, changeAnnotationId)) + )), + Either.forRight(renameFile) + )); + we.setChangeAnnotations(Map.of(changeAnnotationId, changeAnnotation)); + return we; + } + + static WorkspaceEdit createNewFileWorkspaceEdit(String uri, String content) { + String changeAnnotationId = UUID.randomUUID().toString(); + ChangeAnnotation changeAnnotation = new ChangeAnnotation(LABEL); + changeAnnotation.setNeedsConfirmation(false); // VSCode refactor preview errors out showing diff for newly added file + + CreateFile createFile = new CreateFile(uri); + createFile.setAnnotationId(changeAnnotationId); + WorkspaceEdit we = new WorkspaceEdit(List.of( + Either.forRight(createFile), + Either.forLeft(new TextDocumentEdit( + new VersionedTextDocumentIdentifier(uri, null), + List.of(new AnnotatedTextEdit(new Range(new Position(0,0), new Position(0,0)), content, changeAnnotationId)) + )) + )); + we.setChangeAnnotations(Map.of(changeAnnotationId, changeAnnotation)); + return we; + } + + static TextDocument getDocument(SimpleLanguageServer server, String uri, LanguageId language) { + TextDocument doc = server.getTextDocumentService().getLatestSnapshot(uri); + return doc == null ? new LazyTextDocument(uri, language) : doc; + } + + static void addReportHeaderComment(StringBuilder content, List errors, List warnings) { + if (!errors.isEmpty() || !warnings.isEmpty()) { + content.append("# Conversion to YAML from Properties formar report\n"); + if (!errors.isEmpty()) { + content.append("# Errors:\n"); + for (String e : errors) { + content.append("# - %s\n".formatted(e)); + } + } + if (!warnings.isEmpty()) { + content.append("# Warnings:\n"); + for (String w : warnings) { + content.append("# - %s\n".formatted(w)); + } + } + } + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesConverter.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesConverter.java new file mode 100644 index 0000000000..a42bdb6cda --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesConverter.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +class YamlToPropertiesConverter { + + private final Properties properties; + + + public YamlToPropertiesConverter(Map yaml) { + this.properties = new Properties() { + + private static final long serialVersionUID = 1L; + + private LinkedHashMap delegate = new LinkedHashMap<>(); + + @Override + public synchronized Object put(Object key, Object value) { + delegate.put(key, value); + return super.put(key, value); + } + + @Override + public Set> entrySet() { + return delegate.entrySet(); + } + + }; + + for (Map.Entry e : yaml.entrySet()) { + readProperties(e.getValue(), e.getKey()); + } + } + + private void readPropertiesFromYamlMap(Map map, String prefix) { + for (Map.Entry e : map.entrySet()) { + readProperties(e.getValue(), "%s.%s".formatted(prefix, e.getKey())); + } + } + + private void readPropertiesFromYamlList(List l, String prefix) { + for (int i = 0; i < l.size(); i++) { + readProperties(l.get(i), "%s[%d]".formatted(prefix, i)); + } + } + + @SuppressWarnings("unchecked") + private void readProperties(Object o, String prefix) { + if (o instanceof Map) { + readPropertiesFromYamlMap((Map) o, prefix); + } else if ( o instanceof List) { + readPropertiesFromYamlList((List) o, prefix); + } else { + properties.put(prefix, o.toString()); + } + } + + public Properties getProperties() { + return properties; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java index e2b2919405..5d0a525484 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 VMware, Inc. + * Copyright (c) 2023, 2024 VMware, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,7 +13,12 @@ import java.util.Collection; import java.util.List; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; +import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.ShowDocumentParams; import org.springframework.ide.vscode.boot.validation.generations.json.Generation; import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject; import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType; @@ -26,6 +31,8 @@ public class GenerationsValidator extends AbstractDiagnosticValidator { + private static String SPRING_COMMERCIAL_URL = "https://tanzu.vmware.com/spring-runtime"; + private SpringProjectsProvider provider; public GenerationsValidator(DiagnosticSeverityProvider diagnosticSeverityProvider, SpringProjectsProvider provider) { @@ -33,7 +40,7 @@ public GenerationsValidator(DiagnosticSeverityProvider diagnosticSeverityProvide this.provider = provider; } - private static Generation getGenerationForJavaProject(IJavaProject javaProject, ResolvedSpringProject springProject) + public static Generation getGenerationForJavaProject(IJavaProject javaProject, ResolvedSpringProject springProject) throws Exception { List genList = springProject.getGenerations(); Version javaProjectVersion = SpringProjectUtil.getDependencyVersion(javaProject, springProject.getSlug()); @@ -55,6 +62,9 @@ public Collection validate(IJavaProject javaProject, Version javaPro Generation javaProjectGen = getGenerationForJavaProject(javaProject, springProject); ImmutableList.Builder b = ImmutableList.builder(); + boolean validCommercialSupport = VersionValidationUtils.isCommercialValid(javaProjectGen); + + if (VersionValidationUtils.isOssValid(javaProjectGen)) { StringBuilder message = new StringBuilder(); message.append("OSS support for Spring Boot "); @@ -73,16 +83,24 @@ public Collection validate(IJavaProject javaProject, Version javaPro message.append(" not available!"); } else { message.append(javaProjectGen.getName()); - message.append(" no longer available, ended on: "); + message.append(" ended on "); message.append(javaProjectGen.getOssSupportEndDate()); + if (validCommercialSupport) { + message.append(", get commercial support until "); + message.append(javaProjectGen.getCommercialSupportEndDate()); + message.append(" via Tanzu Spring Runtime at https://tanzu.vmware.com/spring-runtime"); + } } Diagnostic d = createDiagnostic(VersionValidationProblemType.UNSUPPORTED_OSS_VERSION, message.toString()); + if (validCommercialSupport) { + d.setData(List.of(getCommercialSupportCodeAction())); + } if (d != null) { b.add(d); } } - if (VersionValidationUtils.isCommercialValid(javaProjectGen)) { + if (validCommercialSupport) { StringBuilder message = new StringBuilder(); message.append("Commercial support for Spring Boot "); message.append(javaProjectGen.getName()); @@ -100,7 +118,7 @@ public Collection validate(IJavaProject javaProject, Version javaPro message.append(" not available!"); } else { message.append(javaProjectGen.getName()); - message.append(" no longer available, ended on: "); + message.append(" ended on "); message.append(javaProjectGen.getCommercialSupportEndDate()); } Diagnostic d = createDiagnostic(VersionValidationProblemType.UNSUPPORTED_COMMERCIAL_VERSION, message.toString()); @@ -121,5 +139,19 @@ public boolean isEnabled() { VersionValidationProblemType.UNSUPPORTED_COMMERCIAL_VERSION ); } + + private static CodeAction getCommercialSupportCodeAction() { + CodeAction commercialSupportLink = new CodeAction(); + commercialSupportLink.setKind(CodeActionKind.QuickFix); + commercialSupportLink.setTitle("Get commercial Spring Boot support via Tanzu Spring Runtime"); + ShowDocumentParams showDocumentParams = new ShowDocumentParams(SPRING_COMMERCIAL_URL); + showDocumentParams.setExternal(true); + showDocumentParams.setTakeFocus(true); + showDocumentParams.setSelection(new Range()); + commercialSupportLink.setCommand(new Command("Get commercial Spring Boot support via Tanzu Spring Runtime", "sts/show/document", + ImmutableList.of(showDocumentParams))); + return commercialSupportLink; + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java index 5281e59f9e..d87037543b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.validation.generations.preferences; -import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.HINT; import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.IGNORE; import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.INFO; import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.WARNING; @@ -24,9 +23,9 @@ public enum VersionValidationProblemType implements ProblemType { SUPPORTED_OSS_VERSION(IGNORE, "Supported OSS Boot Version", "Supported OSS Boot Version"), - UNSUPPORTED_OSS_VERSION(HINT, "Unsupported OSS Version", "Unsupported OSS Version"), + UNSUPPORTED_OSS_VERSION(WARNING, "Unsupported OSS Version", "Unsupported OSS Version"), - UNSUPPORTED_COMMERCIAL_VERSION(HINT, "Unsupported Commercial Version", "Unsupported Commercial Version"), + UNSUPPORTED_COMMERCIAL_VERSION(WARNING, "Unsupported Commercial Version", "Unsupported Commercial Version"), SUPPORTED_COMMERCIAL_VERSION(IGNORE, "Supported Commercial Version", "Supported Commercial Version"), diff --git a/headless-services/spring-boot-language-server/src/main/resources/problem-types.json b/headless-services/spring-boot-language-server/src/main/resources/problem-types.json index 39da428933..0d1ebde703 100644 --- a/headless-services/spring-boot-language-server/src/main/resources/problem-types.json +++ b/headless-services/spring-boot-language-server/src/main/resources/problem-types.json @@ -355,13 +355,13 @@ "code": "UNSUPPORTED_OSS_VERSION", "label": "Unsupported OSS Version", "description": "Unsupported OSS Version", - "defaultSeverity": "HINT" + "defaultSeverity": "WARNING" }, { "code": "UNSUPPORTED_COMMERCIAL_VERSION", "label": "Unsupported Commercial Version", "description": "Unsupported Commercial Version", - "defaultSeverity": "HINT" + "defaultSeverity": "WARNING" }, { "code": "SUPPORTED_COMMERCIAL_VERSION", diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjectsTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjectsTest.java new file mode 100644 index 0000000000..35be521e62 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/commands/WorkspaceBootExecutableProjectsTest.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.lsp4j.ExecuteCommandParams; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.ide.vscode.boot.app.SpringSymbolIndex; +import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest; +import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf; +import org.springframework.ide.vscode.boot.java.commands.WorkspaceBootExecutableProjects.ExecutableProject; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject; +import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness; +import org.springframework.ide.vscode.project.harness.ProjectsHarness; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@BootLanguageServerTest +@Import(SymbolProviderTestConf.class) +public class WorkspaceBootExecutableProjectsTest { + + @Autowired private BootLanguageServerHarness harness; + @Autowired private JavaProjectFinder projectFinder; + @Autowired private SpringSymbolIndex symbolIndex; + + @BeforeEach + public void setup() throws Exception { + harness.intialize(null); + } + + @SuppressWarnings("unchecked") + @Test + void singleProject() throws Exception { + MavenJavaProject project = ProjectsHarness.INSTANCE.mavenProject("test-spring-indexing"); + + // trigger project creation + projectFinder.find(new TextDocumentIdentifier(project.getProjectBuild().getBuildFile().toASCIIString())).get(); + + CompletableFuture initProject = symbolIndex.waitOperation(); + initProject.get(5, TimeUnit.SECONDS); + + List res = (List) harness.getServer().getWorkspaceService().executeCommand(new ExecuteCommandParams(WorkspaceBootExecutableProjects.CMD, Collections.emptyList())).get(); + assertNotNull(res); + assertEquals(1, res.size()); + ExecutableProject execProject = res.get(0); + assertEquals("test-spring-indexing", execProject.name()); + assertEquals("org.test.MainClass", execProject.mainClass()); + assertEquals(project.getLocationUri().toASCIIString(), execProject.uri()); + assertEquals("com.example:test-spring-indexing:0.0.1-SNAPSHOT", execProject.gav()); + assertEquals(99, execProject.classpath().size()); + + assertTrue(execProject.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/classes"))); + assertFalse(execProject.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/test-classes"))); + } + + @SuppressWarnings("unchecked") + @Test + void multipleProjects() throws Exception { + MavenJavaProject project1 = ProjectsHarness.INSTANCE.mavenProject("test-spring-indexing"); + MavenJavaProject project2 = ProjectsHarness.INSTANCE.mavenProject("test-spring-data-symbols"); + ProjectsHarness.INSTANCE.mavenProject("test-annotation-indexing-non-boot-project"); + ProjectsHarness.INSTANCE.mavenProject("test-xml-validations"); + + + // trigger project creation + projectFinder.find(new TextDocumentIdentifier(project1.getProjectBuild().getBuildFile().toASCIIString())).get(); + projectFinder.find(new TextDocumentIdentifier(project2.getProjectBuild().getBuildFile().toASCIIString())).get(); + + CompletableFuture initProject = symbolIndex.waitOperation(); + initProject.get(10, TimeUnit.SECONDS); + + List res = (List) harness.getServer().getWorkspaceService().executeCommand(new ExecuteCommandParams(WorkspaceBootExecutableProjects.CMD, Collections.emptyList())).get(); + assertNotNull(res); + assertEquals(2, res.size()); + + ExecutableProject execProject1 = res.stream().filter(p -> "test-spring-indexing".equals(p.name())).findFirst().orElseThrow(); + assertEquals("test-spring-indexing", execProject1.name()); + assertEquals("org.test.MainClass", execProject1.mainClass()); + assertEquals(project1.getLocationUri().toASCIIString(), execProject1.uri()); + assertEquals("com.example:test-spring-indexing:0.0.1-SNAPSHOT", execProject1.gav()); + assertEquals(99, execProject1.classpath().size()); + assertTrue(execProject1.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/classes"))); + assertFalse(execProject1.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/test-classes"))); + + ExecutableProject execProject2 = res.stream().filter(p -> "test-spring-data-symbols".equals(p.name())).findFirst().orElseThrow(); + assertEquals("test-spring-data-symbols", execProject2.name()); + assertEquals("org.test.Application", execProject2.mainClass()); + assertEquals(project2.getLocationUri().toASCIIString(), execProject2.uri()); + assertEquals("com.example:test-spring-data-symbols:0.0.1-SNAPSHOT", execProject2.gav()); + assertEquals(44, execProject2.classpath().size()); + assertTrue(execProject2.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/classes"))); + assertFalse(execProject2.classpath().stream().map(path -> Path.of(path)).anyMatch(p -> p.endsWith("target/test-classes"))); + + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandlerTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandlerTest.java new file mode 100644 index 0000000000..9c22ee29a3 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/maven/PomInlayHintHandlerTest.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.maven; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Date; +import java.time.Duration; +import java.util.List; +import java.util.Optional; + +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.InlayHint; +import org.eclipse.lsp4j.InlayHintLabelPart; +import org.eclipse.lsp4j.InlayHintParams; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; +import org.junit.jupiter.api.Test; +import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider; +import org.springframework.ide.vscode.boot.validation.generations.json.Generation; +import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject; +import org.springframework.ide.vscode.commons.java.SpringProjectUtil; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; +import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject; +import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.TextDocument; +import org.springframework.ide.vscode.project.harness.ProjectsHarness; + +public class PomInlayHintHandlerTest { + + private ProjectsHarness projects = ProjectsHarness.INSTANCE; + + @Test + void inlayProvided() throws Exception { + MavenJavaProject jp = projects.mavenProject("empty-boot-15-web-app"); + + TextDocument doc = new TextDocument(jp.getProjectBuild().getBuildFile().toASCIIString(), LanguageId.XML, 0, Files.readString(Paths.get(jp.getProjectBuild().getBuildFile()))); + + JavaProjectFinder projectFinder = mock(JavaProjectFinder.class); + when(projectFinder.find(any())).thenReturn(Optional.of(jp)); + + SimpleTextDocumentService documents = mock(SimpleTextDocumentService.class); + when(documents.getLatestSnapshot(anyString())).thenReturn(doc); + + SimpleLanguageServer server = mock(SimpleLanguageServer.class); + when(server.getTextDocumentService()).thenReturn(documents); + + Generation generation = mock(Generation.class); + when(generation.getOssSupportEndDate()).thenReturn(new Date(System.currentTimeMillis() + Duration.ofDays(7).toMillis()).toString()); + when(generation.getName()).thenReturn("1.5.8"); + + ResolvedSpringProject resolvedProject = mock(ResolvedSpringProject.class); + when(resolvedProject.getGenerations()).thenReturn(List.of(generation)); + when(resolvedProject.getSlug()).thenReturn(SpringProjectUtil.SPRING_BOOT); + + SpringProjectsProvider projectProvider = mock(SpringProjectsProvider.class); + when(projectProvider.getProject(SpringProjectUtil.SPRING_BOOT)).thenReturn(resolvedProject); + + PomInlayHintHandler inlayHanlder = new PomInlayHintHandler(server, projectFinder, ProjectObserver.NULL, projectProvider); + + List hints = inlayHanlder.handle(mock(CancelChecker.class), new InlayHintParams(new TextDocumentIdentifier(doc.getUri()), doc.toRange(0, doc.getLength()))); + + assertEquals(1, hints.size()); + + InlayHint hint = hints.get(0); + + assertEquals(new Position(27, 15), hint.getPosition()); + + assertTrue(hint.getLabel().isRight()); + + assertEquals(1, hint.getLabel().getRight().size()); + + InlayHintLabelPart labelPart = hint.getLabel().getRight().get(0); + + assertEquals("Add Spring Boot Starters...", labelPart.getValue()); + + Command cmd = labelPart.getCommand(); + + assertNotNull(cmd); + + assertEquals("spring.initializr.addStarters", cmd.getCommand()); + + } + + @Test + void inlayNotProvidedOutOfOssSupport() throws Exception { + MavenJavaProject jp = projects.mavenProject("empty-boot-15-web-app"); + + TextDocument doc = new TextDocument(jp.getProjectBuild().getBuildFile().toASCIIString(), LanguageId.XML, 0, Files.readString(Paths.get(jp.getProjectBuild().getBuildFile()))); + + JavaProjectFinder projectFinder = mock(JavaProjectFinder.class); + when(projectFinder.find(any())).thenReturn(Optional.of(jp)); + + SimpleTextDocumentService documents = mock(SimpleTextDocumentService.class); + when(documents.getLatestSnapshot(anyString())).thenReturn(doc); + + SimpleLanguageServer server = mock(SimpleLanguageServer.class); + when(server.getTextDocumentService()).thenReturn(documents); + + Generation generation = mock(Generation.class); + when(generation.getOssSupportEndDate()).thenReturn(new Date(System.currentTimeMillis() - Duration.ofDays(7).toMillis()).toString()); + when(generation.getName()).thenReturn("1.5.8"); + + ResolvedSpringProject resolvedProject = mock(ResolvedSpringProject.class); + when(resolvedProject.getGenerations()).thenReturn(List.of(generation)); + when(resolvedProject.getSlug()).thenReturn(SpringProjectUtil.SPRING_BOOT); + + SpringProjectsProvider projectProvider = mock(SpringProjectsProvider.class); + when(projectProvider.getProject(SpringProjectUtil.SPRING_BOOT)).thenReturn(resolvedProject); + + PomInlayHintHandler inlayHanlder = new PomInlayHintHandler(server, projectFinder, ProjectObserver.NULL, projectProvider); + + List hints = inlayHanlder.handle(mock(CancelChecker.class), new InlayHintParams(new TextDocumentIdentifier(doc.getUri()), doc.toRange(0, doc.getLength()))); + + assertEquals(0, hints.size()); + + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommandTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommandTest.java new file mode 100644 index 0000000000..e15c09107b --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/PropertiesToYamlCommandTest.java @@ -0,0 +1,313 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; + +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.ShowDocumentResult; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest; +import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; +import org.springframework.ide.vscode.project.harness.ProjectsHarness; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@BootLanguageServerTest +@Import({SymbolProviderTestConf.class}) +public class PropertiesToYamlCommandTest { + + private static final String FILENAME_SUFFIX = "-conversion-test"; + + @Autowired private LanguageServerHarness harness; + @Autowired private JavaProjectFinder projectFinder; + + private File directory; + + @BeforeEach public void setup() throws Exception { + harness.intialize(null); + + directory = new File(ProjectsHarness.class.getResource("/test-projects/test-spring-validations/").toURI()); + + Files.walk(directory.toPath(), Integer.MAX_VALUE).filter(Files::isRegularFile).filter(p -> p.getFileName().toString().contains(FILENAME_SUFFIX)).forEach(t -> { + try { + Files.delete(t); + } catch (IOException e) { + + } + }); + + String projectDir = directory.toURI().toString(); + + // trigger project creation + projectFinder.find(new TextDocumentIdentifier(projectDir)).get(); + } + + @AfterEach public void tearDown() throws Exception { + if (directory != null && directory.exists()) { + Files.walk(directory.toPath(), Integer.MAX_VALUE).filter(Files::isRegularFile).filter(p -> p.getFileName().toString().contains(FILENAME_SUFFIX)).forEach(t -> { + try { + Files.delete(t); + } catch (IOException e) { + + } + }); + } + } + + void assertConversion(String propsContent, String yamlContent, boolean replace) throws Exception { + Path yamlFilePath = directory.toPath().resolve("src/main/resources/application" + FILENAME_SUFFIX + ".yml"); + Path propsFilePath = directory.toPath().resolve("src/main/resources/application" + FILENAME_SUFFIX + ".properties"); + + if (!Files.exists(propsFilePath)) { + Files.createDirectories(propsFilePath.getParent()); + Files.createFile(propsFilePath); + Files.write(propsFilePath, propsContent.getBytes(), StandardOpenOption.APPEND); + } + + Command cmd = new Command(); + cmd.setCommand(PropertiesToYamlCommand.CMD_PROPS_TO_YAML); + cmd.setArguments(List.of(propsFilePath.toUri().toASCIIString(), yamlFilePath.toUri().toASCIIString(), replace)); + cmd.setTitle("Convert .propeties to .yaml"); + + ShowDocumentResult res = (ShowDocumentResult) harness.perform(cmd); + + assertThat(res.isSuccess()).isTrue(); + + assertThat(Files.exists(yamlFilePath)).isTrue(); + if (replace) { + assertThat(Files.exists(propsFilePath)).isFalse(); + } else { + assertThat(Files.exists(propsFilePath)).isTrue(); + } + + assertThat(Files.readString(yamlFilePath)).isEqualTo(yamlContent); + } + + @Test void almostHasComments() throws Exception { + assertConversion( + "my.hello=Good morning!\n" + + "my.goodbye=See ya # later\n" + , // ==> + "my:\n" + + " hello: Good morning!\n" + + " goodbye: 'See ya # later'\n", + true + ); + } + + + @Test void listItems() throws Exception { + assertConversion( + "some.thing[0].a=first-a\n" + + "some.thing[0].b=first-b\n" + + "some.thing[1].a=second-a\n" + + "some.thing[1].b=second-b\n" + , // ==> + "some:\n" + + " thing:\n" + + " - a: first-a\n" + + " b: first-b\n" + + " - a: second-a\n" + + " b: second-b\n", + true + ); + } + + @Test void simple() throws Exception { + assertConversion( + "some.thing=vvvv\n" + + "some.other.thing=blah\n" + , // ==> + "some:\n" + + " thing: vvvv\n" + + " other:\n" + + " thing: blah\n", + true + ); + } + + @Test void noReplacement() throws Exception { + assertConversion( + "some.thing=vvvv\n" + + "some.other.thing=blah\n" + , // ==> + "some:\n" + + " thing: vvvv\n" + + " other:\n" + + " thing: blah\n", + false + ); + } + + @Test void nonStringyValueConversion() throws Exception { + //See: https://www.pivotaltracker.com/story/show/154181583 + //Test that we do not add unnecessary quotes around certain types of values. + assertConversion( + "exponated=123.4E-12\n" + + "server.port=8888\n" + + "foobar.enabled=true\n" + + "foobar.nice=false\n" + + "fractional=0.78\n" + + "largenumber=989898989898989898989898989898989898989898989898989898989898\n" + + "longfractional=-0.989898989898989898989898989898989898989898989898989898989898\n" + , // ==> + "exponated: '123.4E-12'\n" + //quotes are added because conversion to number changes the string value + "server:\n" + + " port: 8888\n" + + "foobar:\n" + + " enabled: true\n" + + " nice: false\n" + + "fractional: 0.78\n" + + "largenumber: 989898989898989898989898989898989898989898989898989898989898\n" + + "longfractional: -0.989898989898989898989898989898989898989898989898989898989898\n", + true + ); + } + + @Test void emptyFileConversion() throws Exception { + assertConversion( + "" + , // ==> + "", + true + ); + } + + @Test void multipleAssignmentProblem() throws Exception { + assertConversion( + "some.property=something\n" + + "some.property=something-else" + , // ==> + "# Conversion to YAML from Properties formar report\n" + + "# Warnings:\n" + + "# - Multiple values [something, something-else] assigned to 'some.property'. Values are merged into a yaml sequence node.\n" + + "some:\n" + + " property:\n" + + " - something\n" + + " - something-else\n" + , + true + ); + } + + @Test void scalarAndMapConflict() throws Exception { + assertConversion( + "some.property=a-scalar\n" + + "some.property.sub=sub-value" + , + "# Conversion to YAML from Properties formar report\n" + + "# Errors:\n" + + "# - Direct assignment 'some.property=a-scalar' can not be combined with sub-property assignment 'some.property.sub...'. Direct assignment is dropped!\n" + + "some:\n" + + " property:\n" + + " sub: sub-value\n" + , + true + ); + } + + @Test void scalarAndSequenceConflict() throws Exception { + assertConversion( + "some.property=a-scalar\n" + + "some.property[0]=zero\n" + + "some.property[1]=one\n" + , + "# Conversion to YAML from Properties formar report\n" + + "# Errors:\n" + + "# - Direct assignment 'some.property=a-scalar' can not be combined with sequence assignment 'some.property[0]...'. Direct assignments are dropped!\n" + + "some:\n" + + " property:\n" + + " - zero\n" + + " - one\n" + , + true + ); + } + + @Test public void mapAndSequenceConflict() throws Exception { + assertConversion( + "some.property.abc=val1\n" + + "some.property.def=val2\n" + + "some.property[0]=zero\n" + + "some.property[1]=one\n" + , + "# Conversion to YAML from Properties formar report\n" + + "# Warnings:\n" + + "# - 'some.property' has some entries that look like list items and others that look like map entries. All these entries are treated as map entries!\n" + + "some:\n" + + " property:\n" + + " abc: val1\n" + + " def: val2\n" + + " '0': zero\n" + + " '1': one\n" + , + true + ); + } + + @Test public void scalarAndMapAndSequenceConflict() throws Exception { + assertConversion( + "some.property=a-scalar\n" + + "some.property.abc=val1\n" + + "some.property.def=val2\n" + + "some.property[0]=zero\n" + + "some.property[1]=one\n" + , + "# Conversion to YAML from Properties formar report\n" + + "# Errors:\n" + + "# - Direct assignment 'some.property=a-scalar' can not be combined with sub-property assignment 'some.property.abc...'. Direct assignment is dropped!\n" + + "# Warnings:\n" + + "# - 'some.property' has some entries that look like list items and others that look like map entries. All these entries are treated as map entries!\n" + + "some:\n" + + " property:\n" + + " abc: val1\n" + + " def: val2\n" + + " '0': zero\n" + + " '1': one\n" + , + true + ); + } + + @Test void lineComment() throws Exception { + assertConversion( + "some.thing=vvvv\n" + + "# Line comment\n" + + "some.other.thing=blah\n" + , // ==> + "# Conversion to YAML from Properties formar report\n" + + "# Warnings:\n" + + "# - The yaml file had comments which are lost in the refactoring!\n" + + "some:\n" + + " thing: vvvv\n" + + " other:\n" + + " thing: blah\n", + true + ); + } + +} diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommandTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommandTest.java new file mode 100644 index 0000000000..fccbe4286f --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/properties/YamlToPropertiesCommandTest.java @@ -0,0 +1,263 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.properties; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; + +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.ShowDocumentResult; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest; +import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; +import org.springframework.ide.vscode.project.harness.ProjectsHarness; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@BootLanguageServerTest +@Import({SymbolProviderTestConf.class}) +public class YamlToPropertiesCommandTest { + + private static final String FILENAME_SUFFIX = "-conversion-test"; + + @Autowired private LanguageServerHarness harness; + @Autowired private JavaProjectFinder projectFinder; + + private File directory; + + @BeforeEach public void setup() throws Exception { + harness.intialize(null); + + directory = new File(ProjectsHarness.class.getResource("/test-projects/test-spring-validations/").toURI()); + + Files.walk(directory.toPath(), Integer.MAX_VALUE).filter(Files::isRegularFile).filter(p -> p.getFileName().toString().contains(FILENAME_SUFFIX)).forEach(t -> { + try { + Files.delete(t); + } catch (IOException e) { + + } + }); + + String projectDir = directory.toURI().toString(); + + // trigger project creation + projectFinder.find(new TextDocumentIdentifier(projectDir)).get(); + } + + @AfterEach public void tearDown() throws Exception { + if (directory != null && directory.exists()) { + Files.walk(directory.toPath(), Integer.MAX_VALUE).filter(Files::isRegularFile).filter(p -> p.getFileName().toString().contains(FILENAME_SUFFIX)).forEach(t -> { + try { + Files.delete(t); + } catch (IOException e) { + + } + }); + } + } + + @Test void simple() throws Exception { + assertConversion(""" + some: + other: + thing: blah + thing: vvvv + """, + """ + some.other.thing=blah + some.thing=vvvv + """, + true); + } + + @Test void noReplacement() throws Exception { + assertConversion(""" + some: + other: + thing: blah + thing: vvvv + """, + """ + some.other.thing=blah + some.thing=vvvv + """, + false); + } + + @Test public void almostHasComments() throws Exception { + assertConversion( + "my:\n" + + " goodbye: 'See ya # later'\n" + + " hello: Good morning!\n" + , // ==> + "my.goodbye=See ya \\# later\n" + + "my.hello=Good morning\\!\n", + true + ); + } + + @Test public void listItems() throws Exception { + assertConversion( + "some:\n" + + " thing:\n" + + " - a: first-a\n" + + " b: first-b\n" + + " - a: second-a\n" + + " b: second-b\n" + , // ==> + "some.thing[0].a=first-a\n" + + "some.thing[0].b=first-b\n" + + "some.thing[1].a=second-a\n" + + "some.thing[1].b=second-b\n", + true + ); + } + + @Test public void list() throws Exception { + assertConversion( + "some:\n" + + " property:\n" + + " - something\n" + + " - something-else\n" + , // ==> + "some.property[0]=something\n" + + "some.property[1]=something-else\n", + true + ); + } + + @Test public void mapAndSequenceConflict() throws Exception { + assertConversion( + "some:\n" + + " property:\n" + + " '0': zero\n" + + " '1': one\n" + + " abc: val1\n" + + " def: val2\n" + , + "some.property.0=zero\n" + + "some.property.1=one\n" + + "some.property.abc=val1\n" + + "some.property.def=val2\n", + true + ); + } + + @Test public void multipleDocsConversion() throws Exception { + assertConversion( + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + + "\n" + + "---\n" + + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + + "\n" + + "---\n" + + "some:\n" + + " other:\n" + + " thing: blah\n" + + " thing: vvvv\n" + , // ==> + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + + "#---\n" + + "some.other.thing=blah\n" + + "some.thing=vvvv\n" + + "#---\n" + + "some.other.thing=blah\n" + + "some.thing=vvvv\n", + true + ); + } + + @Test void lineComment() throws Exception { + assertConversion(""" + some: + # Comment about line + other: + thing: blah + thing: vvvv + """, + """ + # Conversion to YAML from Properties formar report + # Warnings: + # - The yaml file had comments which are lost in the refactoring! + some.other.thing=blah + some.thing=vvvv + """, + true); + } + + @Test void inlineComment() throws Exception { + assertConversion(""" + some: + other: + thing: blah # Inline Comment + thing: vvvv + """, + """ + # Conversion to YAML from Properties formar report + # Warnings: + # - The yaml file had comments which are lost in the refactoring! + some.other.thing=blah + some.thing=vvvv + """, + true); + } + + void assertConversion(String yamlContent, String propsContent, boolean replace) throws Exception { + Path yamlFilePath = directory.toPath().resolve("src/main/resources/application" + FILENAME_SUFFIX + ".yml"); + Path propsFilePath = directory.toPath().resolve("src/main/resources/application" + FILENAME_SUFFIX + ".properties"); + + if (!Files.exists(yamlFilePath)) { + Files.createDirectories(yamlFilePath.getParent()); + Files.createFile(yamlFilePath); + Files.write(yamlFilePath, yamlContent.getBytes(), StandardOpenOption.APPEND); + } + + Command cmd = new Command(); + cmd.setCommand(YamlToPropertiesCommand.CMD_YAML_TO_PROPS); + cmd.setArguments(List.of(yamlFilePath.toUri().toASCIIString(), propsFilePath.toUri().toASCIIString(), replace)); + cmd.setTitle("Convert .yaml to .properties"); + + ShowDocumentResult res = (ShowDocumentResult) harness.perform(cmd); + + assertThat(res.isSuccess()).isTrue(); + + assertThat(Files.exists(propsFilePath)).isTrue(); + if (replace) { + assertThat(Files.exists(yamlFilePath)).isFalse(); + } else { + assertThat(Files.exists(yamlFilePath)).isTrue(); + } + + assertThat(Files.readString(propsFilePath)).isEqualTo(propsContent); + } + +} diff --git a/headless-services/xml-ls-extension/pom.xml b/headless-services/xml-ls-extension/pom.xml index a3bfa6ecc8..a954e532e5 100644 --- a/headless-services/xml-ls-extension/pom.xml +++ b/headless-services/xml-ls-extension/pom.xml @@ -9,7 +9,7 @@ org.springframework.ide.vscode commons-parent - 1.53.0-SNAPSHOT + 1.54.0-SNAPSHOT ../commons/pom.xml diff --git a/vscode-extensions/vscode-bosh/CHANGELOG.md b/vscode-extensions/vscode-bosh/CHANGELOG.md index 728cf458ab..523d0cd990 100644 --- a/vscode-extensions/vscode-bosh/CHANGELOG.md +++ b/vscode-extensions/vscode-bosh/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2024-03-13 (4.22.0 RELEASE, incl. language servers version 1.53.0) + +* no major changes + ## 2024-02-07 (4.21.1 RELEASE, incl. language servers version 1.52.0) * no major changes diff --git a/vscode-extensions/vscode-bosh/package.json b/vscode-extensions/vscode-bosh/package.json index 48b5b85a14..7b3242e6a4 100644 --- a/vscode-extensions/vscode-bosh/package.json +++ b/vscode-extensions/vscode-bosh/package.json @@ -3,7 +3,7 @@ "displayName": "Bosh Editor", "description": "Provides validation and content assist for various Bosh configuration files", "icon": "icon.png", - "version": "1.53.0", + "version": "1.54.0", "publisher": "vmware", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-concourse/CHANGELOG.md b/vscode-extensions/vscode-concourse/CHANGELOG.md index 8fdb732cef..d8c12120f3 100644 --- a/vscode-extensions/vscode-concourse/CHANGELOG.md +++ b/vscode-extensions/vscode-concourse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2024-03-13 (4.22.0 RELEASE, incl. language servers version 1.53.0) + +* no major changes + ## 2024-02-07 (4.21.1 RELEASE, incl. language servers version 1.52.0) * _(Concourse)_ [Concourse] `set\_pipeline` step considers `team` attribute invalid [#1174](https://github.com/spring-projects/sts4/issues/1174) diff --git a/vscode-extensions/vscode-concourse/package.json b/vscode-extensions/vscode-concourse/package.json index 125e54e7c9..96b8499065 100644 --- a/vscode-extensions/vscode-concourse/package.json +++ b/vscode-extensions/vscode-concourse/package.json @@ -3,7 +3,7 @@ "displayName": "Concourse CI Pipeline Editor", "description": "Provides validation and content assist for Concourse CI pipeline and task configuration yml files", "icon": "icon.png", - "version": "1.53.0", + "version": "1.54.0", "publisher": "vmware", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-manifest-yaml/CHANGELOG.md b/vscode-extensions/vscode-manifest-yaml/CHANGELOG.md index e0b5c3703b..a9a6fea75a 100644 --- a/vscode-extensions/vscode-manifest-yaml/CHANGELOG.md +++ b/vscode-extensions/vscode-manifest-yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2024-03-13 (4.22.0 RELEASE, incl. language servers version 1.53.0) + +* no major changes + ## 2024-02-07 (4.21.1 RELEASE, incl. language servers version 1.52.0) * no major changes diff --git a/vscode-extensions/vscode-manifest-yaml/package.json b/vscode-extensions/vscode-manifest-yaml/package.json index 8bc5776cbb..fd3b96541d 100644 --- a/vscode-extensions/vscode-manifest-yaml/package.json +++ b/vscode-extensions/vscode-manifest-yaml/package.json @@ -3,7 +3,7 @@ "displayName": "Cloudfoundry Manifest YML Support", "description": "Adds linting, content assist and hoverinfo's for Cloudfoundry Deployment Manifests (a.k.a. `manifest.yml`) files.", "icon": "icon.png", - "version": "1.53.0", + "version": "1.54.0", "publisher": "vmware", "repository": { "type": "git", diff --git a/vscode-extensions/vscode-spring-boot/CHANGELOG.md b/vscode-extensions/vscode-spring-boot/CHANGELOG.md index 2bf7da4b8c..67a7196aef 100644 --- a/vscode-extensions/vscode-spring-boot/CHANGELOG.md +++ b/vscode-extensions/vscode-spring-boot/CHANGELOG.md @@ -1,3 +1,19 @@ +## 2024-03-13 (4.22.0 RELEASE, incl. language servers version 1.53.0) + +#### important highlights + +* _(Spring Boot)_ **Add Spring Boot Starters...** InlayHint in Spring Boot projects `pom.xml` next to `` tag (VSCode only at the moment) + +#### all fixes and improvements in detail + +* _(Spring Boot)_ `Add Starters` CodeLens/InlayHint in the Spring Boot's project pom [#1194](https://github.com/spring-projects/sts4/issues/1194) +* _(Spring Boot)_ adjustments to version validations [#1199](https://github.com/spring-projects/sts4/issues/1199) +* _(Spring Boot)_ TestJars support [#1197](https://github.com/spring-projects/sts4/issues/1197) +* _(Spring Boot)_ Bind update of Spring Modulith metadata to a full project build [#1172](https://github.com/spring-projects/sts4/issues/1172) +* _(Spring Boot)_ exception thrown under the hood when file URL protocol is unknown [#1192](https://github.com/spring-projects/sts4/issues/1192) +* _(Spring Boot)_ Fix JavaModelException with non-Java projects [#1188](https://github.com/spring-projects/sts4/pull/1188) +* _(Spring Boot)_ throws exception when closing editors [#1179](https://github.com/spring-projects/sts4/issues/1179) + ## 2024-02-07 (4.21.1 RELEASE, incl. language servers version 1.52.0) #### important highlights diff --git a/vscode-extensions/vscode-spring-boot/lib/Main.ts b/vscode-extensions/vscode-spring-boot/lib/Main.ts index 089673929c..51769e1b2b 100644 --- a/vscode-extensions/vscode-spring-boot/lib/Main.ts +++ b/vscode-extensions/vscode-spring-boot/lib/Main.ts @@ -1,8 +1,13 @@ 'use strict'; import * as OS from "os"; -import * as VSCode from 'vscode'; -import { workspace } from 'vscode'; +import { + commands, + window, + workspace, + ExtensionContext, + Uri + } from 'vscode'; import * as commons from '@pivotal-tools/commons-vscode'; import * as liveHoverUi from './live-hover-connect-ui'; @@ -14,6 +19,8 @@ import { ExtensionAPI } from "./api"; import {registerClasspathService} from "@pivotal-tools/commons-vscode/lib/classpath"; import {registerJavaDataService} from "@pivotal-tools/commons-vscode/lib/java-data"; import * as setLogLevelUi from './set-log-levels-ui'; +import { startTestJarSupport } from "./test-jar-launch"; +import { startPropertiesConversionSupport } from "./convert-props-yaml"; const PROPERTIES_LANGUAGE_ID = "spring-boot-properties"; const YAML_LANGUAGE_ID = "spring-boot-properties-yaml"; @@ -24,7 +31,7 @@ const FACTORIES_LANGUAGE_ID = "spring-factories"; const STOP_ASKING = "Stop Asking"; /** Called when extension is activated */ -export function activate(context: VSCode.ExtensionContext): Thenable { +export function activate(context: ExtensionContext): Thenable { // registerPipelineGenerator(context); let options : commons.ActivatorOptions = { @@ -34,16 +41,15 @@ export function activate(context: VSCode.ExtensionContext): Thenable { + checkjvm: (context: ExtensionContext, jvm: commons.JVM) => { let version = jvm.getMajorVersion(); if (version < 17) { throw Error(`Spring Tools Language Server requires Java 17 or higher to be launched. Current Java version is ${version}`); } if (!jvm.isJdk()) { - VSCode.window.showWarningMessage( + window.showWarningMessage( 'JAVA_HOME or PATH environment variable seems to point to a JRE. A JDK is required, hence Boot Hints are unavailable.', STOP_ASKING).then(selection => { if (selection === STOP_ASKING) { @@ -58,7 +64,7 @@ export function activate(context: VSCode.ExtensionContext): Thenable VSCode.Uri.parse(uri) + protocol2Code: uri => Uri.parse(uri) }, // See PT-158992999 as to why a scheme is added to the document selector // documentSelector: [ PROPERTIES_LANGUAGE_ID, YAML_LANGUAGE_ID, JAVA_LANGUAGE_ID ], @@ -136,33 +142,50 @@ export function activate(context: VSCode.ExtensionContext): Thenable { - VSCode.commands.registerCommand('vscode-spring-boot.ls.start', () => client.start().then(() => { + commands.registerCommand('vscode-spring-boot.ls.start', () => client.start().then(() => { // Boot LS is fully started registerClasspathService(client); registerJavaDataService(client); // Force classpath listener to be enabled. Boot LS can only be launched iff classpath is available and there Spring-Boot on the classpath somewhere. - VSCode.commands.executeCommand('sts.vscode-spring-boot.enableClasspathListening', true); + commands.executeCommand('sts.vscode-spring-boot.enableClasspathListening', true); + + // Register TestJars launch support + context.subscriptions.push(startTestJarSupport()); + })); - VSCode.commands.registerCommand('vscode-spring-boot.ls.stop', () => client.stop()); + commands.registerCommand('vscode-spring-boot.ls.stop', () => client.stop()); liveHoverUi.activate(client, options, context); rewrite.activate(client, options, context); setLogLevelUi.activate(client, options, context); + startPropertiesConversionSupport(context); + + registerMiscCommands(context); - VSCode.commands.registerCommand('vscode-spring-boot.spring.modulith.metadata.refresh', async () => { - const modulithProjects = await VSCode.commands.executeCommand('sts/modulith/projects'); + return new ApiManager(client).api; + }); +} + +function registerMiscCommands(context: ExtensionContext) { + context.subscriptions.push( + commands.registerCommand('vscode-spring-boot.spring.modulith.metadata.refresh', async () => { + const modulithProjects = await commands.executeCommand('sts/modulith/projects'); const projectNames = Object.keys(modulithProjects); if (projectNames.length === 0) { - VSCode.window.showErrorMessage('No Spring Modulith projects found'); + window.showErrorMessage('No Spring Modulith projects found'); } else { - const projectName = projectNames.length === 1 ? projectNames[0] : await VSCode.window.showQuickPick( + const projectName = projectNames.length === 1 ? projectNames[0] : await window.showQuickPick( projectNames, { placeHolder: "Select the target project." }, ); - VSCode.commands.executeCommand('sts/modulith/metadata/refresh', modulithProjects[projectName]); + commands.executeCommand('sts/modulith/metadata/refresh', modulithProjects[projectName]); } - }); + }), - return new ApiManager(client).api; - }); + commands.registerCommand('vscode-spring-boot.open.url', (openUrl) => { + const openWithExternalBrowser = workspace.getConfiguration("spring.tools").get("openWith") === "external"; + const browserCommand = openWithExternalBrowser ? "vscode.open" : "simpleBrowser.api.open"; + return commands.executeCommand(browserCommand, Uri.parse(openUrl)); + }), + ); } diff --git a/vscode-extensions/vscode-spring-boot/lib/convert-props-yaml.ts b/vscode-extensions/vscode-spring-boot/lib/convert-props-yaml.ts new file mode 100644 index 0000000000..857daefa17 --- /dev/null +++ b/vscode-extensions/vscode-spring-boot/lib/convert-props-yaml.ts @@ -0,0 +1,56 @@ +import * as path from "path"; +import { existsSync } from "fs"; +import { ExtensionContext, Uri, commands, window, workspace } from "vscode"; + +export function startPropertiesConversionSupport(extension: ExtensionContext) { + extension.subscriptions.push( + commands.registerCommand('vscode-spring-boot.props-to-yaml', async (uri) => { + + if (!uri && window.activeTextEditor) { + const activeUri = window.activeTextEditor.document.uri; + if (".properties" === path.extname(activeUri.path)) { + uri = activeUri; + } + } + + if (!uri) { + throw new Error("No '.properties' file selected"); + } + + return await commands.executeCommand("sts/boot/props-to-yaml", uri.toString(), Uri.file(getTargetFile(uri.path, "yml")).toString(), shouldReplace()); + }), + + commands.registerCommand('vscode-spring-boot.yaml-to-props', async (uri) => { + + if (!uri && window.activeTextEditor) { + const activeUri = window.activeTextEditor.document.uri; + const ext = path.extname(activeUri.path) + if (".yml" === ext || ".yaml" === ext) { + uri = activeUri; + } + } + + if (!uri) { + throw new Error("No '.yaml' file selected"); + } + + return await commands.executeCommand("sts/boot/yaml-to-props", uri.toString(), Uri.file(getTargetFile(uri.path, "properties")).toString(), shouldReplace()); + }) + ); +} + +function getTargetFile(sourcePath: string, ext: string): string { + const dir = path.dirname(sourcePath); + const fileName = path.basename(sourcePath); + const filenameNoExt = path.basename(sourcePath).substring(0, fileName.length - path.extname(fileName).length); + let targetPath = path.join(dir, `${filenameNoExt}.${ext}`); + for (let i = 1; i < Number.MAX_SAFE_INTEGER && existsSync(targetPath); i++) { + targetPath = path.join(dir, `${filenameNoExt}-${i}.${ext}`) + } + return targetPath; +} + +function shouldReplace(): boolean { + return workspace.getConfiguration("spring.tools.properties").get("replace-converted-file"); +} + diff --git a/vscode-extensions/vscode-spring-boot/lib/debug-config-provider.ts b/vscode-extensions/vscode-spring-boot/lib/debug-config-provider.ts index 192acf338b..ad4f4e2790 100644 --- a/vscode-extensions/vscode-spring-boot/lib/debug-config-provider.ts +++ b/vscode-extensions/vscode-spring-boot/lib/debug-config-provider.ts @@ -1,7 +1,15 @@ -import { CancellationToken, DebugConfiguration, DebugConfigurationProvider, ProviderResult, WorkspaceFolder } from "vscode"; +import { debug, + commands, + CancellationToken, + DebugConfiguration, + DebugConfigurationProvider, + WorkspaceFolder, + DebugConfigurationProviderTriggerKind, + DebugSessionCustomEvent, + Disposable, + ProviderResult +} from "vscode"; import * as path from "path"; -import * as VSCode from "vscode"; -import { Disposable } from "vscode"; import psList from 'ps-list'; import { ListenablePreferenceSetting } from "@pivotal-tools/commons-vscode/lib/launch-util"; @@ -11,14 +19,21 @@ const ADMIN_VM_ARG = '-Dspring.application.admin.enabled=' const BOOT_PROJECT_ARG = '-Dspring.boot.project.name='; const RMI_HOSTNAME = '-Djava.rmi.server.hostname=localhost'; -const TEST_RUNNER_MAIN_CLASSES = [ +export const TEST_RUNNER_MAIN_CLASSES = [ 'org.eclipse.jdt.internal.junit.runner.RemoteTestRunner', 'com.microsoft.java.test.runner.Launcher' ]; +interface ProcessEvent { + type: string; + processId: number; + shellProcessId: number +} + class SpringBootDebugConfigProvider implements DebugConfigurationProvider { resolveDebugConfigurationWithSubstitutedVariables(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult { + // Running app live hovers support if (!TEST_RUNNER_MAIN_CLASSES.includes(debugConfiguration.mainClass) && isActuatorOnClasspath(debugConfiguration)) { if (debugConfiguration.vmArgs) { if (debugConfiguration.vmArgs.indexOf(JMX_VM_ARG) < 0) { @@ -45,13 +60,7 @@ class SpringBootDebugConfigProvider implements DebugConfigurationProvider { } -interface ProcessEvent { - type: string; - processId: number; - shellProcessId: number -} - -function hookListenerToBooleanPreference(setting: string, listenerCreator: () => Disposable): Disposable { +export function hookListenerToBooleanPreference(setting: string, listenerCreator: () => Disposable): Disposable { const listenableSetting = new ListenablePreferenceSetting(setting); let listener: Disposable | undefined = listenableSetting.value ? listenerCreator() : undefined; listenableSetting.onDidChangeValue(() => { @@ -79,22 +88,22 @@ function hookListenerToBooleanPreference(setting: string, listenerCreator: () => export function startDebugSupport(): Disposable { return hookListenerToBooleanPreference( - 'boot-java.live-information.automatic-connection.on', - () => Disposable.from( - VSCode.debug.onDidReceiveDebugSessionCustomEvent(handleCustomDebugEvent), - VSCode.debug.registerDebugConfigurationProvider('java', new SpringBootDebugConfigProvider(), VSCode.DebugConfigurationProviderTriggerKind.Initial) - ) + 'boot-java.live-information.automatic-connection.on', + () => Disposable.from( + debug.onDidReceiveDebugSessionCustomEvent(handleCustomDebugEvent), + debug.registerDebugConfigurationProvider('java', new SpringBootDebugConfigProvider(), DebugConfigurationProviderTriggerKind.Initial) + ) ); } -async function handleCustomDebugEvent(e: VSCode.DebugSessionCustomEvent): Promise { +async function handleCustomDebugEvent(e: DebugSessionCustomEvent): Promise { if (e.session?.type === 'java' && e?.body?.type === 'processid') { const debugConfiguration: DebugConfiguration = e.session.configuration; if (canConnect(debugConfiguration)) { setTimeout(async () => { const pid = await getAppPid(e.body as ProcessEvent); const processKey = pid.toString(); - VSCode.commands.executeCommand('sts/livedata/connect', { processKey }); + commands.executeCommand('sts/livedata/connect', { processKey }); }, 500); } } diff --git a/vscode-extensions/vscode-spring-boot/lib/test-jar-launch.ts b/vscode-extensions/vscode-spring-boot/lib/test-jar-launch.ts new file mode 100644 index 0000000000..87c7af5e6e --- /dev/null +++ b/vscode-extensions/vscode-spring-boot/lib/test-jar-launch.ts @@ -0,0 +1,100 @@ +import { CancellationToken, DebugConfiguration, DebugConfigurationProvider, DebugConfigurationProviderTriggerKind, DebugSession, Disposable, WorkspaceFolder, commands, debug, window } from "vscode"; +import { TEST_RUNNER_MAIN_CLASSES, hookListenerToBooleanPreference } from "./debug-config-provider"; +import path from "path"; +import { tmpdir } from "os"; +import { randomUUID } from "crypto"; +import * as fs from "fs"; + +const ENV_TESTJAR_ARTIFACT_PREFIX = "TESTJARS_ARTIFACT_"; + +interface ExecutableBootProject { + name: string; + uri: string; + mainClass: string; + classpath: string[]; + gav: string; +} + +class TestJarDebugConfigProvider implements DebugConfigurationProvider { + + async resolveDebugConfigurationWithSubstitutedVariables(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): Promise { + // TestJar launch support + if (TEST_RUNNER_MAIN_CLASSES.includes(debugConfiguration.mainClass) && isTestJarsOnClasspath(debugConfiguration)) { + const projects = await commands.executeCommand("sts/spring-boot/executableBootProjects") as ExecutableBootProject[]; + let env = debugConfiguration.env; + if (!env) { + env = {}; + debugConfiguration.env = env; + } + const projectsWithErrors: ExecutableBootProject[] = []; + // Create all project classparth data files and add env vars for workspace projects + await Promise.all(projects.map(async p => { + const envName = this.createEnvVarName(p); + if (!env[envName]) { + try { + env[envName] = await this.createFile(p); + } catch (error) { + projectsWithErrors.push(p); + } + } + })); + if (projectsWithErrors.length > 0) { + const projectStr = projectsWithErrors.map(p => `'${p.name}'`); + window.showWarningMessage(`TestJar Support: Could not provide data for workspace projects: ${projectStr}`); + } + } + return debugConfiguration; + } + + private createEnvVarName(project: ExecutableBootProject) { + return `${ENV_TESTJAR_ARTIFACT_PREFIX}${project.gav.replace(/:/g, "_")}`; + } + + private async createFile(project: ExecutableBootProject) { + const filePath = path.join(tmpdir(), `${project.gav.replace(/:/g, "_")}-${randomUUID()}`); + await fs.writeFile(filePath, `# the main class to invoke\nmain=${project.mainClass}\n# the classpath to use delimited by the OS specific delimiters\nclasspath=${project.classpath.join(path.delimiter)}`, function(err) { + if(err) { + throw Error(); + } + }); + return filePath; + } + +} + +export function startTestJarSupport(): Disposable { + return hookListenerToBooleanPreference( + 'boot-java-vscode-only.test-jars', + () => Disposable.from( + debug.onDidTerminateDebugSession(cleanupDebugSession), + debug.registerDebugConfigurationProvider('java', new TestJarDebugConfigProvider(), DebugConfigurationProviderTriggerKind.Initial), + new Disposable(() => cleanupDebugSession(debug.activeDebugSession)) // If VSCode is shutdown then clean active debug session if it satisfies conditions + ) + ); +} + +async function cleanupDebugSession(session: DebugSession) { + // Handle termination of a Boot app with TestJars on the classpath + if (session.type === 'java' && TEST_RUNNER_MAIN_CLASSES.includes(session.configuration.mainClass) && isTestJarsOnClasspath(session.configuration) && session.configuration.env) { + await Promise.all(Object.keys(session.configuration.env).filter(k => k.startsWith(ENV_TESTJAR_ARTIFACT_PREFIX)).map(k => fs.rm(session.configuration.env[k], () => {}))); + } +} + +function isTestJarsOnClasspath(debugConfiguration: DebugConfiguration): boolean { + if (Array.isArray(debugConfiguration.classPaths)) { + return !!debugConfiguration.classPaths.find(isTestJarFile); + } + return false; + +} + +function isTestJarFile(f: string): boolean { + const fileName = path.basename(f || ""); + if (/^spring-boot-testjars-\d+\.\d+\.\d+(.*)?.jar$/.test(fileName)) { + return true; + } + return false; +} + + + diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index 917bd1c605..13f67e1308 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -3,7 +3,7 @@ "displayName": "Spring Boot Tools", "description": "Provides validation and content assist for Spring Boot `application.properties`, `application.yml` properties files. As well as Boot-specific support for `.java` files.", "icon": "spring-boot-logo.png", - "version": "1.53.0", + "version": "1.54.0", "publisher": "vmware", "repository": { "type": "git", @@ -82,6 +82,16 @@ "when": "resourceFilename == pom.xml || resourceFilename == build.gradle", "command": "vscode-spring-boot.rewrite.list.boot-upgrades", "group": "SpringBoot" + }, + { + "when": "editorLangId == spring-boot-properties", + "command": "vscode-spring-boot.props-to-yaml", + "group": "SpringBoot" + }, + { + "when": "editorLangId == spring-boot-properties-yaml", + "command": "vscode-spring-boot.yaml-to-props", + "group": "SpringBoot" } ], "explorer/context": [ @@ -94,6 +104,26 @@ "when": "(resourceFilename == pom.xml || resourceFilename == build.gradle) && config.boot-java.rewrite.refactorings.on == true", "command": "vscode-spring-boot.rewrite.list.boot-upgrades", "group": "SpringBoot" + }, + { + "when": "resourceExtname == .properties", + "command": "vscode-spring-boot.props-to-yaml", + "group": "SpringBoot" + }, + { + "when": "resourceExtname == .yml || resourceExtname == .yaml", + "command": "vscode-spring-boot.yaml-to-props", + "group": "SpringBoot" + } + ], + "commandPalette": [ + { + "command": "vscode-spring-boot.props-to-yaml", + "when": "false" + }, + { + "command": "vscode-spring-boot.yaml-to-props", + "when": "false" } ] }, @@ -134,6 +164,22 @@ "command": "vscode-spring-boot.set.log-levels", "title": "Set Log Levels", "category": "Spring Boot" + }, + { + "command": "vscode-spring-boot.open.url", + "title": "Open Boot App Page URL", + "category": "Spring Boot", + "enablement": "never" + }, + { + "command": "vscode-spring-boot.props-to-yaml", + "title": "Convert .properties to .yaml", + "category": "Spring Boot" + }, + { + "command": "vscode-spring-boot.yaml-to-props", + "title": "Convert .yaml to .properties", + "category": "Spring Boot" } ], "configuration": [ @@ -228,6 +274,35 @@ ] }, "description": "Array of jmx urls pointing to remote spring boot applications to poll for live hover information. A typical url looks something like this: `service:jmx:rmi://localhost:9111/jndi/rmi://localhost:9111/jmxrmi`" + }, + "boot-java.modulith-project-tracking": { + "type": "boolean", + "default": true, + "description": "Spring Boot Modulith automatic project tracking and metadata update" + }, + "boot-java-vscode-only.test-jars": { + "type": "boolean", + "default": true, + "description": "Enable/Disable Spring Boot TestJars launch environment variables" + }, + "spring.tools.properties.replace-converted-file": { + "type": "boolean", + "default": false, + "description": "Replace converted properties file" + }, + "spring.tools.openWith": { + "default": "integrated", + "type": "string", + "enum": [ + "integrated", + "external" + ], + "enumDescriptions": [ + "VS Code's integrated browser", + "External default browser" + ], + "scope": "window", + "description": "Defines which browser to use when opening Spring Boot apps web pages." } } }, @@ -245,8 +320,7 @@ "type": "array", "default": [ "org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration", - "org.openrewrite.java.spring.boot2.SpringBoot2BestPractices", - "org.openrewrite.java.spring.boot2.SpringBoot1To2Migration", + "org.openrewrite.java.spring.boot3.SpringBoot3BestPractices", "org.openrewrite.java.testing.junit5.JUnit5BestPractices", "org.openrewrite.java.testing.junit5.JUnit4to5Migration", "org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7", @@ -924,7 +998,7 @@ }, "spring-boot.ls.problem.version-validation.UNSUPPORTED_OSS_VERSION": { "type": "string", - "default": "HINT", + "default": "WARNING", "description": "Unsupported OSS Version", "enum": [ "IGNORE", @@ -936,7 +1010,7 @@ }, "spring-boot.ls.problem.version-validation.UNSUPPORTED_COMMERCIAL_VERSION": { "type": "string", - "default": "HINT", + "default": "WARNING", "description": "Unsupported Commercial Version", "enum": [ "IGNORE", diff --git a/vscode-extensions/vscode-spring-cli/package.json b/vscode-extensions/vscode-spring-cli/package.json index 8e04a5d593..63e6e6c2b7 100644 --- a/vscode-extensions/vscode-spring-cli/package.json +++ b/vscode-extensions/vscode-spring-cli/package.json @@ -3,7 +3,7 @@ "displayName": "Spring CLI Support", "description": "Spring CLI integrated into IDE", "icon": "spring-boot-logo.png", - "version": "1.53.0", + "version": "1.54.0", "publisher": "vmware", "repository": { "type": "git",