diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..35ef0867fe --- /dev/null +++ b/.eslintignore @@ -0,0 +1,22 @@ +# .gitignore +out +server +node_modules +*.vsix +.DS_Store +.vscode-test +undefined +target +dist +jre +lombok +bin/ +.settings +.classpath +.project +test/resources/projects/**/.vscode +test/resources/projects/maven/salut/testGradle +test-temp + +# specific to eslint +vscode*.d.ts \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..fa1f618636 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,115 @@ +{ + "env": { + "es6": true, + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "project": [ + "tsconfig.webview.json", + "tsconfig.json" + ] + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/member-delimiter-style": [ + "error", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false + } + } + ], + "@typescript-eslint/naming-convention": "error", + "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/semi": [ + "error", + "always" + ], + "@typescript-eslint/type-annotation-spacing": "error", + "curly": [ + "error", + "multi-line" + ], + "eqeqeq": [ + "error", + "always" + ], + "id-denylist": [ + "error", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined", + "undefined" + ], + "id-match": "error", + "no-debugger": "error", + "no-multiple-empty-lines": "error", + "no-trailing-spaces": "error", + "no-underscore-dangle": "error", + "no-var": "error", + "prefer-arrow-callback": [ + "error", + { + "allowNamedFunctions": true + } + ], + "prefer-const": "error", + "prefer-template": "error", + "quote-props": [ + "error", + "as-needed" + ], + "semi": "error", + "spaced-comment": [ + "error", + "always", + { + "markers": [ + "/" + ] + } + ] + }, + "overrides": [ + { + "files": [ + "**/*.js" + ], + "rules": { + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/naming-convention": "off", + "@typescript-eslint/semi": "off", + "prefer-arrow/prefer-arrow-functions": "off", + "prefer-arrow-callback": "off", + "no-useless-escape": "off", + "spaced-comment": "off", + "semi": "off", + "prefer-template": "off", + "prefer-const": "off" + } + }, + { + "files": [ + "**/*.test.ts" + ], + "rules": { + "prefer-arrow-callback": "off" + } + } + ] +} \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 472cade79b..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,20 +0,0 @@ -[provide a description of the issue] - -##### Environment -- Operating System: -- JDK version: -- Visual Studio Code version: -- Java extension version: - -##### Steps To Reproduce -1. [step 1] -2. [step 2] - -[attach a sample project reproducing the error] -[attach logs](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting#enable-logging) - -##### Current Result - -##### Expected Result - -##### Additional Informations diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..ab4541af81 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: 🐛 Bug report +about: Report an issue about editing, completion, navigation, build, etc. +title: '' +labels: ['bug'] +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the problem is. + +**To Reproduce** +Steps to reproduce the behavior: +1. [step 1] +2. [step 2] +3. ... + +[Please attach a sample project reproducing the error] +[Please attach logs. See https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting#enable-logging] + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment** +- Operating System: +- JDK version: +- Visual Studio Code version: +- Java extension version: + +**Additional Information** diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..4304c84774 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: 🧪 Issue about running unit tests + url: https://github.com/microsoft/vscode-java-test/issues/new + about: If your problem is about running or debugging unit tests, open an issue in the Test Runner for Java extension. + - name: 🏃‍♂️ Issue about running or debugging application code + url: https://github.com/microsoft/vscode-java-debug/issues/new + about: If your problem is about running or debugging Java application code, open an issue in the Debugger for Java extension. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..36bddafeb0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: 💡 Feature request +about: Suggest a new feature or improvement for editing, completion, navigation, build, etc. +title: '' +labels: ['enhancement'] +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/.github/scripts/check_and_update_jdk.py b/.github/scripts/check_and_update_jdk.py new file mode 100644 index 0000000000..a297dc1cde --- /dev/null +++ b/.github/scripts/check_and_update_jdk.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +import re +import requests +import json +import ast + +readme_ver_pattern = r'(?:(?<=Supports code from Java 1\.8 to Java )(\d+)|(?<=JavaSE-)~|(?<=path/to/jdk-)~)' # After resolving current_jdk, we will replace ~ + +# Query the Oracle website for the latest JDK version +response = requests.get('http://javadl-esd-secure.oracle.com/update/baseline.version') +latest_jdk = re.search(r'(?P\d+)\.?', response.text) +if latest_jdk is None: + print('Failed to retrieve latest JDK version') + exit(1) +latest_jdk = latest_jdk.group('major') +print(f'Latest JDK version: {latest_jdk}') + +# Query the vscode-java repo for the current supported JDK version +with open('README.md', 'r') as f: # Open the README.md file in read mode + readme = f.read() # Read the file content as a string +current_jdk = re.search(readme_ver_pattern, readme) # Search for the JDK version in the string +if current_jdk is None: + print('Failed to retrieve current JDK version') + exit(1) +current_jdk = current_jdk.group(1) +print(f'Current supported JDK version: {current_jdk}') + +# If the latest JDK version is not the same as the current supported JDK version, check the test status and update the files +if latest_jdk != current_jdk: + print(f'New JDK version detected: {latest_jdk}') + # Create a formatted string template from the URI structure + uri_base = 'https://ci.eclipse.org/ls/job/jdt-ls-main/lastCompletedBuild/testReport/org.eclipse.jdt.ls.core.internal.{package}/{java_class}/{method}/api/python' + # Define the test URLs to check using the template and list comprehension + tests = [ + uri_base.format(package='managers', java_class=c, method=m) for c, m in [('EclipseProjectImporterTest', 'testPreviewFeaturesDisabledByDefault'), ('InvisibleProjectImporterTest', 'testPreviewFeaturesEnabledByDefault'), ('MavenProjectImporterTest', f'testJava{latest_jdk}Project')] + ] + + # Check the test status for each test URL + all_tests_passed = True + for i in range(len(tests)): + response = requests.get(tests[i]) + if not response.ok: + print(f'Test #{i + 1} not found ({tests[i]})') + all_tests_passed = False + break + data = ast.literal_eval(response.text) # Use ast.literal_eval, because response.json() fails + try: + if data['status'] != 'PASSED': + print(f'Test #{i + 1} failed ({tests[i]})') + all_tests_passed = False + break + except KeyError: + print(f'Test #{i + 1} not found ({tests[i]})') + all_tests_passed = False + break + + # If all tests passed, update the README.md and the package.json files + if all_tests_passed: + print('All tests passed') + + # Replace the ~ with current_jdk + readme_ver_pattern = re.sub('~', current_jdk, readme_ver_pattern) + + # Write this to a file for the create-pull-request workflow + with open('latest_jdk.txt', 'w') as f: + f.write(latest_jdk) + + # Replace the current supported JDK version with the latest JDK version + readme = re.sub(readme_ver_pattern, latest_jdk, readme) + + # Write the updated README.md file + with open('README.md', 'w') as f: + f.write(readme) + + # Read the package.json file + with open('package.json', 'r') as f: + package = json.load(f) + + # Add the latest JDK version to the java.configuration.runtimes array + jdks_config = next(filter(lambda e: e['id'] == "java-jdks", package['contributes']['configuration'])) + jdks_config['properties']['java.configuration.runtimes']['items']['properties']['name']['enum'].append(f'JavaSE-{latest_jdk}') + + # Write the updated package.json file + with open('package.json', 'w') as f: + json.dump(package, f, indent=2) + else: + print('Some tests failed, aborting update') + exit(1) +else: + print('No new JDK version detected, nothing to do') + exit(0) +exit(0) diff --git a/.github/workflows/bump-jdk.yml b/.github/workflows/bump-jdk.yml new file mode 100644 index 0000000000..12c77badfb --- /dev/null +++ b/.github/workflows/bump-jdk.yml @@ -0,0 +1,58 @@ +name: Update JDK Version +on: + schedule: + - cron: '0 10 * * *' + workflow_dispatch: +jobs: + update-jdk-version: + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests + + - name: Check and update JDK version + run: | + if [ -f latest_jdk.txt ]; then + rm latest_jdk.txt # Remove previous records + fi + python .github/scripts/check_and_update_jdk.py + + - name: Read latest JDK version from file + run: | + if [ -f latest_jdk.txt ]; then + version=$(cat latest_jdk.txt) + echo "Latest JDK version: $version" + echo "latest_jdk=$version" >> $GITHUB_ENV # set the latest_jdk environment variable + else + echo "No new JDK version detected, nothing to do" + exit 0 + fi + + - name: Check for existing PR + id: check_pr + run: | + pr_number=$(gh pr list --search "Found JavaSE version ${{ env.latest_jdk }}" --json number --jq '.[0].number') + echo "pr_number=$pr_number" >> $GITHUB_ENV + + - name: Branch and push changes + if: ${{ success() && env.latest_jdk != '' && steps.check_pr.outputs.pr_number == '' }} + run: | + git config --global user.email "redhattools-bot@users.noreply.github.com" + git config --global user.name "redhattools-bot" + git checkout -b "update-jdk-${{ env.latest_jdk }}" + git commit -am "Bump JDK to ${{ env.latest_jdk }}" + git push origin "update-jdk-${{ env.latest_jdk }}" + gh pr create --title "Found JavaSE version ${{ env.latest_jdk }}" --body "See [Raw logs](https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks/${{ github.check_run_id }}/logs)" + diff --git a/.github/workflows/conflictDetector.yaml b/.github/workflows/conflictDetector.yaml new file mode 100644 index 0000000000..15a95fd885 --- /dev/null +++ b/.github/workflows/conflictDetector.yaml @@ -0,0 +1,12 @@ +on: + push: + branches: + - main +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: mschilde/auto-label-merge-conflicts@8c6faa8a252e35ba5e15703b3d747bf726cdb95c + with: + CONFLICT_LABEL_NAME: "has conflicts" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/duplicate-issues-detector.yaml b/.github/workflows/duplicate-issues-detector.yaml new file mode 100644 index 0000000000..b6c8e888da --- /dev/null +++ b/.github/workflows/duplicate-issues-detector.yaml @@ -0,0 +1,34 @@ +name: Potential Duplicate Issues +on: + issues: + types: [opened, edited] #edited means the issue title changed +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: wow-actions/potential-duplicates@4d4ea0352e0383859279938e255179dd1dbb67b5 #v1.1.0 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Issue title filter work with anymatch https://www.npmjs.com/package/anymatch. + # Any matched issue will stop detection immediately. + # You can specify multi filters in each line. + filter: '' + # Exclude keywords in title before detecting. + exclude: 'regression' + # Label to set, when potential duplicates are detected. + label: potential-duplicate + # Get issues with state to compare. Supported state: 'all', 'closed', 'open'. + state: all + # If similarity is higher than this threshold([0,1]), issue will be marked as duplicate. + threshold: 0.6 + # Reactions to be add to comment when potential duplicates are detected. + # Available reactions: "-1", "+1", "confused", "laugh", "heart", "hooray", "rocket", "eyes" + reactions: 'confused' + # Comment to post when potential duplicates are detected. + comment: | + We have found issues that are potential duplicates: {{#issues}} + - #{{ number }} ({{ accuracy }}%) + {{/issues}} + + If any of the issues listed above are a duplicate, please consider closing this issue & upvoting/commenting the original one. + Alternatively, if neither of the listed issues addresses your feature/bug, keep this issue open. \ No newline at end of file diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml new file mode 100644 index 0000000000..2b19f6c74c --- /dev/null +++ b/.github/workflows/no-response.yml @@ -0,0 +1,22 @@ +name: No Response + +# **What it does**: Closes issues where the original author doesn't respond to a request for information. +# **Why we have it**: To remove the need for maintainers to remember to check back on issues periodically to see if contributors have responded. + +on: + issue_comment: + types: [created] + schedule: + - cron: '0 10 * * *' + +jobs: + noResponse: + runs-on: ubuntu-latest + steps: + - uses: lee-dohm/no-response@9bb0a4b5e6a45046f00353d5de7d90fb8bd773bb #v0.5.0 + with: + token: ${{ github.token }} + daysUntilClose: 30 # Number of days of inactivity before an Issue is closed for lack of response + responseRequiredLabel: "need info" # Label indicating that a response from the original author is required + closeComment: > + This issue has been closed automatically because it needs more information and has not had recent activity. Please reach out if you have or find the answers we need so that we can investigate further. diff --git a/.github/workflows/pr-verify.yml b/.github/workflows/pr-verify.yml new file mode 100644 index 0000000000..9240c9a1be --- /dev/null +++ b/.github/workflows/pr-verify.yml @@ -0,0 +1,43 @@ +name: pr-verify + +on: [push, pull_request] + +jobs: + pr-verify-job: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + steps: + - name: Check Out Code + uses: actions/checkout@v4 + - name: Set Up NodeJS + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Set Up Java + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + - run: npm install -g typescript "@vscode/vsce" + - run: wget http://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz + - run: mkdir server && tar -xvzf jdt-language-server-latest.tar.gz -C ./server && rm jdt-language-server-latest.tar.gz + - run: npm install + - run: npm run repo:check + - run: npm run compile + - run: npm run vscode:prepublish + - run: vsce package + - run: ls -ll java-*vsix + - run: npm run eslint + - name: Run Tests + if: runner.os == 'Linux' + env: + SKIP_COMMANDS_TEST: true + run: $(echo "xvfb-run --auto-servernum") npm run test --silent + - name: Run Tests + if: runner.os != 'Linux' + env: + SKIP_COMMANDS_TEST: true + SKIP_CLASSPATH_TEST: true + run: npm run test --silent diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..eafd7f074c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,199 @@ +name: release + +on: + schedule: + - cron: '0 8 * * *' + workflow_dispatch: + inputs: + JDT_LS_VERSION: + description: 'The (optional) release version (including qualifier) of JDT-LS to use.' + type: string + publishPreRelease: + description: 'Publish a pre-release ?' + required: true + type: choice + options: + - 'true' + - 'false' + default: 'true' + publishToMarketPlace: + description: 'Publish to VS Code Marketplace ?' + required: true + type: choice + options: + - 'true' + - 'false' + default: 'false' + publishToOVSX: + description: 'Publish to OpenVSX Registry ?' + required: true + type: choice + options: + - 'true' + - 'false' + default: 'false' +jobs: + should-build-change: + runs-on: ubuntu-latest + outputs: + repo-cache-hit: ${{ steps.cache-last-commit.outputs.cache-hit }} + steps: + - uses: actions/checkout@v5 + with: + repository: 'eclipse-jdtls/eclipse.jdt.ls' + fetch-depth: 2 + path: eclipse.jdt.ls + - uses: actions/checkout@v5 + with: + repository: 'redhat-developer/vscode-java' + fetch-depth: 2 + path: vscode-java + - run: | + pushd eclipse.jdt.ls + git rev-parse HEAD >> ../lastCommit + popd + pushd vscode-java + git rev-parse HEAD >> ../lastCommit + - name: Check New Changes + id: cache-last-commit + uses: actions/cache@v5 + with: + path: lastCommit + key: lastCommit-${{ hashFiles('lastCommit') }} + packaging-job: + runs-on: ubuntu-latest + needs: should-build-change + if: ${{ needs.should-build-change.outputs.repo-cache-hit != 'true' || github.event_name != 'schedule' }} + steps: + - name: Checkout JDT-LS + if: "${{ inputs.JDT_LS_VERSION == '' }}" + uses: actions/checkout@v5 + with: + repository: eclipse-jdtls/eclipse.jdt.ls + - name: Cache Maven local repository + uses: actions/cache@v5 + with: + path: | + ~/.m2/repository + ~/.m2/wrapper + !~/.m2/repository/org/eclipse/jdt/ls + key: maven-local-${{ hashFiles('**/pom.xml') }} + - name: Set Up Java + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + - name: Build JDT-LS + if: "${{ inputs.JDT_LS_VERSION == '' }}" + run: | + ./mvnw clean verify -B -U -DskipTests -Pserver-distro + mkdir ../staging + cp org.eclipse.jdt.ls.product/distro/jdt-language-server-*.tar.gz ../staging + - name: Check Out VS Code Java + uses: actions/checkout@v5 + - name: Set Up NodeJS + uses: actions/setup-node@v5 + with: + node-version: '20' + - name: Install NodeJS dependencies + run: npm install -g typescript "@vscode/vsce" "ovsx" + - name: Download JDT-LS Release + if: "${{ inputs.JDT_LS_VERSION != '' }}" + run: | + version=`echo ${{ inputs.JDT_LS_VERSION }} | cut -d- -f1` + curl -LO https://download.eclipse.org/jdtls/milestones/${version}/jdt-language-server-${{ inputs.JDT_LS_VERSION }}.tar.gz + - name: Build vscode-java + run: | + npm install + - name: Prepare JDT-LS + run: | + rm -rf ./out + mkdir server/ + if [ -e jdt-language-server-*.tar.gz ]; then + tar -xf jdt-language-server-*.tar.gz -C server/ + else + tar -xf ../staging/jdt-language-server-*.tar.gz -C server/ + fi + echo "EXT_VERSION=$(cat package.json | jq -r .version)" >> $GITHUB_ENV + - name: Test vscode-java + env: + SKIP_COMMANDS_TEST: true + run: | + xvfb-run --auto-servernum npm run test --silent + continue-on-error: true + - name: Clean tests + run: npm run clean-test-folder + - name: Prepare Lombok Support + if: false + run: | + npm run download-lombok + - name: Prepare Pre-Release + if: ${{ github.event_name == 'schedule' || inputs.publishPreRelease == 'true' }} + run: | + npm run prepare-pre-release + echo "publishPreReleaseFlag=--pre-release" >> $GITHUB_ENV + - name: Package vscode-java + run: | + # Compile JavaScript once for the universal VSIX (webpack is platform-independent) + vsce package ${{ env.publishPreReleaseFlag }} -o vscode-java-${{ env.EXT_VERSION }}-${GITHUB_RUN_NUMBER}.vsix + + # Package for each platform (only downloads JDK and creates VSIX, no recompilation) + platforms=("win32-x64" "win32-arm64" "linux-x64" "linux-arm64" "darwin-x64" "darwin-arm64") + for platform in ${platforms[@]}; do + npm run download-jre -- --target ${platform} --javaVersion 21 + SKIP_WEBPACK=true vsce package ${{ env.publishPreReleaseFlag }} --target ${platform} -o java-${platform}-${{ env.EXT_VERSION }}-${GITHUB_RUN_NUMBER}.vsix + done + + ls -lash *.vsix + - name: Upload VSIX Artifacts + uses: actions/upload-artifact@v5 + with: + name: vscode-java + path: | + java-*-${{ env.EXT_VERSION }}-${{github.run_number}}.vsix + vscode-java-${{ env.EXT_VERSION }}-${{github.run_number}}.vsix + if-no-files-found: error + - name: Publish to GH Release Tab + if: ${{ inputs.publishToMarketPlace == 'true' && inputs.publishToOVSX == 'true' }} + uses: "marvinpinto/action-automatic-releases@919008cf3f741b179569b7a6fb4d8860689ab7f0" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "v${{ env.EXT_VERSION }}" + title: "${{ env.EXT_VERSION }}" + draft: true + files: | + java-*-${{ env.EXT_VERSION }}-${{github.run_number}}.vsix + vscode-java-${{ env.EXT_VERSION }}-${{ github.run_number }}.vsix + release-job: + environment: ${{ (inputs.publishToMarketPlace == 'true' || inputs.publishToOVSX == 'true') && 'release' || 'pre-release' }} + runs-on: ubuntu-latest + needs: packaging-job + steps: + - name: Set Up NodeJS + uses: actions/setup-node@v5 + with: + node-version: '20' + - name: Install dependencies + run: | + npm install -g typescript "@vscode/vsce" "ovsx" + - name: Download VSIX & JDT-LS + uses: actions/download-artifact@v5 + - name: Publish to VS Code Marketplace + if: ${{ github.event_name == 'schedule' || inputs.publishToMarketPlace == 'true' || inputs.publishPreRelease == 'true' }} + run: | + for platformVsix in java-*-*-${GITHUB_RUN_NUMBER}.vsix; do + vsce publish --skip-duplicate -p ${{ secrets.VSCODE_MARKETPLACE_TOKEN }} --packagePath ${platformVsix} + done + vsce publish --skip-duplicate -p ${{ secrets.VSCODE_MARKETPLACE_TOKEN }} --packagePath vscode-java-*-${GITHUB_RUN_NUMBER}.vsix + - name: Publish to OpenVSX Registry + if: ${{ github.event_name == 'schedule' || inputs.publishToOVSX == 'true' || inputs.publishPreRelease == 'true' }} + run: | + for platformVsix in java-*-*-${GITHUB_RUN_NUMBER}.vsix; do + ovsx publish --skip-duplicate -p ${{ secrets.OVSX_MARKETPLACE_TOKEN }} --packagePath ${platformVsix} + done + ovsx publish --skip-duplicate -p ${{ secrets.OVSX_MARKETPLACE_TOKEN }} --packagePath vscode-java-*-${GITHUB_RUN_NUMBER}.vsix + - name: Delete saved artifact + if: always() + uses: geekyeggo/delete-artifact@e46cfb9575865f907c2beb2e4170b5f4c7d77c52 + with: + name: vscode-java diff --git a/.gitignore b/.gitignore index 905e4094bf..d521724b94 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,12 @@ node_modules undefined target dist +jre +lombok bin/ .settings .classpath .project +test/resources/projects/**/.vscode +test/resources/projects/maven/salut/testGradle +test-temp diff --git a/.sdkmanrc b/.sdkmanrc new file mode 100644 index 0000000000..d2635abfaf --- /dev/null +++ b/.sdkmanrc @@ -0,0 +1,3 @@ +# Enable auto-env through the sdkman_auto_env config +# Add key=value pairs of SDKs to use below +java=21.0.5-tem diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d606e70684..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -sudo: false - -language: node_js -node_js: -- "node" - -matrix: - include: - - os: linux - dist: trusty - - os: osx - -before_install: -- if [ $TRAVIS_OS_NAME == "linux" ]; then - export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; - sh -e /etc/init.d/xvfb start; - sleep 3; - fi -- npm install -g typescript - -install: -- wget http://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz -- mkdir server -- tar -xvzf jdt-language-server-latest.tar.gz -C ./server -- rm jdt-language-server-latest.tar.gz -- npm install -- npm run compile -- npm run vscode:prepublish -- npm install -g vsce -- vsce package -- ls -ll java-*vsix - -script: -- npm test --silent diff --git a/.vscode/extensions.json b/.vscode/extensions.json index ad475c77af..7a024e4039 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,7 +3,8 @@ // for the documentation about the extensions.json format "recommendations": [ // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp - "eg2.tslint", - "EditorConfig.EditorConfig" + "dbaeumer.vscode-eslint", + "EditorConfig.EditorConfig", + "amodio.tsl-problem-matcher" ] -} \ No newline at end of file +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 14f578dcd6..7fe80719b1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,11 +7,19 @@ "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", + "debugWebviews": true, "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, + "env": { + "DEBUG_VSCODE_JAVA":"true", + "VSCODE_REDHAT_TELEMETRY_DEBUG":"true" + }, "sourceMaps": true, "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], - "preLaunchTask": "npm: watch" + "preLaunchTask": "npm: watch", + "rendererDebugOptions": { + "urlFilter": "*redhat.java*", + "sourceMaps": true, + } }, { "name": "Launch Extension - Remote Server", @@ -19,11 +27,12 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, "sourceMaps": true, "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], "env": { - "SERVER_PORT": "3333" + "JDTLS_SERVER_PORT": "3333", + "DEBUG_VSCODE_JAVA":"true", + "VSCODE_REDHAT_TELEMETRY_DEBUG":"true" }, "preLaunchTask": "npm: watch" }, @@ -32,25 +41,103 @@ "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", + "debugWebviews": true, + "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], + "sourceMaps": true, + "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], + "env": { + "JDTLS_CLIENT_PORT": "5036", + "DEBUG_VSCODE_JAVA":"true", + "VSCODE_REDHAT_TELEMETRY_DEBUG":"true" + }, + "preLaunchTask": "npm: watch", + "rendererDebugOptions": { + "urlFilter": "*redhat.java*", + "sourceMaps": true, + } + }, + { + "name": "Launch Extension - SyntaxLS Client", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, "sourceMaps": true, "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], "env": { - "JDTLS_CLIENT_PORT": "5036" + "SYNTAXLS_CLIENT_PORT": "5037", + "DEBUG_VSCODE_JAVA":"true", + "VSCODE_REDHAT_TELEMETRY_DEBUG":"true" }, "preLaunchTask": "npm: watch" }, { - "name": "Launch Tests", + "name": "Launch Extension - Hybrid Clients", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], - "stopOnEntry": false, + "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], "sourceMaps": true, - "outFiles": ["${workspaceRoot}/out/test/**"], - "preLaunchTask": "npm: compile" + "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], + "env": { + "JDTLS_CLIENT_PORT": "5036", + "SYNTAXLS_CLIENT_PORT": "5037", + "DEBUG_VSCODE_JAVA":"true", + "VSCODE_REDHAT_TELEMETRY_DEBUG":"true" + }, + "preLaunchTask": "npm: watch" + }, + { + "name": "Launch Tests - Standard Mode", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceFolder}/test-temp/", + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/standard-mode-suite" + ], + "sourceMaps": true, + "outFiles": ["${workspaceRoot}/out/**/*.js"], + "preLaunchTask": "prepareStandardTest", + "postDebugTask": "cleanTestFolder" + }, + { + "name": "Launch Tests - Lightweight Mode", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceFolder}/test-temp/", + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/lightweight-mode-suite" + ], + "sourceMaps": true, + "outFiles": ["${workspaceRoot}/out/**/*.js"], + "preLaunchTask": "prepareLightweightTest", + "postDebugTask": "cleanTestFolder" + }, + { + "args": [ + "${input:scriptTask}" + ], + "name": "Launch Build Script", + "program": "${workspaceFolder}/scripts/index.js", + "request": "launch", + "skipFiles": [ + "/**" + ], + "type": "node" + } + ], + "inputs": [ + { + "id": "scriptTask", + "type": "promptString", + "description": "Name of the build script to execute (e.g., download-jre, build-server, etc.)", + "default": "download-jre" } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 03777980ab..528142020a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,12 @@ // Place your settings in this file to overwrite default and user settings. { - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - }, - "typescript.tsdk": "./node_modules/typescript/lib", + "files.exclude": { + "out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "out": true // set this to false to include "out" folder in search results + }, + "js/ts.tsdk.path": "./node_modules/typescript/lib", + "git.alwaysSignOff": true, "vsicons.presets.angular": false // we want to use the TS server from our node_modules folder to control its version } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f35d360c28..da12f3f4aa 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,35 +1,52 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format { - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": { - "owner": "typescript", - "pattern":[ - { - "regexp": "\\[tsl\\] ERROR", - "file": 1, - "location": 2, - "message": 3 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "Compilation \\w+ starting…", - "endsPattern": "Compilation\\s+finished" - } - }, - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] + "version": "2.0.0", + "tasks": [ + { + "label": "npm: watch", + "type": "npm", + "script": "watch", + "problemMatcher": ["$ts-webpack-watch", "$eslint-stylish"], + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "npm", + "script": "clean-test-folder", + "label": "cleanTestFolder" + }, + { + "type": "npm", + "script": "generate-standard-test-folder", + "label": "generateStandardTestFolder" + }, + { + "type": "npm", + "script": "generate-lightweight-test-folder", + "label": "generateLightweightTestFolder" + }, + { + "label": "prepareStandardTest", + "dependsOn": [ + "cleanTestFolder", + "generateStandardTestFolder", + "npm: compile" + ] + }, + { + "label": "prepareLightweightTest", + "dependsOn": [ + "cleanTestFolder", + "generateLightweightTestFolder", + "npm: compile" + ] + } + ] } diff --git a/.vscodeignore b/.vscodeignore index 11d309abb8..d6d7fae145 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -8,17 +8,25 @@ images/** .gitignore .github/** tsconfig.json +tsconfig.webview.json +tsconfig.base.json vsc-extension-quickstart.md undefined/** CONTRIBUTING.md .vscode-test/** -**/**.vsix -**/**.tar.gz -dist/**/*.map +**/*.vsix +**/*.tar.gz webpack.*.json node_modules .editorconfig .travis.yml -gulpfile.jsonJenkinsfile -tslint.json +gulpfile.js +Jenkinsfile +.eslintrc.json +.eslintignore webpack.config.js +.DS_Store +.github/** +.gitignore +.tool-versions +.sdkmanrc \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c51fb88381..d08992ad8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,1447 @@ # Change Log +## 1.55.0 (June 24, 2026) + * enhancement - Use standard `decorator` instead of `annotation` token type for highlighting Java annotation. See [#4421](https://github.com/redhat-developer/vscode-java/pull/4421). + * enhancement - Add right click menu item to copy the fully qualified name of the identifier under the cursor. See [#374](https://github.com/redhat-developer/vscode-java/issues/374). + * enhancement - Add regenerate hashCode()/equals() method quick-fix. See [JLS#3764](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3764). + * enhancement - Add type annotation quick-fixes. See [JLS#3759](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3759). + * enhancement - Add Java 26 to Gradle/Java Compatibility Matrix. See [JLS#3757](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3757). + * enhancement - Add new quick-fixes (type argument and modifier related). See [JLS#3756](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3756). + * enhancement - Add varargs-related quick-fixes. See [JLS#3754](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3754). + * enhancement - Add new null annotation quick-fixes from upstream JDT. See [JLS#3752](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3752). + * enhancement - Add support for vscode path variables for settings url settings. See [JLS#2529](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2529). + * bug fix - Sanitize existing command links from hover Javadocs. See [#4429](https://github.com/redhat-developer/vscode-java/pull/4429). + * bug fix - Maven projects 5 folders deep were not loaded as Java projects. See [#4364](https://github.com/redhat-developer/vscode-java/issues/4364). + * bug fix - Prevent Javadoc entries with tables from being truncated in the hover documentation. See [#4219](https://github.com/redhat-developer/vscode-java/issues/4219). + * bug fix - Keep LSP initialize() resilient when m2e is not yet available. See [#3469](https://github.com/redhat-developer/vscode-java/issues/3469). + * bug fix - If the specified type comment template is empty, use the default. See [JLS#3816](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3816). + * bug fix - Prevent setter generation for record components. See [#JLS3812](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3812). + * bug fix - JDTLS batch file fails when located in a folder path with spaces. See [JLS#3783](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3783). + * bug fix - Completion of annotation properties proposes invalid choices. See [JLS#3604](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3604). + * bug fix - Do not offer override/implement actions for annotation types. See [JLS#3814](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3814). + +## 1.54.0 (April 15th, 2026) + * enhancement - Add `serverRunning()` API (v0.14) for progressive loading. See [#4372](https://github.com/redhat-developer/vscode-java/pull/4372). + * enhancement - Add JDK 26. See [#4367](https://github.com/redhat-developer/vscode-java/pull/4367). + * enhancement - Add inlay hints for format parameters. See [#4350](https://github.com/redhat-developer/vscode-java/issues/4350). + * enhancement - Support Scala in Gradle projects. See [#4358](https://github.com/redhat-developer/vscode-java/issues/4358). + * enhancement - Progressive project import notifications for tree view. See [JLS#3744](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3744). + * enhancement - Add Null Annotation quick-fixes from JDT to jdt.ls. See [JLS#3727](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3727). + * enhancement - Remove the first blank line from generated classes created in the default package. See [JLS#3725](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3725). + * enhancement - Add quick-assist to convert a class to a record. See [JLS#3723](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3723). + * enhancement - Enable change compiler compliance quick-fixes. See [JLS#3743](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3743). + * bug fix - Regression in 1.53.0: Gradle import stuck at 70% with Groovy support enabled in custom multi-project settings plugin layout. See [#4360](https://github.com/redhat-developer/vscode-java/issues/4360). + * bug fix - Navigating to a Kotlin class now opens the sources instead of the decompiled code. See [#4345](https://github.com/redhat-developer/vscode-java/issues/4345). + * bug fix - Quick fix "Add throws declaration" removes backslashes and qute fragments. See [#4314](https://github.com/redhat-developer/vscode-java/issues/4314). + * bug fix - Constructor code completion is broken in certain situations. See [#2336](https://github.com/redhat-developer/vscode-java/issues/2336). + * dependencies - bump brace-expansion from 1.1.12 to 1.1.13. See [#4373](https://github.com/redhat-developer/vscode-java/pull/4373). + * dependencies - bump picomatch. See [#4370](https://github.com/redhat-developer/vscode-java/pull/4370). + * dependencies - bump @tootallnate/once and @vscode/test-electron. See [#4355](https://github.com/redhat-developer/vscode-java/pull/4355). + +## 1.53.0 (February 26th, 2026) + * enhancement - Kotlin imports into Java file are unresolved. See [#531](https://github.com/redhat-developer/vscode-java/issues/531). + * enhancement - After opening the Kotlin class of a downloaded Maven dependency source, show `.kt` file instead of `.class`. See [#4297](https://github.com/redhat-developer/vscode-java/issues/4297). + * enhancement - Disable automatic imports on paste. See [#4325](https://github.com/redhat-developer/vscode-java/issues/4325). + * enhancement - Option to turn off automatic creation of class body when creating a new Java file. See [#2652](https://github.com/redhat-developer/vscode-java/issues/2652). + * enhancement - Update Eclipse formatter template to version 23. See [#4344](https://github.com/redhat-developer/vscode-java/pull/4344). + * enhancement - Set `o.e.j.core.compiler.problem.forbiddenReference=ignore` by default. See [JLS#3720](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3720). + * enhancement - Add setting to show generated code in document symbols. See [4084](https://github.com/redhat-developer/vscode-java/issues/4084). + * enhancement - Provide a Windows ARM64 build. See [#4324](https://github.com/redhat-developer/vscode-java/issues/4324). + * enhancement - Log server version+commit on startup. See [JLS#3689](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3689). + * bug fix - Suggestion issue for Variable Arity Parameters. See [#4267](https://github.com/redhat-developer/vscode-java/issues/4267). + * bug fix - Annotations + generics + explicit receiver fail to compile. See [#3744](https://github.com/redhat-developer/vscode-java/issues/3744). + * bug fix - Autocompletion not working in `@interface` class. See [#3533](https://github.com/redhat-developer/vscode-java/issues/3533). + * bug fix - Deprecate `java.saveActions.organizeImports` setting. See [#2207](https://github.com/redhat-developer/vscode-java/issues/2207) and [#659](https://github.com/redhat-developer/vscode-java/issues/659). + * bug fix - Fix code completion in JEP 512: Compact Source Files with static variables. See [JLS#3680](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3680). + * bug fix - JEP 511: module completion now shows documentation. See [JLS#3710](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3710). + * dependencies - Update Fernflower to 253.29346.240, fetched via the target platform. See [JLS#3667](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3667). + * dependencies - Bump tar from 7.5.4 to 7.5.7. See [#4322](https://github.com/redhat-developer/vscode-java/pull/4322). + * dependencies - Bump webpack from 5.94.0 to 5.105.0. See [#4332](https://github.com/redhat-developer/vscode-java/pull/4332). + * dependencies - Bump @isaacs/brace-expansion from 5.0.0 to 5.0.1. See [#4331](https://github.com/redhat-developer/vscode-java/pull/4331). + * dependencies - Bump tar from 7.5.7 to 7.5.8. See [#4343](https://github.com/redhat-developer/vscode-java/pull/4343). + * build - Avoid calling webpack for each platform build. See [#4330](https://github.com/redhat-developer/vscode-java/pull/4330). + * build - New issue templates. See [#4339](https://github.com/redhat-developer/vscode-java/pull/4339). + +## 1.52.0 (January 29th, 2026) + * enhancement - Add library info on hover. See [#3872](https://github.com/redhat-developer/vscode-java/issues/3872). + * enhancement - Support AspectJ in Gradle projects. See [#4304](https://github.com/redhat-developer/vscode-java/pull/4304). + * enhancement - Enable more quick-fixes from upstream JDT. See [JLS#3660](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3660). + * bug fix - Fix wrong type mismatch errors. See [JLS#3691](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3691). + * bug fix - Fix incorrect Markdown hover rendering for inline `{@link}`/`{@linkplain}` member references. See [JLS#3655](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3655). + * bug fix - Watch `java.settings.url` file modifications. See [JLS#3679](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3679). + * bug fix - Don't create unnecessary new lines when pasting text including literal `\n`. See [#4305](https://github.com/redhat-developer/vscode-java/issues/4305), [#4306](https://github.com/redhat-developer/vscode-java/pull/4306). + * bug fix - Automatic source discovery fails for jars not built with Maven. See [#4301](https://github.com/redhat-developer/vscode-java/issues/4301). + * bug fix - Fix Javadoc braces rendering in hover. See [#1291](https://github.com/redhat-developer/vscode-java/issues/1291). + * dependencies - Bump tar from 7.5.2 to 7.5.4. See [#4311](https://github.com/redhat-developer/vscode-java/pull/4311), [#4315](https://github.com/redhat-developer/vscode-java/pull/4315). + * dependencies - Bump lodash from 4.17.21 to 4.17.23. See [#4316](https://github.com/redhat-developer/vscode-java/pull/4316). + * build - Upgrade GitHub Actions to version 5. See [#4296](https://github.com/redhat-developer/vscode-java/pull/4296). + +## 1.51.0 (January 6th, 2026) + * enhancement - Add a quickfix to replace a deprecated field with one referenced in the docs. See [JLS#3626](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3626). + * enhancement - Add a quickfix for "type safety warning" to infer type arguments. See [JLS#626](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/626). + * bug fix - "Generate constructor" feature can now be used when the type has no fields. See [#4154](https://github.com/redhat-developer/vscode-java/issues/4154). + * bug fix - When viewing Javadoc through hover, any Javadoc with `{@literal}` tags now has proper newlines. See [#3758](https://github.com/redhat-developer/vscode-java/issues/3758). + * bug fix - Handle tags placed in `{@literal}` properly in Javadoc hover. See [#1838](https://github.com/redhat-developer/vscode-java/issues/1838). + * bug fix - Fix how tables are displayed in Javadoc hover. See [#2465](https://github.com/redhat-developer/vscode-java/issues/2465). + * bug fix - Fix a bug in the quickfix that replaces a deprecated method with one referenced in the docs. See [JLS#3638](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3638). + * bug fix - Fix Move method refactoring causing syntax errors due to calling private fields. See [#3604](https://github.com/redhat-developer/vscode-java/issues/3604) + * bug fix - Fix Move method refactoring causing syntax errors due to dependency on internal classes. See [#3607](https://github.com/redhat-developer/vscode-java/issues/3607) + * bug fix - Fix formatting breaking fenced blocks in Markdown javadoc [4209](https://github.com/redhat-developer/vscode-java/issues/4209). + * bug fix - Ensure importers with the same order number are not dropped. See [JLS#3658](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3658). + * dependencies - Address vulnerability in version of jsoup being used. See [#3859](https://github.com/redhat-developer/vscode-java/issues/3859). + +## 1.50.0 (November 26th, 2025) + * enhancement - Add preference to disable returning Javadoc on hover. See [#1420](https://github.com/redhat-developer/vscode-java/issues/1420). + * enhancement - Adopt quick fixes for the following problems. See [JLS#3609](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3609). + - `UnusedMethodDeclaredThrownException`, + - `InvalidOperator`, + - `RedundantSpecificationOfTypeArguments` + * enhancement - Refresh codelens when updating preferences. See [JLS#3047](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3047). + * bug fix - Do not define title in package.json schema as it is shown in tooltip for all package.json files. See [#4268](https://github.com/redhat-developer/vscode-java/issues/4268). + * bug fix - Temporary rollback of junit bundles to fix JUnit 6 support. See [#4260](https://github.com/redhat-developer/vscode-java/issues/4260). + * bug fix - Fixed NPE thrown when computing Code Actions on invalid code. See [JLS#3602](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3602). + +## 1.49.0 (November 19th, 2025) + * performance - Avoid unnecessary Maven project rebuild when the window is reloaded. See [#4250](https://github.com/redhat-developer/vscode-java/issues/4250). + * performance - Prevent unnecessary Maven project rebuild when configuring test classpath flag. See [JLS#3590](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3590). + * enhancement - Add JSpecify annotations for null analysis. See [#4249](https://github.com/redhat-developer/vscode-java/pull/4249). + * enhancement - Improve code completion type for annotation attributes (now using `Field` kind). See [#3242](https://github.com/redhat-developer/vscode-java/issues/3242). + * enhancement - Use discovered, compatible JDK, if embedded JDK does not meet requirements. See [#4226](https://github.com/redhat-developer/vscode-java/issues/4226). + * enhancement - Command to add a JVM install. See [#4161](https://github.com/redhat-developer/vscode-java/issues/4161). + * bug fix - 1.48.0 only contains the universal version. See [4256](https://github.com/redhat-developer/vscode-java/issues/4256). + * bug fix - Fix indentation rules when a line is moved. See [#692](https://github.com/redhat-developer/vscode-java/issues/692). + * bug fix - Inner classes are now correctly shown/decompiled via Fernflower. See [JLS#2815](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2815). + * bug fix - Ensure accurate 'build finished' status by waiting for all background processes. See [#4230](https://github.com/redhat-developer/vscode-java/issues/4230). + * bug fix - Fix discrepency in annotation processing, between full and incremental builds. See [#2117](https://github.com/redhat-developer/vscode-java/issues/2117). + * bug fix - Suppress incorrect error logging related to content providers and decompiler checks. See [#3178](https://github.com/redhat-developer/vscode-java/issues/3178). + * bug fix - Ensure we correctly parse the Lombok version. See [#2765](https://github.com/redhat-developer/vscode-java/issues/2765). + * bug fix - Safeguard workspace hash computation in telemetry service. See [#4246](https://github.com/redhat-developer/vscode-java/pull/4246). + * dependencies - Bump glob to 11.1.0. See [#4255](https://github.com/redhat-developer/vscode-java/pull/4255). + * dependencies - Bump js-yaml from 4.1.0 to 4.1.1. See [#4252](https://github.com/redhat-developer/vscode-java/pull/4252). + * dependencies - Bump tar from 7.5.1 to 7.5.2. See [#4224](https://github.com/redhat-developer/vscode-java/pull/4224). + * dependencies - Bump org.apache.commons:commons-lang3 from 3.5 to 3.18.0 in /test/resources/projects/maven/salut-java11. See [#4243](https://github.com/redhat-developer/vscode-java/pull/4243). + * build - Fix `npm run build` on Windows. See [#4244](https://github.com/redhat-developer/vscode-java/issues/4244). + +## 1.47.0 (October 30th, 2025) + * enhancement - Add inlay hints for lambda parameter types and option to suppress for same-name numbered parameters. See [#4203](https://github.com/redhat-developer/vscode-java/pull/4203), [#4208](https://github.com/redhat-developer/vscode-java/pull/4208). + * enhancement - Improve detection and setup of `sourcePath` for Android support. See [JLS#3490](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3490). + * enhancement - Disable unused lambda parameter warning by default. See [#4216](https://github.com/redhat-developer/vscode-java/issues/4216). + * bug fix - Resolve poor formatting issues in Jupyter notebooks. See [#4207](https://github.com/redhat-developer/vscode-java/issues/4207). + * bug fix - Fix failure in "Create method" quick assist with parameterized arguments. See [#4138](https://github.com/redhat-developer/vscode-java/issues/4138). + * bug fix - Prevent incorrect postfix completions on import statements. See [#3364](https://github.com/redhat-developer/vscode-java/issues/3364). + * bug fix - Fix multiple `NullPointerException` reported by telemetry. See [JLS#3570](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3570). + * bug fix - Fix "Resource leak" false positives. See [#1349](https://github.com/redhat-developer/vscode-java/issues/1349). + * bug fix - Update flags for `javac` compiler support. See [#4198](https://github.com/redhat-developer/vscode-java/pull/4198). + * bug fix - Revert change that ignored null unchecked conversion warnings by default. See [JLS#3472](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3472). + * bug fix - Only call `prepareExecutable` for syntax server when needed. See [#4202](https://github.com/redhat-developer/vscode-java/issues/4202). + * bug fix - Allow partial configuration updates for `workspace/didChangeConfiguration`. See [JLS#3108](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3108). + * bug fix - Add CSP for "Change Signature" & "Java Dashboard" webviews. See [#4193](https://github.com/redhat-developer/vscode-java/issues/4193). + * buf fix - Report all errors for pre-releases or when running in Insiders. See [#4210](https://github.com/redhat-developer/vscode-java/pull/4210). + * bug fix - Provide more comprehensive error telemetry, and include workspace identifier. See [JLS#3566](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3566), [#4175](https://github.com/redhat-developer/vscode-java/issues/4175). + * dependency - Bump `vscode-redhat-telemetry` to 0.9.2. See [#4195](https://github.com/redhat-developer/vscode-java/pull/4195). + * dependency - Update target platform to Eclipse 2025-09 (4.37) release. See [JLS#3530](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3530). + * build - Remove `gulp` and other vulnerable dependencies. See [#4199](https://github.com/redhat-developer/vscode-java/pull/4199). + +## 1.46.0 (October 2nd, 2025) + * performance - Cleaning workspace should also delete configuration folder. See [#4157](https://github.com/redhat-developer/vscode-java/issues/4157). + * performance - Improve Null Analysis by reducing & deferring expensive calls. See [JLS#3531](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3531). + * enhancement - Support Java 25. See [#4170](https://github.com/redhat-developer/vscode-java/pull/4170), [#4185](https://github.com/redhat-developer/vscode-java/pull/4185), [#4172](https://github.com/redhat-developer/vscode-java/pull/4172). + * enhancement - Add a "Java Dashboard" view that presents information for troubleshooting. See [#4128](https://github.com/redhat-developer/vscode-java/issues/4128). + * enhancement - Support fuzzy camel case search for workspace symbols. See [JLS#3513](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3513). + * enhancement - Enable formatting Java in Jupyter Notebook. See [#4163](https://github.com/redhat-developer/vscode-java/issues/4163). + * enhancement - Add inlay hints for implicit variable types. See [#4031](https://github.com/redhat-developer/vscode-java/issues/4031). + * bug fix - Fix Android Support with recent AGP versions. See [#3682](https://github.com/redhat-developer/vscode-java/issues/3682). + * bug fix - Ensure Gradle 9.1.0 requires JDK >= 25. See [JLS#3540](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3540). + * bug fix - Eable `workspace/executeCommand` in the Syntax language client. See [#4187](https://github.com/redhat-developer/vscode-java/pull/4187). + * bug fix - Add missing KO NLS keys and refine translations. See [#4183](https://github.com/redhat-developer/vscode-java/pull/4183). + * bug fix - Show decompiled source when opening `.class` file on remote workspace. See [#4114](https://github.com/redhat-developer/vscode-java/issues/4114). + * dependencies - Bump brace-expansion from 1.1.11 to 1.1.12. See [#4150](https://github.com/redhat-developer/vscode-java/pull/4150). + * dependencies - Use the Eclipse 4.37 platform release repository. See [JLS#3526](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3526). + * dependencies - Update M2E 2.9.0 to 2.9.1. See [JLS#3520](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3520). + * build - Do not reference path when invoking `gulp`. See [#4158](https://github.com/redhat-developer/vscode-java/issues/4158). + +## 1.45.0 (September 4th, 2025) + * performance - Delay registration of resource/element listeners. See [JLS#3510](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3510). + * bug fix - Path expansion is not working for the `sources` field in `referencedLibraries`. See [JLS#3495](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3495). + * bug fix - Send LSP server version with `InitializeResult`. See [JLS#3484](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3484). + * bug fix - Update the decompiler header for FernFlower. See [JLS#3512](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3512). + * bug fix - Remove unused options for completion & incomplete classpath severity. See [JLS#3506](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3506). + +## 1.44.0 (July 31st, 2025) + * performance - Improve startup with (optional) Java Application Class-Data Sharing. See [#4067](https://github.com/redhat-developer/vscode-java/pull/4067). + * enhancement - Add code actions for creating method in base type. See [#4064](https://github.com/redhat-developer/vscode-java/issues/4064). + * bug fix - Fix Gradle/Java Compatibility Matrix for recent Java versions. See [JLS#3485](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3485). + * bug fix - Detect JBang installed JDKs. See [#3799](https://github.com/redhat-developer/vscode-java/issues/3799). + * dependencies - Update M2E 2.8.0 to 2.9.0. See [JLS#3477](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3477). + +## 1.43.1 (July 1st, 2025) +* bug fix - Fix compilation issue when annotation exists on a record class. [#4096](https://github.com/redhat-developer/vscode-java/issues/4096) + +## 1.43.0 (June 26th, 2025) + * performance - "Rebuild Projects" command should be done incrementally. See [#4041](https://github.com/redhat-developer/vscode-java/pull/4041). + * enhancement - Adopt quick fixes for various modifier corrections. See [JLS#1053](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/1053). + - `BodyForNativeMethod`, `MethodRequiresBody`, `OuterLocalMustBeEffectivelyFinal`, + - `MissingSynchronizedModifierInInheritedMethod`, `MethodCanBeStatic`, `OverridingDeprecatedMethod` + * enhancement - Add cleanups for various redundant modifiers/expressions/statements. See [#4066](https://github.com/redhat-developer/vscode-java/issues/4066). + * enhancement - Increase default value for maximum heap size (`Xmx`) from `1G` to `2G`. See [#4062](https://github.com/redhat-developer/vscode-java/pull/4062). + * bug fix - Fix issues with Lombok `@Builder` annotation on `record` type declarations. See [#4050](https://github.com/redhat-developer/vscode-java/issues/4050). + * bug fix - Prevent code actions from failing with "Document does not match the AST". See [#4027](https://github.com/redhat-developer/vscode-java/issues/4027). + * bug fix - Handle snippets when opened (empty) Java file triggers activation. See [#3940](https://github.com/redhat-developer/vscode-java/issues/3940). + * bug fix - Remove JAXP entity limits when runtime is Java 24 or higher. See [#4071](https://github.com/redhat-developer/vscode-java/pull/4071). + +## 1.42.0 (May 15th, 2025) + * enhancement - Implement methods in newly created type from an inherited sealed class. See [JLS#1570](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/1570). + * enhancement - Code action for "The left-hand side of an assginment must be a variable". See [JLS#3441](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3441). + * bug fix - Avoid `StackOverflowError` when computing Extended Outline. See [JLS#3435](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3435). + * bug fix - Compilation failure with primitive array comparison. See [#4020](https://github.com/redhat-developer/vscode-java/issues/4020). + * bug fix - Avoid notifying of failures for workspace builds. See [#4032](https://github.com/redhat-developer/vscode-java/pull/4032). + * bug fix - Report language server exiting with unsaved changes as `java.ls.error`. See [#4033](https://github.com/redhat-developer/vscode-java/pull/4033). + * documentation - Javac-based (experimental) compilation should require latest released Java SDK (24). See [#4029](https://github.com/redhat-developer/vscode-java/issues/4029). + * documentation - Fix return type typo in `qualifyMembers` example. See [#4026](https://github.com/redhat-developer/vscode-java/pull/4026). + +## 1.41.1 (April 1st, 2025) + * bug fix - Fix issues with preference manager by reverting "merge" behaviour. See [#3995](https://github.com/redhat-developer/vscode-java/issues/3995). + * bug fix - Add missing "Create record" quick fix. See [#3988](https://github.com/redhat-developer/vscode-java/issues/3988). + +## 1.41.0 (March 27th, 2025) + * enhancement - Provide support for Java 24. See [#3983](https://github.com/redhat-developer/vscode-java/pull/3983). + * enhancement - Add `Make static` refactoring. See [JLS#3400](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3400). + * enhancement - Adopt quick fixes for some more problems. See [JLS#3398](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3398). + - `MethodButWithConstructorName`, `UsingDeprecatedMethod`, + - `VarIsNotAllowedHere`, `SwitchExpressionsReturnWithinSwitchExpression` + * enhancement - Code action to ignore configurable compiler problems. See [#1791](https://github.com/redhat-developer/vscode-java/issues/1791). + * bug fix - Fix indentation for snippet strings within code actions. See [#3970](https://github.com/redhat-developer/vscode-java/pull/3970). + * bug fix - Only rename source file to match the single public type declaration. See [#3963](https://github.com/redhat-developer/vscode-java/issues/3963). + * bug fix - Fix inherited document symbols to work for interfaces as well. See [#3972](https://github.com/redhat-developer/vscode-java/pull/3972). + * bug fix - Detect changes to watched files that are outside of the workspace. [JLS#1765](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/1765), [JLS#3407](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3407). + * bug fix - Guard against `null` workspace edits (eg. for `Organize Imports`). See [#3978](https://github.com/redhat-developer/vscode-java/issues/3978). + * bug fix - Guard against `null` completion item resolved on cancellation. See [#3973](https://github.com/redhat-developer/vscode-java/pull/3973). + * bug fix - Fix commands test by including new commands. See [#3966](https://github.com/redhat-developer/vscode-java/pull/3966). + * build - Fix `check_and_update_jdk` script by catching missing test URL. See [#3982](https://github.com/redhat-developer/vscode-java/pull/3982). + * dependencies - Update serialize-javascript, mocha, sinon, css-loader. See [#3948](https://github.com/redhat-developer/vscode-java/pull/3948), [#3967](https://github.com/redhat-developer/vscode-java/pull/3967). + +## 1.40.0 (February 27th, 2025) + * enhancement - Support for inherited document symbols. See [#2342](https://github.com/redhat-developer/vscode-java/issues/2342). + * enhancement - Introduce approximately 15 new quick fixes. See [JLS#3368](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3368), [JLS#3372](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3372). + * enhancement - Introduce quick assist & cleanup converting a pattern-instanceof-if-chain to a switch statement. See [#3951](https://github.com/redhat-developer/vscode-java/pull/3951). + * bug fix - Unicode characters not rendering correctly in decompiled file. See [#3949](https://github.com/redhat-developer/vscode-java/issues/3949). + * bug fix - Fix a potential deadlock in search-based functionality. See [#3926](https://github.com/redhat-developer/vscode-java/issues/3926). + * bug fix - Adopt the Lombok 1.18.36 release. See [#3939](https://github.com/redhat-developer/vscode-java/pull/3939). + +## 1.39.0 (January 22nd, 2025) + * performance - Enhance initialization of gradle projects. See [JLS#3357](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3357). + * enhancement - Implementation code lens for non interface/abstract base types/methods. See [JLS#3355](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3355). + * bug fix - Handle snippet position groups with undefined offsets (eg. `Add constructor ..`). See [#3905](https://github.com/redhat-developer/vscode-java/issues/3905). + * bug fix - Ensure Gradle project always reacts to build configuration changes. See [#3893](https://github.com/redhat-developer/vscode-java/issues/3893). + * bug fix - Update the `javac` build profile with new `--add-opens`. See [#3897](https://github.com/redhat-developer/vscode-java/issues/3897). + * debt - Bump minimum required Java Execution Environment from 17 to 21. See [#3911](https://github.com/redhat-developer/vscode-java/pull/3911). + +## 1.38.0 (December 19th, 2024) + * enhancement - Add code lens for interface / abstract method implementations. See [#3813](https://github.com/redhat-developer/vscode-java/issues/3813). + * `java.implementationCodeLens.enabled` replaced by `java.implementationCodeLens` + * Values for new setting are `"none"`, `"types"`, `"methods"`, `"all"` + * enhancement - Add quick fix for sealed class within empty switch expression. See [JLS#3345](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3345). + * enhancement - Support code assist on unresolved types. See [#1123](https://github.com/redhat-developer/vscode-java/issues/1123). + * bug fix - Improve rendering of Markdown Comments (JEP 467). See [JLS#3332](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3332). + * build - Check for updated snapshot repositories when running build. See [#3889](https://github.com/redhat-developer/vscode-java/pull/3889). + * dependencies - Bump cross-spawn from 7.0.3 to 7.0.6. See [#3862](https://github.com/redhat-developer/vscode-java/pull/3862). + * dependencies - Update vscode-redhat-telemetry to 0.9.1. See [#3886](https://github.com/redhat-developer/vscode-java/pull/3886). + +## 1.37.0 (November 28th, 2024) + * performance - Improve performance of code action requests. See [#3845](https://github.com/redhat-developer/vscode-java/pull/3845). + * performance - Improve performance of all language server requests that resolve a document URI. See [JLS#3313](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3313). + * enhancement - Code action for unused pattern variable, lambda parameter, etc. and the corresponding clean up. See [#3856](https://github.com/redhat-developer/vscode-java/pull/3856), [#3864](https://github.com/redhat-developer/vscode-java/pull/3864). + * enhancement - Add setting to control inclusion of declarations in reference search. See [#3850](https://github.com/redhat-developer/vscode-java/issues/3850). + * bug fix - Mapstruct implementation class not generated. See [#3836](https://github.com/redhat-developer/vscode-java/issues/3836). + * bug fix - Open more requested system packages for tests with `javac` support. See [#3847](https://github.com/redhat-developer/vscode-java/pull/3847). + * bug fix - Fix some typos in documentation. See [#3863](https://github.com/redhat-developer/vscode-java/pull/3863) + * build - Add Maven (`-U`) flag for updating artifacts from snapshot repositories. See [#3848](https://github.com/redhat-developer/vscode-java/pull/3848). + +## 1.36.0 (October 31st, 2024) + * enhancement - Experimental support for using `javac` as the compiler. See [#3558](https://github.com/redhat-developer/vscode-java/pull/3558), [JLS#3167](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3167). + * `java.jdt.ls.javac.enabled`: Enables Javac-based compilation. + * Requires running with **Java 23**. Make sure to use `java.jdt.ls.java.home` for this. + * Defaults to `off` + * `java.completion.engine`: Select code completion engine. (`ecj` or `dom`) + * Requires `java.jdt.ls.javac.enabled` to be `on` + * Defaults to `ecj` + * enhancement - Automatically add `///` on new line when editing Markdown comments (JEP 467). See [#3801](https://github.com/redhat-developer/vscode-java/issues/3801). + * bug fix - Re-enable dynamic code actions by fixing the URI comparison. See [#3792](https://github.com/redhat-developer/vscode-java/pull/3792). + * bug fix - Intermittent failures to suggest Java core packages for completion & code actions. See [#3797](https://github.com/redhat-developer/vscode-java/issues/3797). + * bug fix - `java.diagnostic.filter` is broken on Windows. See [JLS#3290](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3290). + * bug fix - Type declaration snippets should respect `java.templates.typeComment`. See [JLS#3295](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3295). + * bug fix - Linux release package files have excessive permissions. See [JLS#3293](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3293). + * bug fix - Remove Dependency Analytics extension from being recommended. See [#3804](https://github.com/redhat-developer/vscode-java/pull/3804). + * bug fix - Update embedded lombok library name to reflect actual version. See [#3833](https://github.com/redhat-developer/vscode-java/pull/3833). + * dependencies - Use Node 20 in release-job only. See [#3809](https://github.com/redhat-developer/vscode-java/pull/3809). + +## 1.35.1 (September 30th, 2024) + * bug fix - Dynamic code actions fail on Windows. See [#3780](https://github.com/redhat-developer/vscode-java/issues/3780). + +## 1.35.0 (September 26th, 2024) + * performance - Consider token to limit the chains that are searched. See [JLS#2835](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2835). + * enhancement - Provide support for Java 23. See [#3774](https://github.com/redhat-developer/vscode-java/pull/3774). + * enhancement - Show decompiled content directly on opened `.class` file. See [#3759](https://github.com/redhat-developer/vscode-java/issues/3759). + * enhancement - Support dynamic code actions through LSP snippet syntax. See [#3686](https://github.com/redhat-developer/vscode-java/issues/3686). + * enhancement - Introduce new type mismatch quickfix for constructor invocations. See [#3040](https://github.com/redhat-developer/vscode-java/issues/3040). + * enhancement - Control scope for search operations (eg. references, call hierarchy, workspace symbols). See [#2649](https://github.com/redhat-developer/vscode-java/issues/2649). + * enhancement - Add "Organize Imports" as a clean up. See [#3764](https://github.com/redhat-developer/vscode-java/pull/3764). + * bug fix - Import Gradle project via. Buildship if Gradle Build Server is not available. See [JLS#3245](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3245). + * bug fix - Copy/paste will not escape content within String literal when code has error. See [#3761](https://github.com/redhat-developer/vscode-java/issues/3761). + * bug fix - Respect `unwantedRecommendations`. See [#3767](https://github.com/redhat-developer/vscode-java/pull/3767). + * dependencies - Bump webpack from 5.76.0 to 5.94.0. See [#3756](https://github.com/redhat-developer/vscode-java/pull/3756). + * dependencies - Update vscode-redhat-telemetry to 0.9.0. See [#3778](https://github.com/redhat-developer/vscode-java/pull/3778). + +## 1.34.0 (August 29th, 2024) + * enhancement - Support custom source file extensions through `files.associations`. See [#3731](https://github.com/redhat-developer/vscode-java/pull/3731). + * enhancement - Add telemetry for detecting language server running out of memory. See [#3743](https://github.com/redhat-developer/vscode-java/pull/3743). + * bug fix - Fix `ClassCastException` for the file paste event. See [JLS#3239](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3239). + * bug fix - Invalid code actions suggested on deletion of a file. See [#3663](https://github.com/redhat-developer/vscode-java/issues/3663). + * bug fix - Better handling when file path contains non-ASCII characters. See [#3735](https://github.com/redhat-developer/vscode-java/issues/3735). + * bug fix - Add Gradle 8.8 to compatibility check. See [JLS#3212](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3212). + * documentation - Fix stale reference in "Quick Start". See [#3741](https://github.com/redhat-developer/vscode-java/pull/3741). + +## 1.33.0 (August 1st, 2024) + * performance - Clean up invalid projects during initialization to prevent build cycles. See [#3639](https://github.com/redhat-developer/vscode-java/issues/3639). + * enhancement - Expose source actions via. the code action (light bulb) menu. See [#3714](https://github.com/redhat-developer/vscode-java/pull/3714). + * enhancement - Use `java.diagnostic.filter` to exclude files from the "Problems" tab. See [#2150](https://github.com/redhat-developer/vscode-java/issues/2150). + * enhancement - Clear out-of-date files under extension's global storage. See [#2597](https://github.com/redhat-developer/vscode-java/issues/2597). + * enhancement - Add support for callees based on implementors for call hierarchy. See [JLS#2780](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2780). + * bug fix - Links to classes do not appear in completion documentation. See [#3697](https://github.com/redhat-developer/vscode-java/issues/3697). + * bug fix - Add tag property to better track kinds of stacktrace errors of interest. See [#3720](https://github.com/redhat-developer/vscode-java/pull/3720). + * dependencies - Target platform update resulting in **loss of support for Java versions older than 1.8**. See [JLS#3227](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3227). + +## 1.32.0 (June 27th, 2024) + * performance - Ensure every null analysis annotation has a value defined when enabled. See [#3387](https://github.com/redhat-developer/vscode-java/issues/3387). + * enhancement - Add `final` to "Extract to local variable" quick assist if requested. See [#3308](https://github.com/redhat-developer/vscode-java/issues/3308). + * bug fix - Fix issues with the Lombok annotation handler. See [#3561](https://github.com/redhat-developer/vscode-java/issues/3561). + * bug fix - Revalidate project files after classpath changes when autobuild is off. See [JLS#3155](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3155). + * bug fix - Code completion fails with classes that are permitted by a sealed class. See [#3636](https://github.com/redhat-developer/vscode-java/issues/3636). + * bug fix - Perform verification on pipe name when transport kind is `default`. See [#3680](https://github.com/redhat-developer/vscode-java/pull/3680). + * bug fix - Some code actions may fail to resolve when machine's processor count too low. See [JLS#3180](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3180). + * bug fix - Support the import of multi-folder Gradle projects with same name. See [JLS#1743](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/1743). + * bug fix - Autobuild setting should be respected on initialization. See [JLS#3176](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3176). + * bug fix - Improve chain completion by waiting for either "main" or "context" chains. See [JLS#2730](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2730). + * bug fix - Report only one instance of a logged error through telemetry. See [JLS#3190](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3190). + * build - Fix NPE when using 'Launch Extension - JDTLS Client' to local debug extension. See [#3677](https://github.com/redhat-developer/vscode-java/pull/3677). + +## 1.31.0 (May 30th, 2024) + * performance - Create the default project only when it is necessary. See [#3452](https://github.com/redhat-developer/vscode-java/issues/3452). + * performance - Improve order of operations when importing multi-module Maven projects. See [#3637](https://github.com/redhat-developer/vscode-java/issues/3637). + * enhancement - Support delegate API to retrieve/update active profiles of Maven projects. See [JLS#3158](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3158). + * enhancement - Support delegate API for updating Java project options. See [JLS#3162](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3162). + * bug fix - Fix indentation for new line preceded by comma. See [#3396](https://github.com/redhat-developer/vscode-java/issues/3396). + * bug fix - Support document paste across older versions of VS Code. See [#3631](https://github.com/redhat-developer/vscode-java/issues/3631). + * bug fix - Fall back to `stdio` transport if `pipe` is likely to fail. See [#3649](https://github.com/redhat-developer/vscode-java/issues/3649). + * bug fix - Switch expression on a boolean value does not report error. See [JLS#3141](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3141). + * bug fix - Only clean default project when building workspace if it exists. See [JLS#3153](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3153). + * bug fix - Avoid sending an "empty" (lacking project data) startup event. See [#3655](https://github.com/redhat-developer/vscode-java/pull/3655). + * dependencies - Update vscode-redhat-telemetry to 0.8.0. See [#3659](https://github.com/redhat-developer/vscode-java/pull/3659). + +## 1.30.0 (April 25th, 2024) + * enhancement - Add `final` to new declarations generated from code actions. See [#3586](https://github.com/redhat-developer/vscode-java/pull/3586). + * bug fix - Change default client/server transport from `stdio` to `pipe`. See [#3587](https://github.com/redhat-developer/vscode-java/pull/3587). + * bug fix - Qualifier of workspace symbol search should be wildcard search. See [JLS#3134](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3134). + * bug fix - Fix the document paste handling provider for VS Code 1.88.0. See [#3568](https://github.com/redhat-developer/vscode-java/issues/3568). + * bug fix - Clear active build tool selection after cleaning the language server workspace of mixed Maven/Gradle project. See [#3567](https://github.com/redhat-developer/vscode-java/issues/3567). + * bug fix - Static imports with wildcard should resolve all elements. See [#3564](https://github.com/redhat-developer/vscode-java/issues/3564). + * bug fix - Language Server fails to start with multiple `--add-exports` in `java.jdt.ls.vmargs`. See [#3577](https://github.com/redhat-developer/vscode-java/issues/3577). + * bug fix - Make `java.import.gradle.user.home` scope `machine-overridable`. See [#3569](https://github.com/redhat-developer/vscode-java/issues/3569). + * bug fix - Disable automatic handling of `workspace/willRenameFiles`. See [#3565](https://github.com/redhat-developer/vscode-java/pull/3565). + * build - Fix tests in release workflow. See [#3562](https://github.com/redhat-developer/vscode-java/pull/3562). + +## 1.29.0 (April 3rd, 2024) + * enhancement - Provide support for Java 22. See [#3538](https://github.com/redhat-developer/vscode-java/issues/3538). + * enhancement - Simplify the server status item click action & add contribution point. See [#3537](https://github.com/redhat-developer/vscode-java/pull/3537), [#3548](https://github.com/redhat-developer/vscode-java/pull/3548), [#3546](https://github.com/redhat-developer/vscode-java/pull/3546). + * enhancement - Add setting to group completion items representing overloaded methods together. See [#3492](https://github.com/redhat-developer/vscode-java/pull/3492). + * enhancement - Renaming primary type declaration should update source file name on save. See [#3408](https://github.com/redhat-developer/vscode-java/issues/3408). + * enhancement - Support updating whole classpath of the project in delegate commands. See [JLS#3098](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3098). + * enhancement - Open output channel as well when opening logs. See [#3531](https://github.com/redhat-developer/vscode-java/pull/3531). + * enhancement - Read the server logs in order to discover early startup log messages. See [JLS#3106](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3106). + * enhancement - Report errors of type `dtree.ObjectNotFoundException` as `java.ls.error`. See [#3509](https://github.com/redhat-developer/vscode-java/pull/3509). + * bug fix - Signature help should display all overloaded methods. See [JLS#3052](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3052). + * bug fix - Fix issues with Unnamed classes (Java 21) (reference computation, code actions, compilation). See [JLS#3069](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3069), [JLS#3089](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3089), [JLS#3090](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3090). + * bug fix - Record Patterns may cause `VerifyError`. See [#3479](https://github.com/redhat-developer/vscode-java/issues/3479). + * bug fix - Support list of patterns in case statements (Java 21). See [JLS#3043](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3043). + * bug fix - Allow methods, inherited fields, inherited methods for `Generate toString()` code action. See [#2639](https://github.com/redhat-developer/vscode-java/issues/2639). + * bug fix - Update Buildship to 3.1.10, which fixes "Marker property value is too long". See [JLS#2424](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2424). + * bug fix - Set the `nullUncheckedConversion` setting to be ignored by default. See [#3501](https://github.com/redhat-developer/vscode-java/issues/3501). + * bug fix - Fix NPE when fetching the classpath of the project. See [JLS#3115](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3115). + * dependencies - Bump follow-redirects from 1.15.4 to 1.15.6. See [#3534](https://github.com/redhat-developer/vscode-java/pull/3534). + * build - Adopt the Lombok 1.18.32 release. See [#3543](https://github.com/redhat-developer/vscode-java/pull/3543). + * build - Update various GitHub reusable workflows to v4. See [#3519](https://github.com/redhat-developer/vscode-java/pull/3519). + * build - Update release version regular expression for `bump-jdk` workflow. See [#3552](https://github.com/redhat-developer/vscode-java/pull/3552). + +## 1.28.1 (February 15th, 2024) + * enhancement - Unnamed classes & instance `main` methods (Java 21) preview support. See [JLS#3042](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3042). + * enhancement - Add support for activating cleanup actions through keyboard shortcut. See [#3424](https://github.com/redhat-developer/vscode-java/issues/3424). + * enhancement - Jump to specific position of `.class` when clicking on Javadoc link. See [#3490](https://github.com/redhat-developer/vscode-java/pull/3490). + * bug fix - Fix startup failure on macOS (x64) 10.15 or older. See [#3484](https://github.com/redhat-developer/vscode-java/issues/3484). + * bug fix - Support Gradle 8.5 with Java 21. See [#3470](https://github.com/redhat-developer/vscode-java/issues/3470). + +## 1.27.0 (February 1st, 2024) + * enhancement - Make the server status bar item more user friendly. See [#3473](https://github.com/redhat-developer/vscode-java/issues/3473). + * enhancement - Support syntax highlight for embedded HTML. See [#3465](https://github.com/redhat-developer/vscode-java/pull/3465). + * enhancement - Add Unnamed patterns and variables (Java 21) preview support. See [JLS#2963](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2963). + * enhancement - Add quick fixes for for suppressing warnings using `@SuppressWarnings`. See [JLS#2698](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2698). + * enhancement - Add quick fixes for uninitialized `final` fields. See [JLS#1328](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/1328). + * enhancement - Add support for externally provided `lifecycle-mapping-metadata.xml` file. See [#3393](https://github.com/redhat-developer/vscode-java/issues/3393). + * bug fix - Allow generic snippets to be returned when completion token is `null`. See [#3466](https://github.com/redhat-developer/vscode-java/issues/3466). + * bug fix - Allow to import the newly created maven submodule within a multi-module project. See [#3464](https://github.com/redhat-developer/vscode-java/issues/3464). + * bug fix - Use `source.gradle-kotlin-dsl` instead of `source.kotlin` to avoid clashes with other Kotlin grammars. See [#3463](https://github.com/redhat-developer/vscode-java/pull/3463). + * bug fix - Log the error details when initialization fails. See [#3472](https://github.com/redhat-developer/vscode-java/pull/3472). + * bug fix - Avoid string concatenation with `Runtime.getRuntime().exec(..)`. See [JLS#3022](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3022). + * dependencies - Adopt the Lombok 1.18.31 edge release. See [#3461](https://github.com/redhat-developer/vscode-java/pull/3461). + * build - Automatically suggest updates based on JDT-LS Java language support. See [#3402](https://github.com/redhat-developer/vscode-java/pull/3402). + +## 1.26.0 (January 11th, 2024) + * performance - Reduce delegate command calls when classpath changes. See [#3439](https://github.com/redhat-developer/vscode-java/pull/3439). + * performance - Ensure initial import of projects respect resource filter settings. See [#2972](https://github.com/redhat-developer/vscode-java/issues/2972). + * performance - Improve the performance of "Organize Imports" when "favorite static imports" are involved. See [#3383](https://github.com/redhat-developer/vscode-java/issues/3383). + * enhancement - Add String Templates (Java 21) preview support. See [JLS#2994](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2994). + * enhancement - Support syntax highlight for embedded SQL, JSON, XML & YAML languages. See [#831](https://github.com/redhat-developer/vscode-java/issues/831), [#3455](https://github.com/redhat-developer/vscode-java/pull/3455). + * enhancement - Generate correct sources when pasting Java code into the file explorer view. See [#3323](https://github.com/redhat-developer/vscode-java/issues/3323). + * enhancement - Quick assists converting string concatenations to `StringBuilder`, `StringBuffer`, `String.format(..)`, `MessageFormat`. See [JLS#3007](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3007). + * enhancement - Quick assists inverting `equals` comparison & handling of lambda expressions. See [JLS#2996](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2996). + * enhancement - Support "non-null" assertions by default using null analysis. See [#3431](https://github.com/redhat-developer/vscode-java/issues/3431). + * enhancement - Make the language server status a normal status bar item for better visibility. See [#3416](https://github.com/redhat-developer/vscode-java/issues/3416). + * bug fix - Fix multiline semantic highlighting for `implements`, `extends`, and `permits` keywords. See [JLS#2995](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2995). + * bug fix - Use wrapper distribution when `gradle-wrapper.properties` exists. See [JLS#3012](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3012). + * bug fix - Fix false positive parameter mismatch error. See [JLS#2992](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2992). + * bug fix - Document pasting should defer to other contributors when there are no changes. See [#3444](https://github.com/redhat-developer/vscode-java/issues/3444). + * bug fix - Use Lombok 1.18.31 snapshot to avoid errors for annotations with parameters. See [#3454](https://github.com/redhat-developer/vscode-java/issues/3454). + * bug fix - Remember the choice when asking project selection on import. See [#3415](https://github.com/redhat-developer/vscode-java/issues/3415). + * bug fix - Guard against `null` completion context and insertion text. See [#3422](https://github.com/redhat-developer/vscode-java/issues/3422). + * bug fix - The assignment to variable `workingCopy` has no effect. See [JLS#3002](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3002). + * bug fix - Change scope of `java.import.gradle.home` to `machine-overridable`. See [#3430](https://github.com/redhat-developer/vscode-java/pull/3430). + * bug fix - Filter excessive logging of artifact download from m2e in "debug mode". See [JLS#3011](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/3011). + * dependencies - Bump follow-redirects from 1.15.2 to 1.15.4. See [#3457](https://github.com/redhat-developer/vscode-java/pull/3457). + * debt - Remove the legacy status bar item implementation. See [#3081](https://github.com/redhat-developer/vscode-java/issues/3081). + +## 1.25.1 (December 7th, 2023) + * performance - Avoid unnecessary (Maven) project updates. See [#3411](https://github.com/redhat-developer/vscode-java/issues/3411). + * bug fix - Out of sync editor content may report false compilation errors. See [JLS#2955](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2955). + * bug fix - Improved support for textmate definition for Kotlin DSL. See [#3403](https://github.com/redhat-developer/vscode-java/issues/3403). + * bug fix - No completion suggestions for package references when `matchCase` is set to `firstLetter`. See [JLS#2925](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2925). + * bug fix - Closing Text Blocks immediately after an escaped character produces incorrect syntax highlight. See [#3384](https://github.com/redhat-developer/vscode-java/issues/3384). + * bug fix - Fix the typo: blob -> glob. See [#3413](https://github.com/redhat-developer/vscode-java/pull/3413). + +## 1.25.0 (November 30th, 2023) + * enhancement - Provide support for Java 21. See [#3292](https://github.com/redhat-developer/vscode-java/issues/3292). + * enhancement - Import projects by configurations. See [#3356](https://github.com/redhat-developer/vscode-java/pull/3356). + * enhancement - Support add/remove of imported projects. See [#3398](https://github.com/redhat-developer/vscode-java/pull/3398). + * enhancement - Host textmate definition for kotlin language. See [#3334](https://github.com/redhat-developer/vscode-java/issues/3334). + * enhancement - Categorize the extension settings. See [#2548](https://github.com/redhat-developer/vscode-java/issues/2548). + * enhancement - Add `maven.multiModuleProjectDirectory` property. See [#3380](https://github.com/redhat-developer/vscode-java/issues/3380). + * enhancement - Add capability to list all VM installs and update project JDK. See [JLS#2977](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2977). + * bug fix - Update to `vscode-languageclient` 8.2.0-next.3 (using Node 18) to fix IPC path length limitations. See [#3371](https://github.com/redhat-developer/vscode-java/issues/3371). + * bug fix - Avoid refreshing language server when contributing extension's dependency closure includes it. See [#3349](https://github.com/redhat-developer/vscode-java/issues/3349). + * bug fix - Wrongly encoded semantic tokens around `class` keyword. See [JLS#2920](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2920). + * bug fix - Cleanups & Organize Imports should only react to internal project preferences with `canUseInternalSettings`. See [#3399](https://github.com/redhat-developer/vscode-java/issues/3399), [#3370](https://github.com/redhat-developer/vscode-java/issues/3370), [JLS#2975](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2975). + * bug fix - Fix missing prompt to select build tool for Gradle/Maven mixed project. See [#3400](https://github.com/redhat-developer/vscode-java/issues/3400). + * bug fix - Respect the VS Code setting to disable extension recommendations. See [#3381](https://github.com/redhat-developer/vscode-java/issues/3381). + * bug fix - `IllegalArgumentException` on `completionItem/resolve` of package declaration. See [JLS#2924](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2924). + * bug fix - Add trace to understand the probability of document out-of-sync. See [JLS#2954](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2954). + * dependencies - Bump axios from 1.5.0 to 1.6.1. See [#3388](https://github.com/redhat-developer/vscode-java/pull/3388). + * dependencies - Update buildship to 3.1.8. See [JLS#2974](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2974). + +## 1.24.0 (October 26th, 2023) + * performance - Exclude certain folders (eg. `node_modules/`) from "trigger" file search on activation. [#3348](https://github.com/redhat-developer/vscode-java/pull/3348). + * enhancement - Move snippet suggestions above matching keywords in completion list. See [#2584](https://github.com/redhat-developer/vscode-java/issues/2584). + * enhancement - Add new alias `public static void main(String[] args)` for public main method. See [#2105](https://github.com/redhat-developer/vscode-java/issues/2105). + * enhancement - Add aliases for `sysout`/`syserr` snippets that will see more usage. See [#3041](https://github.com/redhat-developer/vscode-java/issues/3041). + * enhancement - Add "Surround with try/catch" code action. See [JLS#2727](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2727). + * enhancement - Automatically add the existing static imports in code as favorite static members. See [JLS#2903](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2903). + * enhancement - Provide quick fix to "Configure static import...". See [#3339](https://github.com/redhat-developer/vscode-java/pull/3339). + * enhancement - Support named pipes for client/server communication. See [#3282](https://github.com/redhat-developer/vscode-java/issues/3282). + * enhancement - Track the LSP request data from syntax server. See [#3278](https://github.com/redhat-developer/vscode-java/pull/3278). + * bug fix - Re-implement smart semicolon detection through text document change API. See [#3290](https://github.com/redhat-developer/vscode-java/issues/3290). + * bug fix - Completion returns no results for method declarations when `matchCase` set to `FIRSTLETTER`. See [#3214](https://github.com/redhat-developer/vscode-java/issues/3214), [#3186](https://github.com/redhat-developer/vscode-java/issues/3186). + * bug fix - Allow filtering methods by parameter names, and order by number of parameters. See [JLS#2907](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2907), [#3206](https://github.com/redhat-developer/vscode-java/issues/3206). + * bug fix - Reconcile AST node to provide accurate type definition snippets. See [#2250](https://github.com/redhat-developer/vscode-java/issues/2250). + * bug fix - `BasicFileDetector` should handle inaccessible directories gracefully during project import. See [#1156](https://github.com/redhat-developer/vscode-java/issues/1156), [#3137](https://github.com/redhat-developer/vscode-java/issues/3137). + * bug fix - Ensure line delimiter exists after the file header template. See [JLS#2906](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2906). + * bug fix - `o.e.core.internal.resources.ResourceException`: Invalid project description. See [JLS#2845](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2845). + * bug fix - Error when parsing resource filter. See [#3345](https://github.com/redhat-developer/vscode-java/pull/3345). + * bug fix - NPE in `SemanticTokensHandler`. See [JLS#2876](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2876). + * bug fix - NPE in cleanup action handler. See [JLS#2879](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2879). + * bug fix - `UnsupportedOperationException` at `org.eclipse.lsp4j.services.LanguageServer.setTrace()`. See [JLS#2891](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2891). + * dependencies - Bump postcss from 8.4.21 to 8.4.31. See [#3335](https://github.com/redhat-developer/vscode-java/pull/3335). + +## 1.23.0 (September 28th, 2023) + * enhancement - Improve JDK detection on the local machine, and ensure they are registered. See [#3301](https://github.com/redhat-developer/vscode-java/pull/3301). + * enhancement - Update current method snippet and add `static_method` snippet for interface. See [#1697](https://github.com/redhat-developer/vscode-java/issues/1697). + * enhancement - Improve the constructor snippet for additional classes in a file. See [#725](https://github.com/redhat-developer/vscode-java/issues/725). + * enhancement - Store the completion kinds requested by completion operation. See [JLS#2857](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2857). + * enhancement - Update to Lombok 1.18.30. See [#3321](https://github.com/redhat-developer/vscode-java/pull/3321). + * enhancement - Add API `onWillRequestStart` to track request send event. See [#3316](https://github.com/redhat-developer/vscode-java/pull/3316). + * enhancement - Report whether the project has Kotlin Gradle files. See [JLS#2859](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2859). + * enhancement - Track the completion kinds of completion request. See [#3307](https://github.com/redhat-developer/vscode-java/pull/3307). + * bug fix - Fix `EmptyStackException` in `textDocument/foldingRange`. See [JLS#2865](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2865). + * bug fix - Fix renaming of attribute with `@Singular` annotation. See [#3203](https://github.com/redhat-developer/vscode-java/issues/3203). + * bug fix - `Open Java Language Server Log File` should open the correct server (standard/syntax) log. See [#3309](https://github.com/redhat-developer/vscode-java/issues/3309). + * bug fix - Fix `URI` with query parameter. See [#3305](https://github.com/redhat-developer/vscode-java/issues/3305). + * bug fix - Fix an error thrown during "Initialize workspace". See [JLS#2842](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2842). + +## 1.22.1 (September 14th, 2023) + * bug fix - Removed some improvements to JDK detection as they were causing issues on MacOS. See [#3287](https://github.com/redhat-developer/vscode-java/issues/3287). If you still see JDK class errors after upgrading to 1.22.1, please open **Command Palette** and run "**Java: Clean Java Language Server Workspace**". + * bug fix - Log errors from project importer. See [JLS#2843](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2843). + * bug fix - Disable `;` key binding when smart semicolon detection is disabled. See [#3290](https://github.com/redhat-developer/vscode-java/issues/3290). + +## 1.22.0 (September 12th, 2023) + * performance - Stale code actions should be cancellable and paste actions should have higher priority. See [#3199](https://github.com/redhat-developer/vscode-java/issues/3199). + * enhancement - Add support for smart semicolon insertion. See [#703](https://github.com/redhat-developer/vscode-java/issues/703). + * enhancement - Introduce new snippet templates with appropriate context. See [#2867](https://github.com/redhat-developer/vscode-java/issues/2867). + * enhancement - Improve JDK detection on the local machine, and ensure they are registered. See [#3251](https://github.com/redhat-developer/vscode-java/pull/3251). + * enhancement - Add folding range for multiple single-line comments. See [#860](https://github.com/redhat-developer/vscode-java/issues/860). + * enhancement - Use a more appropriate completion item image for annotation attributes and records. See [JLS#2796](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2796). + * enhancement - Select suitable JDK to launch Gradle. See [JLS#2812](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2812). + * enhancement - end-to-end performance tracking for code completion requests. See [#3165](https://github.com/redhat-developer/vscode-java/pull/3165). + * enhancement - Track the case of language server `OutOfMemory`. See [#3273](https://github.com/redhat-developer/vscode-java/pull/3273). + * enhancement - Record the trigger context of completion request. See [#3272](https://github.com/redhat-developer/vscode-java/pull/3272). + * bug fix - Call hierarchy should always report the end of its progress. See [JLS#2827](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2827). + * bug fix - Fix multiline semantic highlighting for `class`, `interface` & `record` declarations. See [#1444](https://github.com/redhat-developer/vscode-java/issues/1444), [JLS#2807](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2807). + * bug fix - The type declaration snippets should generate file headers. See [JLS#2813](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2813). + * bug fix - Fix folding ranges for nested switch statements. See [#2751](https://github.com/redhat-developer/vscode-java/issues/2751). + * bug fix - Fix "java.lang.VerifyError: Operand stack overflow". See [#3232](https://github.com/redhat-developer/vscode-java/issues/3232). + * bug fix - Commands needing language server should not be activated before the service is ready . See [#3281](https://github.com/redhat-developer/vscode-java/pull/3281). + * bug fix - Record methods are not recognized under certain conditions. See [#3233](https://github.com/redhat-developer/vscode-java/issues/3233). + * bug fix - Fix compiler arguments parsing failure in Gradle build support. See [JLS#2781](https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2781). + * bug fix - Filter out excessive logging of classfile parsing from m2e in "debug mode". See [JLS#2785](https://github.com/eclipse-jdtls/eclipse.jdt.ls/pull/2785). + * bug fix - Don't escape unicode characters when pasting string literals. See [#3181](https://github.com/redhat-developer/vscode-java/issues/3181). + * bug fix - Enable by default syntactic null analysis for fields. See [#3255](https://github.com/redhat-developer/vscode-java/issues/3255). + * bug fix - Rename `SERVER_PORT` environment variable to `JDTLS_SERVER_PORT`. See [#3256](https://github.com/redhat-developer/vscode-java/issues/3256), [#2507](https://github.com/redhat-developer/vscode-java/issues/2507). + * dependencies - Update semver to latest version where possible. See [#3264](https://github.com/redhat-developer/vscode-java/pull/3264). + * dependencies - Update vscode-redhat-telemetry to 0.7.0. See [#3262](https://github.com/redhat-developer/vscode-java/pull/3262). + +## 1.21.0 (July 27th, 2023) + * performance - Check completion proposal is compatible or not. See [JLS#2733](https://github.com/eclipse/eclipse.jdt.ls/pull/2733). + * enhancement - Add code actions for Join/Split variable. See [JLS#2732](https://github.com/eclipse/eclipse.jdt.ls/pull/2732). + * enhancement - Support outline view for decompiled source. See [JLS#2742](https://github.com/eclipse/eclipse.jdt.ls/pull/2742). + * enhancement - Reload the cached classfile sources when their source attachment is updated. See [#3207](https://github.com/redhat-developer/vscode-java/pull/3207). + * enhancement - Log error when Gradle and JDK versions are mismatched. See [JLS#2749](https://github.com/eclipse/eclipse.jdt.ls/pull/2749). + * bug fix - Fix parameter and exception changes in method signature refactoring. See [#3098](https://github.com/redhat-developer/vscode-java/issues/3098). + * bug fix - Fix missing completion items for fully qualified name completion. See [#3173](https://github.com/redhat-developer/vscode-java/issues/3173). + * bug fix - Support Java text block highlight. See [#2896](https://github.com/redhat-developer/vscode-java/issues/2896). + * bug fix - Fix incorrect syntax highlight for comment following a `throws` clause. See [#3039](https://github.com/redhat-developer/vscode-java/issues/3039). + * bug fix - Fix incorrect syntax highlight for `new` keyword on inner class creation. See [#1195](https://github.com/redhat-developer/vscode-java/issues/1195). + * bug fix - Fix incorrect semantic highlighting due to out-of-date AST in use. See [JLS#2709](https://github.com/eclipse/eclipse.jdt.ls/pull/2709). + * bug fix - Prevent caching outdated AST in `CoreASTProvider`. See [JLS#2714](https://github.com/eclipse/eclipse.jdt.ls/pull/2714). + * bug fix - Call Hierarchy resolves wrong element under certain conditions. See [JLS#2771](https://github.com/eclipse/eclipse.jdt.ls/issues/2771). + * bug fix - `NullPointerException` during code completion of a `var` reference. See [#2758](https://github.com/redhat-developer/vscode-java/issues/2758). + * bug fix - Do not delete the Java project nature removing a nested `.classpath` resource file. See [JLS#2750](https://github.com/eclipse/eclipse.jdt.ls/pull/2750). + * bug fix - Unable to acquire the state change lock for the module 'buildship'. See [#3184](https://github.com/redhat-developer/vscode-java/issues/3184). + * bug fix - Rename 'Attach Source' menu to 'Attach Source…'. See [#3202](https://github.com/redhat-developer/vscode-java/pull/3202). + * dependencies - Bump word-wrap from 1.2.3 to 1.2.4. See [#3211](https://github.com/redhat-developer/vscode-java/pull/3211). + +## 1.20.0 (June 29th, 2023) + * performance - Set the default value of `java.completion.matchCase` to `firstLetter`. See [#3142](https://github.com/redhat-developer/vscode-java/pull/3142). + * enhancement - Support for "Go to Declaration". See [JLS#2684](https://github.com/eclipse/eclipse.jdt.ls/issues/2684). + * enhancement - Improve method argument guessing functionality. See [#2903](https://github.com/redhat-developer/vscode-java/issues/2903). + * enhancement - Add code action to clean up & simplify lambda expressions. See [#3158](https://github.com/redhat-developer/vscode-java/pull/3158). + * enhancement - Use FernFlower as the default decompiler. See [JLS#2704](https://github.com/eclipse/eclipse.jdt.ls/pull/2704). + * enhancement - Attempt automatic JVM detection on startup. See [JLS#2731](https://github.com/eclipse/eclipse.jdt.ls/pull/2731). + * enhancement - Support for chain completions. See [#3008](https://github.com/redhat-developer/vscode-java/pull/3008). + * enhancement - Make reasonable guess for method name when applying "Extract Method" refactoring. See [#2011](https://github.com/redhat-developer/vscode-java/issues/2011). + * enhancement - Add postfix completion for `sysouf`, `sysoutv`, `format`, `par`, `not`,`assert` & `optional` . See [JLS#2691](https://github.com/eclipse/eclipse.jdt.ls/pull/2691), [JLS#2697](https://github.com/eclipse/eclipse.jdt.ls/pull/2697). + * enhancement - Use choice syntax as placeholder for constructor/method/field snippets. See [#3018](https://github.com/redhat-developer/vscode-java/pull/3018), [#3140](https://github.com/redhat-developer/vscode-java/pull/3140). + * enhancement - The `try-catch` snippet should support being applied to a selection. See [#3103](https://github.com/redhat-developer/vscode-java/issues/3103). + * enhancement - Track errors, exceptions, and project import success rate on server side for reliability analysis. See [#3162](https://github.com/redhat-developer/vscode-java/pull/3162), [JLS#2726](https://github.com/eclipse/eclipse.jdt.ls/pull/2726). + * bug fix - Display package name in document symbols outline for class files. See [#3074](https://github.com/redhat-developer/vscode-java/issues/3074). + * bug fix - Signature help should display the selected completion item. See [#3127](https://github.com/redhat-developer/vscode-java/issues/3127). + * bug fix - Gracefully handle language server failures/crashes. See [#2036](https://github.com/redhat-developer/vscode-java/issues/2036), [#3131](https://github.com/redhat-developer/vscode-java/issues/3131). + * bug fix - No completions on field initializer with `@Default` and `@Builder` Lombok annotations. See [JLS#2669](https://github.com/eclipse/eclipse.jdt.ls/issues/2669). + * bug fix - `IllegalArgumentException` within a try-catch block. See [#3138](https://github.com/redhat-developer/vscode-java/issues/3138). + * bug fix - Fix `pId` mismatch in completions. See [JLS#2681](https://github.com/eclipse/eclipse.jdt.ls/pull/2681). + * bug fix - Typo in constant `METADATA_FILES_GENERATION`. See [#3133](https://github.com/redhat-developer/vscode-java/pull/3133). + * build - Add enviornment variable to reference an external build of JDT-LS. See [#3151](https://github.com/redhat-developer/vscode-java/issues/3151). + * build - Check for non-standard NPM registry in `package-lock.json` as a step in CI. See [#2876](https://github.com/redhat-developer/vscode-java/issues/2876). + * build - Bump `semver` from 7.3.5 to 7.5.2. See [#3168](https://github.com/redhat-developer/vscode-java/pull/3168). + +## 1.19.0 (June 1st, 2023) + * performance - No need to run the reconcile operation in a workspace job. See [JLS#2660](https://github.com/eclipse/eclipse.jdt.ls/pull/2660). + * performance - Avoid blocking the pipeline while handling `refreshLocal` during document lifecycle events. See [JLS#2659](https://github.com/eclipse/eclipse.jdt.ls/pull/2659). + * performance - Avoid running document lifecycle in a workspace runnable unless it is necessary. See [JLS#2641](https://github.com/eclipse/eclipse.jdt.ls/pull/2641), [JLS#2637](https://github.com/eclipse/eclipse.jdt.ls/pull/2637). + * performance - Re-validate current document if the focus is switched to a Java file. See [#3053](https://github.com/redhat-developer/vscode-java/pull/3053). + * performance - Only append data on completion item selected. See [JLS#2639](https://github.com/eclipse/eclipse.jdt.ls/pull/2639). + * performance - Remove some unnecessary completion item data fields. See [JLS#2638](https://github.com/eclipse/eclipse.jdt.ls/issues/2638). + * performance - Remove `COMPLETION_EXECUTION_TIME` from the completion item response. See [JLS#2621](https://github.com/eclipse/eclipse.jdt.ls/issues/2621). + * performance - Use separate thread to handle `didChangeWatchedFiles` events. See [JLS#2643](https://github.com/eclipse/eclipse.jdt.ls/pull/2643). + * performance - Add option to lazily resolve the text edits. See [JLS#1864](https://github.com/eclipse/eclipse.jdt.ls/issues/1864). + * enhancement - Add command to restart Java language server. See [#2586](https://github.com/redhat-developer/vscode-java/pull/2586). + * enhancement - Add support for proper array completions. See [JLS#2609](https://github.com/eclipse/eclipse.jdt.ls/issues/2609). + * enhancement - Completion items should support `InsertTextMode`. See [JLS#2577](https://github.com/eclipse/eclipse.jdt.ls/issues/2577). + * enhancement - Use `vscode-extension-proposals` for recommendations. See [#3099](https://github.com/redhat-developer/vscode-java/issues/3099). + * bug fix - Missing javadoc for field during completion. See [JLS#2645](https://github.com/eclipse/eclipse.jdt.ls/issues/2645). + * bug fix - Incorrect completion text edit ranges for snippets. See [JLS#2626](https://github.com/eclipse/eclipse.jdt.ls/issues/2626). + * bug fix - Update completion resolve data for javadoc completions. See [JLS#2636](https://github.com/eclipse/eclipse.jdt.ls/pull/2636). + * bug fix - Prevent sending shutdown job progress report. See [JLS#2622](https://github.com/eclipse/eclipse.jdt.ls/pull/2622). + * bug fix - On Windows, `os.execvp` does not load the executable into current process. See [JLS#2615](https://github.com/eclipse/eclipse.jdt.ls/issues/2615). + * bug fix - Code completion for constructor is broken with `java.completion.matchCase` enabled. See [#3118](https://github.com/redhat-developer/vscode-java/issues/3118). + * build - Gracefully recover from failure to detect the language server project in sibling directory. See [#3107](https://github.com/redhat-developer/vscode-java/issues/3107). + * dependencies - Update to lombok 1.18.28. See [#3117](https://github.com/redhat-developer/vscode-java/pull/3117). + +## 1.18.0 (April 27th, 2023) + * performance - Completion handling should not be done in asynchronous thread pool. See [JLS#2605](https://github.com/eclipse/eclipse.jdt.ls/pull/2605). + * performance - Support lazily resolving postfix completion items. See [#3072](https://github.com/redhat-developer/vscode-java/pull/3072), [JLS#2616](https://github.com/eclipse/eclipse.jdt.ls/issues/2616), [JLS#2584](https://github.com/eclipse/eclipse.jdt.ls/issues/2584). + * performance - Place the URI of a document into the completion response store. See [#2614](https://github.com/eclipse/eclipse.jdt.ls/pull/2614). + * enhancement - Provide Java 20 support. See [#3023](https://github.com/redhat-developer/vscode-java/issues/3023). + * enhancement - Add `syserr` postfix completion. See [JLS#2620](https://github.com/eclipse/eclipse.jdt.ls/pull/2620). + * bug fix - Ensure meaningful information is displayed by the progress reporter. See [#3082](https://github.com/redhat-developer/vscode-java/pull/3082). + * bug fix - Respect settings in the `lombok.config` file. See [#2887](https://github.com/redhat-developer/vscode-java/issues/2887). + * bug fix - `NullPointerException` in `signatureHelp/codeAction/inlayHint` when AST is not generated. See [JLS#2608](https://github.com/eclipse/eclipse.jdt.ls/issues/2608). + * bug fix - `StringIndexOutOfBoundsException` on `textDocument/signatureHelp` when triggered from end of document. See [JLS#2606](https://github.com/eclipse/eclipse.jdt.ls/issues/2606). + * bug fix - Some logged information should only be shown in debug mode. See [JLS#2603](https://github.com/eclipse/eclipse.jdt.ls/issues/2603). + +## 1.17.0 (April 13th, 2023) + * performance - Support resolving dependencies in parallel for Maven projects. See [#3030](https://github.com/redhat-developer/vscode-java/pull/3030). + * performance - Cache and re-use type bindings for a completion invocation. See [JLS#2535](https://github.com/eclipse/eclipse.jdt.ls/pull/2535). + * performance - Avoid retrieving AST root during diagnostic publishing. See [JLS#2574](https://github.com/eclipse/eclipse.jdt.ls/pull/2574). + * performance - Implement `itemDefaults` for completion responses. See [JLS#2475](https://github.com/eclipse/eclipse.jdt.ls/issues/2475). + * enhancement - Add support for decompiling class files. See [#2679](https://github.com/redhat-developer/vscode-java/issues/2679), [#3012](https://github.com/redhat-developer/vscode-java/issues/3012). + * enhancement - Add "Change signature" refactoring. See [#2104](https://github.com/redhat-developer/vscode-java/issues/2104). + * enhancement - Implement `labelDetails` for completion items. See [JLS#2476](https://github.com/eclipse/eclipse.jdt.ls/issues/2476). + * enhancement - `sysout` postfix completion should be applicable to any variable. See [JLS#2559](https://github.com/eclipse/eclipse.jdt.ls/pull/2559). + * enhancement - Add support for telemetry notifications. See [#2289](https://github.com/redhat-developer/vscode-java/issues/2289), [#3042](https://github.com/redhat-developer/vscode-java/pull/3042), [#3058](https://github.com/redhat-developer/vscode-java/pull/3058). + * enhancement - Trace API should give indicator of response success status. See [#3010](https://github.com/redhat-developer/vscode-java/pull/3010). + * bug fix - Single double quote should be matched appropriately. See [#3037](https://github.com/redhat-developer/vscode-java/issues/3037). + * bug fix - Increase relevance of "Create enum". See [#2940](https://github.com/redhat-developer/vscode-java/issues/2940). + * bug fix - Recover when `documentPaste` API is not properly registered. See [#3028](https://github.com/redhat-developer/vscode-java/pull/3028). + * bug fix - Ensure we do not return duplicate search results for workspace symbols. See [JLS#2547](https://github.com/eclipse/eclipse.jdt.ls/pull/2547). + * bug fix - Code action to generate accessor outside of identifier no longer available. See [JLS#2533](https://github.com/eclipse/eclipse.jdt.ls/issues/2533). + * bug fix - Support importing multi-Maven projects with the same `artifactId`. See [JLS#2017](https://github.com/eclipse/eclipse.jdt.ls/issues/2017). + * bug fix - Do not show `Generate Constructors` quick assist for static fields. See [JLS#2142](https://github.com/eclipse/eclipse.jdt.ls/issues/2142). + * bug fix - Delegate commands should respect cancellation events from the client. See [JLS#2415](https://github.com/eclipse/eclipse.jdt.ls/issues/2415). + * bug fix - Ensure `java.project.upgradeGradle` client/server commands do not clash. See [#3001](https://github.com/redhat-developer/vscode-java/issues/3001). + * bug fix - Fix "commands test" when run locally. See [#3027](https://github.com/redhat-developer/vscode-java/pull/3027). + * build - Exclude `.github/` and `.gitignore` from packaging. See [#3057](https://github.com/redhat-developer/vscode-java/pull/3057). + * build - Add separate tsconfig for webview. See [#3009](https://github.com/redhat-developer/vscode-java/pull/3009). + * debt - Support the refactoring document correctly. See [#2974](https://github.com/redhat-developer/vscode-java/issues/2974). + +## 1.16.0 (March 16th, 2023) + * performance - Allow language server to declare availability sooner by postponing autobuild. See [JLS#2527](https://github.com/eclipse/eclipse.jdt.ls/pull/2527). + * performance - Save operations need not run in workspace runnable when project is not unmanaged. See [JLS#2449](https://github.com/eclipse/eclipse.jdt.ls/pull/2449). + * enhancement - Implement method hierarchy through existing type hierarchy logic. See [#2991](https://github.com/redhat-developer/vscode-java/pull/2991). + * enhancement - Declare support for inlay hints through the language server specification. See [#2965](https://github.com/redhat-developer/vscode-java/pull/2965), [JLS#2365](https://github.com/eclipse/eclipse.jdt.ls/issues/2365). + * enhancement - Update types filter according to import declarations. See [#2943](https://github.com/redhat-developer/vscode-java/issues/2943). + * enhancement - Update to vscode-languageclient 8.1.0, LSP4J 0.20.0 (LSP 3.17.0). See [#2474](https://github.com/redhat-developer/vscode-java/issues/2474), [JLS#2348](https://github.com/eclipse/eclipse.jdt.ls/issues/2348). + * bug fix - Fix regression in extension startup for web-based editors. See [#2968](https://github.com/redhat-developer/vscode-java/issues/2968). + * bug fix - No completion on generic anonymous class instance objects. See [JLS#2505](https://github.com/eclipse/eclipse.jdt.ls/issues/2505). + * bug fix - Null Analysis does not work for Eclipse/Invisible projects. See [#2956](https://github.com/redhat-developer/vscode-java/issues/2956). + * bug fix - Unnecessary error marker for record constructor that uses varargs. See [#2640](https://github.com/redhat-developer/vscode-java/issues/2640). + * bug fix - Temporary fix to ensure refactoring document is displayed. See [#2975](https://github.com/redhat-developer/vscode-java/pull/2975). + * bug fix - In progress items should always be at the bottom in the server tasks view. See [#2627](https://github.com/redhat-developer/vscode-java/issues/2627). + * bug fix - Fix NPE in `textDocument/documentHighlight` requests. See [#2952](https://github.com/redhat-developer/vscode-java/issues/2952). + * bug fix - Update VS Code engine to 1.74.0. See [#2950](https://github.com/redhat-developer/vscode-java/issues/2950). + * build - Bump webpack from 5.34.0 to 5.76.0. See [#2999](https://github.com/redhat-developer/vscode-java/pull/2999). + * other - Add API to track LSP performance at the language client. See [#2996](https://github.com/redhat-developer/vscode-java/pull/2996). + +## 1.15.0 (February 20th, 2023) + * performance - Skip generated methods when calculating document symbols. See [JLS#2446](https://github.com/eclipse/eclipse.jdt.ls/issues/2446). + * performance - Make the debounce adaptive for the publish diagnostic job. See [JLS#2443](https://github.com/eclipse/eclipse.jdt.ls/pull/2443). + * performance - Only perform context sensitive import rewrite when resolving completion items. See [JLS#2453](https://github.com/eclipse/eclipse.jdt.ls/pull/2453). + * performance - Extension activation should not depend on language server being started. See [#2900](https://github.com/redhat-developer/vscode-java/issues/2900). + * performance - Copy/paste within the same file should not trigger the paste handler for missing imports. See [JLS#2441](https://github.com/eclipse/eclipse.jdt.ls/issues/2441). + * enhancement - Support "extract interface" refactoring. See [#761](https://github.com/redhat-developer/vscode-java/issues/761). + * enhancement - Add "Convert String concatenation to Text Block" quick assist. See [JLS#2456](https://github.com/eclipse/eclipse.jdt.ls/pull/2456). + * enhancement - Add clean up for using `try-with-resource`. See [#2891](https://github.com/redhat-developer/vscode-java/pull/2891). + * enhancement - Enable formatting support in syntax server. See [#2926](https://github.com/redhat-developer/vscode-java/issues/2926). + * enhancement - Add option to configure behaviour when mojo execution metadata not available. See [#2889](https://github.com/redhat-developer/vscode-java/issues/2889). + * enhancement - Add option to permit usage of test resources of a Maven project as dependencies within the compile scope of other projects. See [#2569](https://github.com/redhat-developer/vscode-java/issues/2569). + * bug fix - Change default generated method stub to throw exception. See [JLS#2366](https://github.com/eclipse/eclipse.jdt.ls/pull/2366). + * bug fix - Prevent the paste handler for missing imports from generating overlapping text edits. See [JLS#2442](https://github.com/eclipse/eclipse.jdt.ls/issues/2442). + * bug fix - Reference search doesn't work for fields in JDK classes. See [JLS#2405](https://github.com/eclipse/eclipse.jdt.ls/issues/2405). + * bug fix - Paste event handling blocks pasting while project loading. See [#2924](https://github.com/redhat-developer/vscode-java/issues/2924). + * bug fix - Avoid generating boilerplate code repeatedly in new Java file. See [#2939](https://github.com/redhat-developer/vscode-java/issues/2939). + * bug fix - Completion results should include filtered (excluded) types if they are also present in the import declarations. See [JLS#2467](https://github.com/eclipse/eclipse.jdt.ls/pull/2467). + * bug fix - Fix type hierarchy regression since VS Code 1.75.1. See [#2930](https://github.com/redhat-developer/vscode-java/pull/2930). + * bug fix - Re-publish diagnostics for null analysis configuration change when auto-build is disabled. See [JLS#2447](https://github.com/eclipse/eclipse.jdt.ls/pull/2447). + * bug fix - Dependency Analytics extension popup should respect user choice. See [#2892](https://github.com/redhat-developer/vscode-java/issues/2892). + * bug fix - Only do full build for a configuration change when auto-build is enabled. See [JLS#2437](https://github.com/eclipse/eclipse.jdt.ls/pull/2437). + * bug fix - The command to upgrade gradle should check for cancellation prior to updating metadata files. See [JLS#2444](https://github.com/eclipse/eclipse.jdt.ls/pull/2444). + * bug fix - Fix incorrect ordering of completion items that use a decorator. See [#2917](https://github.com/redhat-developer/vscode-java/issues/2917). + * bug fix - Reduce the amount of logging from `org.apache.http` bundles. See [JLS#2420](https://github.com/eclipse/eclipse.jdt.ls/pull/2420). + * build - Do not require `org.eclipse.xtend.lib`. See [JLS#2416](https://github.com/eclipse/eclipse.jdt.ls/pull/2416). + * build - Add Github action to detect potential duplicate issues. See [#2927](https://github.com/redhat-developer/vscode-java/pull/2927). + * build - Use commit SHA-1 instead of branch name for third-party actions. See [#2895](https://github.com/redhat-developer/vscode-java/pull/2895). + * documentation - Clarify the `README` quick start instructions. See [#2915](https://github.com/redhat-developer/vscode-java/pull/2915). + +## 1.14.0 (January 17th, 2023) + * enhancement - Support for shared indexes among workspaces. See [#2723](https://github.com/redhat-developer/vscode-java/issues/2723). + * enhancement - Support pasting content into a string literal. See [#1249](https://github.com/redhat-developer/vscode-java/issues/1249). + * enhancement - Resolve missing imports (if any) when pasting code. See [JLS#2320](https://github.com/eclipse/eclipse.jdt.ls/pull/2320). + * enhancement - Support matching case for code completion. See [#2834](https://github.com/redhat-developer/vscode-java/pull/2834). + * enhancement - Add code action to insert missing required attributes for an annotation. See [JLS#1860](https://github.com/eclipse/eclipse.jdt.ls/issues/1860). + * enhancement - Create cleanup actions for adding `final` modifier where possible, converting `switch` statement to `switch` expression, using pattern matching for `instanceof` checks, and converting anonymous functions to lambda expressions. See [#2827](https://github.com/redhat-developer/vscode-java/pull/2827). + * enhancement - Support quickfix for gradle jpms projects. See [JLS#2304](https://github.com/eclipse/eclipse.jdt.ls/pull/2304). + * enhancement - Add the Korean translation file. See [#2802](https://github.com/redhat-developer/vscode-java/pull/2802). + * bug fix - Fix incorrect type hierarchy on multi module Maven projects. See [#2871](https://github.com/redhat-developer/vscode-java/issues/2871). + * bug fix - Permit output folder to be the same as a source folder. See [#2786](https://github.com/redhat-developer/vscode-java/issues/2786). + * bug fix - Organize imports removes static imports under some conditions. See [#2861](https://github.com/redhat-developer/vscode-java/issues/2861). + * bug fix - Fix completion issue occurring when invocation spans multiple lines. See [JLS#2387](https://github.com/eclipse/eclipse.jdt.ls/issues/2387). + * bug fix - Fix scope calculation for "Surround with try/catch" refactoring. See [#2711](https://github.com/redhat-developer/vscode-java/issues/2711). + * bug fix - Fix NPE occurring when completion item is selected. See [JLS#2376](https://github.com/eclipse/eclipse.jdt.ls/issues/2376). + * bug fix - Log user friendly error if client does not support `_java.reloadBundles.command`. See [JLS#2370](https://github.com/eclipse/eclipse.jdt.ls/pull/2370). + * bug fix - Postfix completion should not be available when editing Javadoc. See [JLS#2367](https://github.com/eclipse/eclipse.jdt.ls/issues/2367). + * bug fix - Update m2e to latest version in order to ensure classpath resources persist. See [#2857](https://github.com/redhat-developer/vscode-java/issues/2857). + * build - Use `instanceof` pattern matching in code base. See [JLS#2357](https://github.com/eclipse/eclipse.jdt.ls/pull/2357). + * build - React to `vsce` renaming to `@vscode/vsce`. See [#2879](https://github.com/redhat-developer/vscode-java/pull/2879). + * build - Work around vsce refusal to publish extensions with proposed API. See [#2854](https://github.com/redhat-developer/vscode-java/pull/2854). + * build - Deploy the universal vsix to support all platforms without an embedded JRE. See [#2837](https://github.com/redhat-developer/vscode-java/issues/2837). + * build - Ensure npm public registry is used for the resolved field in `package-lock.json`. See [#2874](https://github.com/redhat-developer/vscode-java/issues/2874). + * build - Bump qs from 6.5.2 to 6.5.3 and decode-uri-component from 0.2.0 to 0.2.2. See [#2832](https://github.com/redhat-developer/vscode-java/pull/2832), [#2823](https://github.com/redhat-developer/vscode-java/pull/2823). + * build - Move utilities out of extension.ts. See [#2824](https://github.com/redhat-developer/vscode-java/pull/2824). + * documentation - Fix Build Status badge. See [#2847](https://github.com/redhat-developer/vscode-java/pull/2847). + +## 1.13.0 (December 1st, 2022) + * enhancement - Support "Add all missing imports". See [#2753](https://github.com/redhat-developer/vscode-java/pull/2753). + * enhancement - Support Gradle annotation processing. See [#1039](https://github.com/redhat-developer/vscode-java/issues/1039). + * enhancement - Add an option to configure null analysis, and set to `interactive` by default. See [#2747](https://github.com/redhat-developer/vscode-java/pull/2747), [#2790](https://github.com/redhat-developer/vscode-java/pull/2790). + * enhancement - Add setting for clean ups to be applied when document is saved. See [#2144](https://github.com/redhat-developer/vscode-java/issues/2144), [#2803](https://github.com/redhat-developer/vscode-java/pull/2803), [#2813](https://github.com/redhat-developer/vscode-java/pull/2813). + * enhancement - Add contribution points for completion customization. See [JLS#2110](https://github.com/eclipse/eclipse.jdt.ls/pull/2110). + * enhancement - Allow the language server to be run without using `IApplication`. See [JLS#2311](https://github.com/eclipse/eclipse.jdt.ls/issues/2311). + * enhancement - Improve Lombok support and renaming fields when an accessor is present. See [#2805](https://github.com/redhat-developer/vscode-java/issues/2805). + * bug fix - Display the postfix completions at the bottom of the list. See [JLS#2343](https://github.com/eclipse/eclipse.jdt.ls/pull/2343). + * bug fix - Display a link for `{@link ...}` expression within javadoc. See [#2810](https://github.com/redhat-developer/vscode-java/issues/2810). + * bug fix - Do not reset existing project options when setting null analysis options. See [#2764](https://github.com/redhat-developer/vscode-java/issues/2764). + * bug fix - Code action response may contain `null` as one of the code actions. See [JLS#2327](https://github.com/eclipse/eclipse.jdt.ls/issues/2327). + * bug fix - Inlay hints should not show up next to Lombok annotations. See [JLS#2323](https://github.com/eclipse/eclipse.jdt.ls/issues/2323). + * bug fix - Ensure language server always terminates. See [JLS#2302](https://github.com/eclipse/eclipse.jdt.ls/issues/2302). + * bug fix - Prevent a deadlock during language server initialization. See [#2763](https://github.com/redhat-developer/vscode-java/issues/2763). + * bug fix - Always send `begin` work done progress before sending `end`. See [JLS#2258](https://github.com/eclipse/eclipse.jdt.ls/pull/2258). + * bug fix - Use existing Gradle project `.settings/` location if available. See [#2528](https://github.com/redhat-developer/vscode-java/issues/2528). + * bug fix - Avoid re-using the same job for the "Publish Diagnostics" job. See [JLS#2356](https://github.com/eclipse/eclipse.jdt.ls/pull/2356). + * build - Use Predicate for filter. See [JLS#2355](https://github.com/eclipse/eclipse.jdt.ls/pull/2355). + * build - Add pre-release and platform specific publishing for OpenVSX registry. See [#2587](https://github.com/redhat-developer/vscode-java/pull/2587). + * build - Fix issues reported by npm-audit. See [#2777](https://github.com/redhat-developer/vscode-java/pull/2777). + +## 1.12.0 (October 27th, 2022) + * performance - Improve project initialization. See [JLS#2252](https://github.com/eclipse/eclipse.jdt.ls/pull/2252). + * performance - Re-use ExecutorService to avoid creating extra threads and resource leak. See [JLS#2041](https://github.com/eclipse/eclipse.jdt.ls/pull/2041). + * performance - Avoid triggering full rebuild of project after import completes (on Windows). See [#793](https://github.com/redhat-developer/vscode-java/issues/793). + * enhancement - Add support for postfix completion. See [#1455](https://github.com/redhat-developer/vscode-java/issues/1455). + * enhancement - Add quick fix for "remove all unused imports". See [JLS#2280](https://github.com/eclipse/eclipse.jdt.ls/pull/2280). + * enhancement - Add quick fixes for problems relating to sealed classes. See [JLS#2265](https://github.com/eclipse/eclipse.jdt.ls/pull/2265). + * bug fix - Signature help not working correctly for parameterized types. See [#2739](https://github.com/redhat-developer/vscode-java/issues/2739). + * bug fix - Avoid NPE for null analysis when updating classpath. See [#2712](https://github.com/redhat-developer/vscode-java/issues/2712). + * bug fix - Check the digest of the initializiation scripts for security and to prevent duplicates. See [#2692](https://github.com/redhat-developer/vscode-java/issues/2692). + * bug fix - Support `includeDeclaration` in `textDocument/references`. See [JLS#2148](https://github.com/eclipse/eclipse.jdt.ls/issues/2148). + * bug fix - Provide folding for import regions in `.class` files. See [#2133](https://github.com/redhat-developer/vscode-java/issues/2133). + * bug fix - Deadlock when using JDK 17 with Maven Java project. See [#2676](https://github.com/redhat-developer/vscode-java/issues/2676). + * bug fix - Ignore unnamed module for split packages. See [JLS#2273](https://github.com/eclipse/eclipse.jdt.ls/pull/2273). + * bug fix - The project preference should only persist non default values. See [JLS#2272](https://github.com/eclipse/eclipse.jdt.ls/issues/2272). + * bug fix - Synchronize contributed bundles on demand. See [#2729](https://github.com/redhat-developer/vscode-java/pull/2729). + * bug fix - Avoid unnecessary project updates when the default VM changes. See [JLS#2266](https://github.com/eclipse/eclipse.jdt.ls/pull/2266). + * bug fix - Exclude non-compile scope dependencies from consideration for enabling null analysis. See [JLS#2264](https://github.com/eclipse/eclipse.jdt.ls/pull/2264). + * bug fix - Add opportunistic support for Java/Kotlin polyglot Android projects. See [JLS#2261](https://github.com/eclipse/eclipse.jdt.ls/pull/2261). + + +## 1.11.0 (September 29th, 2022) + * enhancement - Provide Java 19 preview support. See [#2650](https://github.com/redhat-developer/vscode-java/issues/2650). + * enhancement - Enable annotation-based `null` analysis. See [#1693](https://github.com/redhat-developer/vscode-java/issues/1693). + * enhancement - Show generate `toString()`, `hashCode()` and `equals()` quick fixes on demand. See [JLS#2213](https://github.com/eclipse/eclipse.jdt.ls/pull/2213). + * enhancement - Enable method argument guessing (`java.completion.guessMethodArguments`) by default. See [#2621](https://github.com/redhat-developer/vscode-java/issues/2621). + * enhancement - Enable signature help (`java.signatureHelp.enabled`) by default. See [#2063](https://github.com/redhat-developer/vscode-java/issues/2063). + * enhancement - Support creating `module-info.java`. See [#2680](https://github.com/redhat-developer/vscode-java/pull/2680). + * enhancement - Only add parentheses for lambda expression completions with multiple parameters. See [JLS#2100](https://github.com/eclipse/eclipse.jdt.ls/issues/2100). + * enhancement - Add buildship auto sync preference when build configuration update is set to `automatic`. See [JLS#2224](https://github.com/eclipse/eclipse.jdt.ls/pull/2224). + * bug fix - Show the field suggestions for the `toString()`, `hashCode()` and `equals()` generator dialogs in definition order. See [#2502](https://github.com/redhat-developer/vscode-java/issues/2502). + * bug fix - Fix Gradle project synchorization errors when init script path contains spaces. See [JLS#2245](https://github.com/eclipse/eclipse.jdt.ls/pull/2245), [JLS#2222](https://github.com/eclipse/eclipse.jdt.ls/issues/2222), [JLS#2249](https://github.com/eclipse/eclipse.jdt.ls/pull/2249). + * bug fix - Fix NPE in the protobuf init script. See [#2700](https://github.com/redhat-developer/vscode-java/issues/2700). + * bug fix - Disable JVM logging by default (`-Xlog:disable`). See [#2292](https://github.com/redhat-developer/vscode-java/issues/2292). + * bug fix - Fix type completion when type name conflicts. See [JLS#2232](https://github.com/eclipse/eclipse.jdt.ls/pull/2232). + * bug fix - Fix gradle project classpath calculation. See [#2628](https://github.com/redhat-developer/vscode-java/issues/2628). + * bug fix - Bad ".git" pattern in `.project` file's `filteredResources` element causes chaos. See [#2704](https://github.com/redhat-developer/vscode-java/pull/2704). + * bug fix - Creating a new Java file won't generate package statement. See [#2687](https://github.com/redhat-developer/vscode-java/issues/2687). + * bug fix - Improve documentation for static import order. See [#711](https://github.com/redhat-developer/vscode-java/issues/711). + * build - Migrate from tslint to eslint. See [#2415](https://github.com/redhat-developer/vscode-java/pull/2415). + +## 1.10.0 (August 31st, 2022) + * enhancement - Search more folders to infer source roots for invisible projects. See [JLS#2176](https://github.com/eclipse/eclipse.jdt.ls/pull/2176). + * enhancement - Experimental support for Android projects with `java.jdt.ls.androidSupport.enabled`. It is enabled by default only in VS Code Insiders. See [JLS#923](https://github.com/eclipse/eclipse.jdt.ls/issues/923). + * enhancement - Automatically add Protobuf output source directories to classpath & generate tasks, if necessary. See [#2629](https://github.com/redhat-developer/vscode-java/pull/2629) & [JLS#2195](https://github.com/eclipse/eclipse.jdt.ls/pull/2195). + * enhancement - Support "Sort Members" code action. See [#2139](https://github.com/redhat-developer/vscode-java/issues/2139). + * enhancement - Add grammar for Java Properties files. See [#2636](https://github.com/redhat-developer/vscode-java/pull/2636). + * enhancement - Always interpret the full workspace symbol query as a package name. See [JLS#2174](https://github.com/eclipse/eclipse.jdt.ls/pull/2174). + * enhancement - Add support for Maven offline mode (`java.import.maven.offline.enabled`). See [#2617](https://github.com/redhat-developer/vscode-java/pull/2617). + * enhancement - Add the `zh-TW` (Traditional Chinese) translation file. See [#2573](https://github.com/redhat-developer/vscode-java/pull/2573). + * bug fix - Prevent "Header must provide a Content-Length property" failure by restricting JVM logging. See [#2577](https://github.com/redhat-developer/vscode-java/issues/2577). + * bug fix - Infer the source root only when necessary. See [JLS#2178](https://github.com/eclipse/eclipse.jdt.ls/pull/2178). + * bug fix - Fix inlay hints for `record` classes. See [#2414](https://github.com/redhat-developer/vscode-java/issues/2414). + * bug fix - Fix formatting of the `new` snippets. See [#2605](https://github.com/redhat-developer/vscode-java/issues/2605). + * bug fix - Make `java.import.gradle.java.home` property machine-overridable. See [#2624](https://github.com/redhat-developer/vscode-java/pull/2624). + * bug fix - Set default severity of "Circular classpath" to "warning". See [#718](https://github.com/redhat-developer/vscode-java/issues/718). + * bug fix - Permit non-JDT errors to be reported in Java files. See [JLS#2154](https://github.com/eclipse/eclipse.jdt.ls/issues/2154). + * bug fix - Avoid naming conflicts between Gradle project modules. See [JLS#2190](https://github.com/eclipse/eclipse.jdt.ls/pull/2190). + * bug fix - Re-fetch the extension registry when delegate command lookup fails. See [JLS#2184](https://github.com/eclipse/eclipse.jdt.ls/pull/2184). + * bug fix - Skip the "default project" when detecting Lombok. See [#2633](https://github.com/redhat-developer/vscode-java/pull/2633). + * bug fix - Skip security check for `java.home` and `java.jdt.ls.java.home` in trusted workspace. See [#2600](https://github.com/redhat-developer/vscode-java/issues/2600). + * bug fix - Keep consistent style in notifications (eg. use "Reload") and use plural form for `Reload Projects` command title. See [#2585](https://github.com/redhat-developer/vscode-java/issues/2585) & [#2612](https://github.com/redhat-developer/vscode-java/pull/2612). + * dependencies - Update to `jdk-utils@0.4.4`. See [#2601](https://github.com/redhat-developer/vscode-java/pull/2601). + * debt - Remove stale Travis CI information from `README`. See [#2592](https://github.com/redhat-developer/vscode-java/issues/2592). + +## 1.9.0 (July 21st, 2022) + * enhancement - Package lombok into extension for use when lombok support enabled, and not on project classpath. See [#2550](https://github.com/redhat-developer/vscode-java/pull/2550). + * enhancement - Add support for qualified workspace symbols. See [#2538](https://github.com/redhat-developer/vscode-java/pull/2538). + * enhancement - Refresh the unmanaged project's classpath on demand. See [#1282](https://github.com/redhat-developer/vscode-java/issues/1282). + * enhancement - Provide reload project diagnostics on demand. See [#2575](https://github.com/redhat-developer/vscode-java/pull/2575). + * bug fix - Missing completions for fully qualified constructor names. See [JLS#2147](https://github.com/eclipse/eclipse.jdt.ls/issues/2147). + * bug fix - Completion replacement for a type proposal is incorrect in some cases. See [#2534](https://github.com/redhat-developer/vscode-java/issues/2534). + * bug fix - Project configuration is not updated after modifying build file. See [#2566](https://github.com/redhat-developer/vscode-java/issues/2566). + * bug fix - Fixed language server crashing because of wrong lombok jar. See [#2542](https://github.com/redhat-developer/vscode-java/pull/2542). + * bug fix - Do not warn about missing JDT-LS stdout/stderr log files. See [#2535](https://github.com/redhat-developer/vscode-java/issues/2535). + * bug fix - Scan two levels of directories for activation indicators. See [#2280](https://github.com/redhat-developer/vscode-java/issues/2280). + * bug fix - Correct typo in gradle checksum mismatch error message. See [JLS#2161](https://github.com/eclipse/eclipse.jdt.ls/pull/2161). + * build - wrong JRE embedded in pre-release package. See [#2559](https://github.com/redhat-developer/vscode-java/issues/2559). + * build - TypeError: `s.logFailedRequest` is not a function. See [#2480](https://github.com/redhat-developer/vscode-java/issues/2480). + * build - Compile error in `MavenBuildSupport.update(IProject, boolean, IProgressMonitor)`. See [JLS#2150](https://github.com/eclipse/eclipse.jdt.ls/issues/2150). + * build - Migrate to `@vscode/test-electron`. See [#2555](https://github.com/redhat-developer/vscode-java/pull/2555). + * build - Update moment & terser packages. See [#2580](https://github.com/redhat-developer/vscode-java/pull/2580). + +## 1.8.0 (June 30th, 2022) + * enhancement - Improve the Lombok support. See [#2519](https://github.com/redhat-developer/vscode-java/pull/2519). + * enhancement - Show `Add javadoc for` in quick assists. See [JLS#2133](https://github.com/eclipse/eclipse.jdt.ls/pull/2133). + * enhancement - Show `Change modifiers to final` in quick assists. See [JLS#2134](https://github.com/eclipse/eclipse.jdt.ls/pull/2134). + * enhancement - Support project reload selection. See [#2513](https://github.com/redhat-developer/vscode-java/pull/2513). + * enhancement - Auto-select field when generating constructors. See [#2125](https://github.com/redhat-developer/vscode-java/pull/2508). + * enhancement - Allow to build selected projects. See [#2526](https://github.com/redhat-developer/vscode-java/pull/2526). + * enhancement - Support multiple selections for generate accessors. See [JLS#2136](https://github.com/eclipse/eclipse.jdt.ls/pull/2136). + * bug fix - Fix NPE when triggering signature help in class file. See [JLS#2102](https://github.com/eclipse/eclipse.jdt.ls/issues/2102). + * bug fix - Support for renaming record attributes. See [#2433](https://github.com/redhat-developer/vscode-java/issues/2433). + * bug fix - Add logback tracing to JDT-LS. See [JLS#2108](https://github.com/eclipse/eclipse.jdt.ls/issues/2108). + * bug fix - `Open All Log Files` should also include the standard output/error log files. See [#2367](https://github.com/redhat-developer/vscode-java/issues/2367). + * bug fix - Verify that `java.jdt.ls.java.home` meets minimum JRE requirement. See [#2512](https://github.com/redhat-developer/vscode-java/pull/2512). + * bug fix - Avoid repeatedly setting busy and ready for language server status. See [#2494](https://github.com/redhat-developer/vscode-java/pull/2494). + * bug fix - Fix ParentProcessWatcher on macOS. See [#2488](https://github.com/redhat-developer/vscode-java/issues/2488). + * bug fix - Change the order for configuration updating options. See [JLS#2135](https://github.com/eclipse/eclipse.jdt.ls/pull/2135). + * bug fix - Show Type Hierarchy breaks in vscode-insiders. See [#2524](https://github.com/redhat-developer/vscode-java/issues/2524). + * bug fix - TypeError: Cannot read properties of undefined (reading 'stop'). See [#2503](https://github.com/redhat-developer/vscode-java/issues/2503). + * build - Move to Java 17. See [#2495](https://github.com/redhat-developer/vscode-java/pull/2495). + * debt - GitHub Actions job should use Node.js 14. See [#2532](https://github.com/redhat-developer/vscode-java/pull/2532). + * other - Adjust the order of code actions. See [JLS#2109](https://github.com/eclipse/eclipse.jdt.ls/pull/2109). + * other - Add DCO documentation. See [#2521](https://github.com/redhat-developer/vscode-java/pull/2521). + * other - Allow to clean workspace without pop-up notification. See [#2514](https://github.com/redhat-developer/vscode-java/pull/2514). + + +## 1.7.0 (June 1st, 2022) + * enhancement - Support separate "Generate Getters" and "Generate Setters". See [#2362](https://github.com/redhat-developer/vscode-java/issues/2362). + * enhancement - Show field type when generating accessors. See [#2459](https://github.com/redhat-developer/vscode-java/pull/2459). + * enhancement - Show quick fixes for generating accessors in field declarations. See [JLS#2092](https://github.com/eclipse/eclipse.jdt.ls/pull/2092). + * enhancement - Support exclusion list for inlay hints. See [#2412](https://github.com/redhat-developer/vscode-java/issues/2412). + * enhancement - Support Gradle invalid type code error check. See [#1594](https://github.com/redhat-developer/vscode-java/issues/1594). + * bug fix - Add support to open decompiled symbols through the symbols list. See [JLS#2087](https://github.com/eclipse/eclipse.jdt.ls/issues/2087). + * bug fix - Add completion support for multiline comment blocks. See [#2484](https://github.com/redhat-developer/vscode-java/pull/2484). + * bug fix - Ensure the standard server shuts down immediately after the client. See [#2471](https://github.com/redhat-developer/vscode-java/issues/2471). + * bug fix - Fix `java.completion.importOrder`. See [#2489](https://github.com/redhat-developer/vscode-java/pull/2489). + * other - Add a new API to wait for standard server ready. See [#2461](https://github.com/redhat-developer/vscode-java/pull/2461). + * other - Support publishing pre-release versions. See [#2285](https://github.com/redhat-developer/vscode-java/issues/2285). + +## 1.6.0 (May 5th, 2022) + * enhancement - Trigger signature help on completion item selected. See [#2426](https://github.com/redhat-developer/vscode-java/pull/2426). + * enhancement - Support completion insert/replace capability. Use the setting `editor.suggest.insertMode` to control whether to overwrite words when accepting completions. You can also quickly toggle between insert & replace modes with `Shift + Tab` or `Shift + Enter` (default keyboard shortcuts). See [#2427](https://github.com/redhat-developer/vscode-java/pull/2427). + * enhancement - Add a new preference `java.signatureHelp.description.enabled` to disable/enable signature description. See [#2404](https://github.com/redhat-developer/vscode-java/pull/2404). + * bug fix - Fix the "Manage Workspace Trust" command. See [#2431](https://github.com/redhat-developer/vscode-java/issues/2431). + * bug fix - Improve the signature help feature by handling some special cases. See [JLS#2025](https://github.com/eclipse/eclipse.jdt.ls/issues/2025). + * bug fix - Do not show signature help at the end of an invocation. See [JLS#2079](https://github.com/eclipse/eclipse.jdt.ls/pull/2079). + * bug fix - Show error status when the project is not created. See [JLS#2058](https://github.com/eclipse/eclipse.jdt.ls/issues/2058). + * bug fix - Error during importing an Eclipse project whose sources are at root. See [#2436](https://github.com/redhat-developer/vscode-java/issues/2436). + * bug fix - Fix NPE in isCompletionInsertReplaceSupport check. See [JLS#2070](https://github.com/eclipse/eclipse.jdt.ls/pull/2070). + * bug fix - Unexpected 'Project xxx has no explicit encoding set' warnings. See [#2416](https://github.com/redhat-developer/vscode-java/issues/2416). + * bug fix - Fix issue where JDT-LS's logback configuration was being ignored. See [JLS#2077](https://github.com/eclipse/eclipse.jdt.ls/pull/2077). + +## 1.5.0 (April 13th, 2022) + * performance - Adopt new CompletionProposal API to ignore types before creating certain proposals. See [JLS#2034](https://github.com/eclipse/eclipse.jdt.ls/pull/2034). + * enhancement - Provide Java 18 support. See [#2364](https://github.com/redhat-developer/vscode-java/pull/2364). + * enhancement - Support inlay hints for parameter names. See [#2099](https://github.com/redhat-developer/vscode-java/issues/2099). + * enhancement - Show server status through the language status item. See [#2351](https://github.com/redhat-developer/vscode-java/issues/2351). + * enhancement - Add code action to extract lambda body to method. See [JLS#2027](https://github.com/eclipse/eclipse.jdt.ls/issues/2027). + * enhancement - Navigate to class declaration. See [#2132](https://github.com/redhat-developer/vscode-java/pull/2132). + * bug fix - Provide file & type comments for newly created compilation units. See [JLS#2047](https://github.com/eclipse/eclipse.jdt.ls/pull/2047). + * bug fix - Code snippets should be usable even before LS done resolving dependencies. See [#684](https://github.com/redhat-developer/vscode-java/issues/684). + * bug fix - Fix an occurrence of duplicate quick fixes at the line level See [#2339](https://github.com/redhat-developer/vscode-java/issues/2339). + * bug fix - Cannot refactor in static block. See [#2370](https://github.com/redhat-developer/vscode-java/issues/2370). + * bug fix - Make `java.configuration.runtimes` & `java.jdt.ls.vmargs` machine-overridable. See [#2001](https://github.com/redhat-developer/vscode-java/issues/2001), [#2368](https://github.com/redhat-developer/vscode-java/pull/2368). + * bug fix - The number of method signatures cannot be displayed in some cases. See [#2341](https://github.com/redhat-developer/vscode-java/issues/2341). + * bug fix - Ensure that client-side commands do not clash with server-side. See [#2331](https://github.com/redhat-developer/vscode-java/issues/2331). + * bug fix - Fix issue in JDK detection logic. See [#2025](https://github.com/redhat-developer/vscode-java/issues/2025). + * other - Increase the maximum size of client.log file. See [#2356](https://github.com/redhat-developer/vscode-java/pull/2356). + +## 1.4.0 (March 3rd, 2022) + * enhancement - Trigger completion after `new` keyword. See [#1666](https://github.com/redhat-developer/vscode-java/issues/1666). + * enhancement - Improve occurrences highlighting. See [JLS#1941](https://github.com/eclipse/eclipse.jdt.ls/pull/1941). + * enhancement - Autoclose multiline strings (JEP 368). See [#1428](https://github.com/redhat-developer/vscode-java/issues/1428). + * enhancement - Provide more aliases for code snippets. See [#2314](https://github.com/redhat-developer/vscode-java/pull/2314). + * bug fix - "Add serial version ID" should not generate empty comments. See [JLS#1899](https://github.com/eclipse/eclipse.jdt.ls/issues/1899). + * bug fix - Convert to static import incorrectly removes import statements. See [JLS#1203](https://github.com/eclipse/eclipse.jdt.ls/issues/1203). + * bug fix - Open Java extension log doesn't open latest file. See [#2319](https://github.com/redhat-developer/vscode-java/issues/2319). + * bug fix - Type mismatch: cannot convert from `Object` to `Map`. See [JLS#1971](https://github.com/eclipse/eclipse.jdt.ls/issues/1971). + * bug fix - Signature help occasionally fails on constructors and qualified method invocations. See [#2097](https://github.com/redhat-developer/vscode-java/issues/2097). + * other - Set `java.configuration.workspaceCacheLimit` default value to 90. See [#2330](https://github.com/redhat-developer/vscode-java/pull/2330). + * other - Deprecate `java.configuration.checkProjectSettingsExclusions`. See [#2311](https://github.com/redhat-developer/vscode-java/pull/2311). + +## 1.3.0 (January 24th, 2022) + * enhancement - Support completion for lambda expressions. See [JLS#1985](https://github.com/eclipse/eclipse.jdt.ls/issues/1985). + * enhancement - Add "Convert to Switch Expression" code assist proposal. See [JLS#1935](https://github.com/eclipse/eclipse.jdt.ls/pull/1935). + * enhancement - Support Gradle compatibility check. See [#2225](https://github.com/redhat-developer/vscode-java/issues/2225). + * enhancement - Language server status bar item is not in sync with the real status. See [#2243](https://github.com/redhat-developer/vscode-java/issues/2243). + * bug fix - Fix regression in signature help. See [JLS#1980](https://github.com/eclipse/eclipse.jdt.ls/issues/1980). + * bug fix - Provide a way to disable embedded JRE. See [#2276](https://github.com/redhat-developer/vscode-java/issues/2276). + * bug fix - Projects containing windows symlink directories are not recognized. See [#2264](https://github.com/redhat-developer/vscode-java/issues/2264). + * bug fix - JDK installed via Homebrew is not detected. See [#2254](https://github.com/redhat-developer/vscode-java/issues/2254). + * bug fix - Avoid duplicate quick fixes when showing all quick fixes on a line. See [#2236](https://github.com/redhat-developer/vscode-java/issues/2236). + * bug fix - "Go to References" result contains inaccurate references. See [#2227](https://github.com/redhat-developer/vscode-java/issues/2227). + * bug fix - Ensure gradle wrappers are correctly processed on project import. See [#2218](https://github.com/redhat-developer/vscode-java/issues/2218). + * build - Fix Jenkinsfile to publish the correct generic extension version. See [#2252](https://github.com/redhat-developer/vscode-java/pull/2252). + * other - Change minimum JDK requirement listed in documentation. See [#2275](https://github.com/redhat-developer/vscode-java/pull/2275). + +## 1.2.0 (December 16th, 2021) + * enhancement - Support platform specific extension. See [#2109](https://github.com/redhat-developer/vscode-java/issues/2109). + * enhancement - Make the debounce adaptive for validation job. See [JLS#1973](https://github.com/eclipse/eclipse.jdt.ls/pull/1973). + * bug fix - Fix issue where importing packages showed incorrect result. See [#1422](https://github.com/redhat-developer/vscode-java/issues/1422). + * bug fix - Fix regression in code action for unresolved type. See [JLS#1967](https://github.com/eclipse/eclipse.jdt.ls/pull/1967). + * bug fix - Diagnostics from changes to build configuration not reflected in opened source files. See [JLS#1963](https://github.com/eclipse/eclipse.jdt.ls/issues/1963). + * bug fix - Java extension does not work on standalone java files. See [#2231](https://github.com/redhat-developer/vscode-java/issues/2231). + * debt - Remove unused log4j 1.2.15 from builds. See [JLS#1972](https://github.com/eclipse/eclipse.jdt.ls/pull/1972). + * debt - Use jdk-utils to detect installed runtimes. See [#2246](https://github.com/redhat-developer/vscode-java/pull/2246). + +## 1.1.0 (November 26th, 2021) + * enhancement - Stop generating metadata files at project's root. See [#618](https://github.com/redhat-developer/vscode-java/issues/618). + * enhancement - Quickfixes should be available at the line level. See [#2130](https://github.com/redhat-developer/vscode-java/issues/2130). + * enhancement - Explicitly report OutOfMemory error to user. See [#1959](https://github.com/redhat-developer/vscode-java/issues/1959). + * enhancement - Add option to clean out cached workspace data that is unused for a specified period of time. See [#2110](https://github.com/redhat-developer/vscode-java/issues/2110). + * enhancement - Add `Generate Constructors` to Show Fixes for type declaration. See [JLS#1937](https://github.com/eclipse/eclipse.jdt.ls/pull/1937). + * enhancement - Add `Override/Implement methods` to Show Fixes for type declaration. See [JLS#1932](https://github.com/eclipse/eclipse.jdt.ls/pull/1932). + * enhancement - Add "Surround With Try-With" code assist proposal. See [#2128](https://github.com/redhat-developer/vscode-java/issues/2128). + * enhancement - Formatter should indent `case` statements within a `switch` statement by default. See [#2185](https://github.com/redhat-developer/vscode-java/issues/2185). + * enhancement - Formatter should not join wrapped lines by default. See [#2181](https://github.com/redhat-developer/vscode-java/issues/2181). + * enhancement - Always show `Organize imports` in Quick Fixes for import declaration. See [JLS#1936](https://github.com/eclipse/eclipse.jdt.ls/pull/1936). + * bug fix - Java server refreshing the workspace (cleaning/building) for each restart. See [#2222](https://github.com/redhat-developer/vscode-java/issues/2222). + * bug fix - Problem messages can get offset by frequent changes to the document. See [#1633](https://github.com/redhat-developer/vscode-java/issues/1633). + * bug fix - Duplicate implement method quick fixes. See [JLS#1942](https://github.com/eclipse/eclipse.jdt.ls/issues/1942). + * bug fix - Malformed semantic tokens in some case. See [JLS#1922](https://github.com/eclipse/eclipse.jdt.ls/issues/1922). + * bug fix - Several errors reported for anonymous Object classes. See [JLS#1915](https://github.com/eclipse/eclipse.jdt.ls/issues/1915). + * bug fix - `if` with `instanceof` pattern match and `&&` breaks completion in nested `if`. See [JLS#1855](https://github.com/eclipse/eclipse.jdt.ls/issues/1855). + * bug fix - Java build status spinning forever. See [#2214](https://github.com/redhat-developer/vscode-java/pull/2214). + * bug fix - Creating the formatter file fails silently if parent folder doesn't exist. See [#2189](https://github.com/redhat-developer/vscode-java/issues/2189). + * debt - Don't use deprecated rangeLength property in handleChanged. See [JLS#1928](https://github.com/eclipse/eclipse.jdt.ls/pull/1928). + +## 1.0.0 (October 19th, 2021) + * performance - completion: optimize the index engine for the scenario "complete on type name". See [JLS#1846](https://github.com/eclipse/eclipse.jdt.ls/issues/1846). + * enhancement - Support Java 17. See [#2102](https://github.com/redhat-developer/vscode-java/pull/2102). + * enhancement - Add semantic token types for Records. See [#2125](https://github.com/redhat-developer/vscode-java/issues/2125). + * enhancement - Support highlight for constructor call. See [#2124](https://github.com/redhat-developer/vscode-java/issues/2124). + * enhancement - Add Getter and Setter to Show Fixes for type declaration. See [JLS#1883](https://github.com/eclipse/eclipse.jdt.ls/pull/1883). + * enhancement - Add `toString()` to Show Fixes for type declaration. See [JLS#1903](https://github.com/eclipse/eclipse.jdt.ls/pull/1903). + * enhancement - Add a `codeAction` to generate the `serialVersionUID` field. See [JLS#1892](https://github.com/eclipse/eclipse.jdt.ls/issues/1892). + * enhancement - i18n: support Chinese. See [#2027](https://github.com/redhat-developer/vscode-java/pull/2027). + * enhancement - Adopt new createStatusBarItem API. See [#2083](https://github.com/redhat-developer/vscode-java/pull/2083). + * bug fix - Missing space in anonymous type completion proposal. See [#2147](https://github.com/redhat-developer/vscode-java/issues/2147). + * bug fix - Packages are not filtered from completion despite the `java.completion.filteredTypes` configuration. See [JLS#1904](https://github.com/eclipse/eclipse.jdt.ls/issues/1904). + * bug fix - Exclude `jdk.*`, `org.graalvm.*` and `io.micrometer.shaded.*` from completion. See [#2164](https://github.com/redhat-developer/vscode-java/pull/2164). + * bug fix - "Project Configuration Update" is broken due to `JDTUtils.isExcludedFile()` is not working. See [JLS#1909](https://github.com/eclipse/eclipse.jdt.ls/issues/1909). + * bug fix - NPE on `::new` method refs (Cannot invoke `org.eclipse.jdt.core.dom.IMethodBinding.isSynthetic()` because "functionalMethod" is null). See [JLS#1885](https://github.com/eclipse/eclipse.jdt.ls/issues/1885). + * bug fix - Go to definition doesn't compute/find results on methods inside an anonymous class. See [JLS#1813](https://github.com/eclipse/eclipse.jdt.ls/issues/1813). + * bug fix - Assign all to fields generates wrong field names in some corner cases. See [JLS#1031](https://github.com/eclipse/eclipse.jdt.ls/issues/1031). + * bug fix - Import quickfix disappear on save. See [#2127](https://github.com/redhat-developer/vscode-java/issues/2127). + * bug fix - Module descriptor syntax coloring should be improved. See [#1384](https://github.com/redhat-developer/vscode-java/issues/1384). + * bug fix - Fix Open Java Formatter Settings. See [#2138](https://github.com/redhat-developer/vscode-java/pull/2138). + * bug fix - Code is compiled with preview features for no reason, causing the project not to run. See [#1971](https://github.com/redhat-developer/vscode-java/issues/1971). + * build - npm run watch fails with unresolved dependencies. See [#230](https://github.com/redhat-developer/vscode-java/issues/230). + * debt - Update org.jsoup 1.9.2 to 1.14.2. See [JLS#1884](https://github.com/eclipse/eclipse.jdt.ls/pull/1884). + +## 0.82.0 (September 16th, 2021) + * performance - completion: optimize the performance of SnippetCompletionProposal. See [JLS#1838](https://github.com/eclipse/eclipse.jdt.ls/issues/1838). + * performance - completion: listing constructors is slow. See [JLS#1836](https://github.com/eclipse/eclipse.jdt.ls/issues/1836). + * enhancement - Support Kotlin Gradle files. See [#632](https://github.com/redhat-developer/vscode-java/issues/632) & [JLS#449](https://github.com/eclipse/eclipse.jdt.ls/issues/449). + * enhancement - "Open Call Hierarchy" does not jump to the reference where it is invoked at. See [#2044](https://github.com/redhat-developer/vscode-java/issues/2044). + * enhancement - Semantic highlighting is not available in lightweight mode. See [#1999](https://github.com/redhat-developer/vscode-java/issues/1999). + * enhancement - Add additional variables for java.template snippets. See [#1987](https://github.com/redhat-developer/vscode-java/issues/1987). + * enhancement - Add 'hashCode()' and 'equals()' to Show Fixes for type declaration. See [JLS#1842](https://github.com/eclipse/eclipse.jdt.ls/pull/1842). + * enhancement - Permit usage of javaagent when resource is not in workspace. See [#1965](https://github.com/redhat-developer/vscode-java/issues/1965). + * enhancement - Add functionality to exclude files that will not be tracked for changes. See [JLS#1847](https://github.com/eclipse/eclipse.jdt.ls/issues/1847). + * bug fix - Some typeComment variables can't be parsed. See [#2052](https://github.com/redhat-developer/vscode-java/issues/2052). + * bug fix - Generate Getters source action is broken from within a record. See [JLS#1392](https://github.com/eclipse/eclipse.jdt.ls/issues/1392). + * bug fix - Java LS sometimes hangs while loading a gradle project. See [#2088](https://github.com/redhat-developer/vscode-java/issues/2088). + * bug fix - java.project.exclusion is not working as expected. See [#2075](https://github.com/redhat-developer/vscode-java/issues/2075). + * bug fix - Fix regression for Gradle project compilation. See [#2071](https://github.com/redhat-developer/vscode-java/issues/2071). + * bug fix - Get correct Java project in multi-module case. See [JLS#1865](https://github.com/eclipse/eclipse.jdt.ls/pull/1865). + * debt - Update target platform to 2021-09 (4.21) Release. See [JLS#1880](https://github.com/eclipse/eclipse.jdt.ls/pull/1880). + * other - Support import from configuration files. See [JLS#1840](https://github.com/eclipse/eclipse.jdt.ls/pull/1840). + * other - Support 3.16 semantic tokens. See [JLS#1678](https://github.com/eclipse/eclipse.jdt.ls/issues/1678). + * other - Remove redundant use of `await` on a return. See [#2100](https://github.com/redhat-developer/vscode-java/pull/2100). + * other - Disable extension in virtual workspaces. See [#1942](https://github.com/redhat-developer/vscode-java/pull/1942). + +## 0.81.0 (August 17th, 2021) + * enhancement - 'Create method' code action for method reference. See [JLS#1464](https://github.com/eclipse/eclipse.jdt.ls/issues/1464). + * enhancement - Show job status via progress notification on start. See [#2022](https://github.com/redhat-developer/vscode-java/pull/2022) + * enhancement - New setting entry to choose project type (Maven or Gradle) when ambiguous. See [#600](https://github.com/redhat-developer/vscode-java/issues/600). + * performance - Avoid displaying (expensive) constant values in completion items. See [JLS#1835](https://github.com/eclipse/eclipse.jdt.ls/issues/1835). + * performance - toURI is expensive on Windows for completions. See [JLS#1831](https://github.com/eclipse/eclipse.jdt.ls/issues/1831). + * bug fix - Go to definition doesn't compute/find results on methods inside an anonymous class. See [JLS#1813](https://github.com/eclipse/eclipse.jdt.ls/issues/1813). + * bug fix - quickfix not available where cursor lands by default on annotations. See [#1992](https://github.com/redhat-developer/vscode-java/issues/1992). + * bug fix - Fix content assist for multiline strings. See [#1811](https://github.com/redhat-developer/vscode-java/issues/1811). + * bug fix - Language server freezes when importing Maven project. See [#2020](https://github.com/redhat-developer/vscode-java/issues/2020). + * bug fix - Suggest correct import quick fix in anonymous classes. See [#2034](https://github.com/redhat-developer/vscode-java/issues/2034). + * bug fix - Organize imports generates duplicate static import statement. See [#2012](https://github.com/redhat-developer/vscode-java/issues/2012). + * bug fix - Do not show the import notification when no projects available. See [#2056](https://github.com/redhat-developer/vscode-java/pull/2056). + * bug fix - Make commands wait for applyEdit. See [#2042](https://github.com/redhat-developer/vscode-java/pull/2042). + * build - Move pull request verification job to GitHub Actions. See [#2031](https://github.com/redhat-developer/vscode-java/pull/2031). + * debt - Update eclipse-jarsigner-plugin to 1.3.2. See [JLS#1829](https://github.com/eclipse/eclipse.jdt.ls/pull/1829). + * debt - Language server distro contains 2 Guava jars. See [JLS#1706](https://github.com/eclipse/eclipse.jdt.ls/issues/1706). + * other - Change the default value of the setting `java.project.importOnFirstTimeStartup` to `automatic`. See [#2014](https://github.com/redhat-developer/vscode-java/issues/2014) + * other - Disable Workspace Trust in test suite runtime. See [#2026](https://github.com/redhat-developer/vscode-java/pull/2026). + * other - Typo in notcoveredexecution.md. See [#2033](https://github.com/redhat-developer/vscode-java/pull/2033). + +## 0.80.0 (June 30th, 2021) + * enhancement - Allow folding `static` blocks. See [JLS#1777](https://github.com/eclipse/eclipse.jdt.ls/issues/1777). + * enhancement - Add deprecated property to CompletionItem and SymbolInformation. See [JLS#695](https://github.com/eclipse/eclipse.jdt.ls/issues/695). + * enhancement - Support Workspace Trust. See [#1926](https://github.com/redhat-developer/vscode-java/issues/1926). + * enhancement - Add option to ignore all proxies. See [#1947](https://github.com/redhat-developer/vscode-java/issues/1947). + * enhancement - Provide fix suggestions for not covered Maven plugin execution in project build lifecycle. See [#1949](https://github.com/redhat-developer/vscode-java/pull/1949). + * bug fix - Cannot make a static reference to the non-static type T. See [JLS#1781](https://github.com/eclipse/eclipse.jdt.ls/issues/1781). + * bug fix - extract method does not seem to like var nor method references. See [#1956](https://github.com/redhat-developer/vscode-java/issues/1956). + * bug fix - "Problem" The method methodName(ParamType) in the type ClassName is not applicable for the arguments () in lightweight syntax only mode. See [#1931](https://github.com/redhat-developer/vscode-java/issues/1931). + * bug fix - Rename to shouldLanguageServerExitOnShutdown extended capability. See [#2008](https://github.com/redhat-developer/vscode-java/pull/2008). + * bug fix - Syntax server no longer exits once JDT server is initialized. See [#1928](https://github.com/redhat-developer/vscode-java/issues/1928). + * bug fix - File contents would be strange when renaming java file name (with lombok). See [JLS#1775](https://github.com/eclipse/eclipse.jdt.ls/issues/1775). + * bug fix - Changes on the profile have no effect if there are backslashes (\\) in the format.settings.url. See [#1944](https://github.com/redhat-developer/vscode-java/issues/1944). + * bug fix - java.project.sourcePaths doesn't refresh diagnostics. See [JLS#1769](https://github.com/eclipse/eclipse.jdt.ls/issues/1769). + * bug fix - wrong status in 'language/progressReport' notification when processing call hierarchy requests. See [JLS#1722](https://github.com/eclipse/eclipse.jdt.ls/issues/1722). + * build - Adjust .vscodeignore filters due to vsce@1.92 update. See [#1983](https://github.com/redhat-developer/vscode-java/pull/1983). + * other - Bump browserslist from 4.16.4 to 4.16.6. See [#1961](https://github.com/redhat-developer/vscode-java/pull/1961). + +## 0.79.2 (May 19th, 2021) + * bug fix - Package name not recognized when opening standalone java files. See [JLS#1764](https://github.com/eclipse/eclipse.jdt.ls/issues/1764). + * bug fix - Force Java Compilation returns error. See [#1929](https://github.com/redhat-developer/vscode-java/issues/1929). + * bug fix - Invalid formatter profile name setting causes errors. See [JLS#1761](https://github.com/eclipse/eclipse.jdt.ls/issues/1761). + * bug fix - Formatter doesn't load format config after update. See [#1917](https://github.com/redhat-developer/vscode-java/issues/1917). + * bug fix - Improve handling of exported settings files. See [#1939](https://github.com/redhat-developer/vscode-java/issues/1939). + * bug fix - A 'keyword' semantic token will sometimes appear when typing an expression. See [#1921](https://github.com/redhat-developer/vscode-java/issues/1921). + * other - Update hosted-git-info dependency. See [#1940](https://github.com/redhat-developer/vscode-java/pull/1940). + * other - Update lodash dependency. See [#1934](https://github.com/redhat-developer/vscode-java/pull/1934). + +## 0.79.1 (May 3rd, 2021) +* bug fix - Formatter doesn't load format config after update. See [#1917](https://github.com/redhat-developer/vscode-java/issues/1917). + +## 0.79.0 (April 29th, 2021) +* enhancement - Update language client to 7.0.0 to adopt LSP 3.16 features (enables lazy code action resolution). See [#1894](https://github.com/redhat-developer/vscode-java/pull/1894). + +## 0.78.0 (April 29th, 2021) + * enhancement - Add Java 16 Support. See [#1891](https://github.com/redhat-developer/vscode-java/pull/1891). + * enhancement - java.project.referencedLibraries should resolve paths leading with ~. See [JLS#1735](https://github.com/eclipse/eclipse.jdt.ls/issues/1735). + * enhancement - Provide support for 3rd party build types (Bazel). See [#1825](https://github.com/redhat-developer/vscode-java/issues/1825). + * enhancement - Add setting to control method declaration lookups in source files. See [#1887](https://github.com/redhat-developer/vscode-java/pull/1887). + * bug fix - Changes to Formatter profiles don‘t take effect in real time. See [JLS#1736](https://github.com/eclipse/eclipse.jdt.ls/issues/1736). + * bug fix - Javadoc overriding methods not inheriting param descriptions. See [JLS#1732](https://github.com/eclipse/eclipse.jdt.ls/issues/1732). + * bug fix - NPE in NewCUProposal.createChange(NewCUProposal.java:277). See [JLS#1723](https://github.com/eclipse/eclipse.jdt.ls/issues/1723). + * bug fix - java.settings.url does not override default java settings. See [JLS#1741](https://github.com/eclipse/eclipse.jdt.ls/issues/1741). + * bug fix - workspaceEdit textDocument version is always 0. See [JLS#1695](https://github.com/eclipse/eclipse.jdt.ls/issues/1695). + * build - Bump ssri from 6.0.1 to 6.0.2. See [#1889](https://github.com/redhat-developer/vscode-java/pull/1889). + +## 0.77.0 (April 15th, 2021) + * enhancement - Refactor when moving files. See [#641](https://github.com/redhat-developer/vscode-java/issues/641). + * enhancement - Support Type Hierarchy. See [#1790](https://github.com/redhat-developer/vscode-java/pull/1790). + * enhancement - Expose source paths setting in VS Code for unmanaged folders. See [#1798](https://github.com/redhat-developer/vscode-java/issues/1798). + * enhancement - Source actions should generate code at cursor location. See [#1346](https://github.com/redhat-developer/vscode-java/issues/1346). + * enhancement - Support String formatting via delegate command. See [JLS#1702](https://github.com/eclipse/eclipse.jdt.ls/pull/1702). + * enhancement - Add more options to query project settings. See [#1828](https://github.com/redhat-developer/vscode-java/pull/1828). + * enhancement - Writing Java in VS CODE shows way too much warnings! See [#1657](https://github.com/redhat-developer/vscode-java/issues/1657). + * enhancement - Enhanced IBuildSupport usage to support other build tools such as bazel. See [JLS#1694](https://github.com/eclipse/eclipse.jdt.ls/pull/1694). + * bug fix - External tool file modifications not registered. See [JLS#1650](https://github.com/eclipse/eclipse.jdt.ls/issues/1650). + * bug fix - Enhance the condition of inline constant. See [JLS#1672](https://github.com/eclipse/eclipse.jdt.ls/pull/1672). + * bug fix - Java code formatter rules is ignored. See [#1640](https://github.com/redhat-developer/vscode-java/issues/1640). + * bug fix - java.format.settings.url no longer loads project .xml file. See [#1827](https://github.com/redhat-developer/vscode-java/issues/1827). + * bug fix - Typo When Trying to Add Folder to Java Source Path That Is Already Included By Parent. See [#1833](https://github.com/redhat-developer/vscode-java/issues/1833). + * bug fix - Set minimum for threshold settings. See [#1868](https://github.com/redhat-developer/vscode-java/pull/1868). + * bug fix - Invisible project forgets source paths on classpath update. See [JLS#1647](https://github.com/eclipse/eclipse.jdt.ls/issues/1647). + * bug fix - Keep getting "Couldn't start client Language Support for Java" when opening a Java file in vscode. See [#1813](https://github.com/redhat-developer/vscode-java/issues/1813). + * bug fix - Disable console.log for lsp trace due to performance issue. See [#1824](https://github.com/redhat-developer/vscode-java/pull/1824). + * build - Update Target Platform to 2021-03 Release. See [JLS#1691](https://github.com/eclipse/eclipse.jdt.ls/pull/1691). + * build - Update lsp4j to 0.11.0. See [JLS#1700](https://github.com/eclipse/eclipse.jdt.ls/pull/1700). + * debt - Build Fails Due to Tests. See [JLS#1646](https://github.com/eclipse/eclipse.jdt.ls/issues/1646). + * debt - Stop generating .gz artifacts during builds. See [JLS#1707](https://github.com/eclipse/eclipse.jdt.ls/issues/1707). + * debt - Java LS Tests fail randomly. See [JLS#1684](https://github.com/eclipse/eclipse.jdt.ls/issues/1684). + * debt - Fix vulnerabilities by 'npm audit fix'. See [#1830](https://github.com/redhat-developer/vscode-java/pull/1830). + * other - Set org.eclipse.jdt.core.compiler.problem.missingSerialVersion to ignore by default. See [JLS#1714](https://github.com/eclipse/eclipse.jdt.ls/issues/1714). + +## 0.76.0 (March 5th, 2021) + * feature - Code actions should return textedits with proper formatting. See [JLS#1157](https://github.com/eclipse/eclipse.jdt.ls/issues/1157). + * bug fix - Surround with try/catch reformats document. See [#1572](https://github.com/redhat-developer/vscode-java/issues/1572). + * bug fix - Change location of .m2/ and .tooling/ from HOME. See [JLS#1654](https://github.com/eclipse/eclipse.jdt.ls/issues/1654). + * bug fix - Issue with 'Go To Definition'. See [JLS#1634](https://github.com/eclipse/eclipse.jdt.ls/issues/1634). + * bug fix - search for enum reference without source. See [#1665](https://github.com/redhat-developer/vscode-java/issues/1665). + * other - Configure whether to show recommendations of external installations. See [#1816](https://github.com/redhat-developer/vscode-java/issues/1816). + * other - Adopt the helpers from jdt.core.manipulation to deal with the CU's preferences. See [JLS#1666](https://github.com/eclipse/eclipse.jdt.ls/pull/1666). + * debt - Upgrade infrastructure to support GLIBCXX 3.4.21. See [#1817](https://github.com/redhat-developer/vscode-java/pull/1817). + * debt - Tests fail on Windows. See [JLS#996](https://github.com/eclipse/eclipse.jdt.ls/issues/996). + +## 0.75.0 (February 11th, 2021) + * enhancement - Specify output path for invisible project. See [#1694](https://github.com/redhat-developer/vscode-java/pull/1694). + * enhancement - Recommend dependency analytics extension. See [#1771](https://github.com/redhat-developer/vscode-java/pull/1771). + * bug fix - @link highlighting broken when linking to class. See [#1753](https://github.com/redhat-developer/vscode-java/issues/1753). + * other - Remove legacy Semantic Highlighting implementation. See [JLS#1649](https://github.com/eclipse/eclipse.jdt.ls/pull/1649). + * other - Make redhat.fabric8-analytics recommendation more compelling. See [#1788](https://github.com/redhat-developer/vscode-java/pull/1788). + * other - use lightweight mode by default when vscode is running from web browsers. See [#1780](https://github.com/redhat-developer/vscode-java/pull/1780). + * other - always exclude project settings files by default. See [#1779](https://github.com/redhat-developer/vscode-java/pull/1779). + * other - Declare semantic token modifiers. See [#1760](https://github.com/redhat-developer/vscode-java/pull/1760). + * other - semantic tokens: use 'method' instead of 'member'. See [#1713](https://github.com/redhat-developer/vscode-java/issues/1713). + +## 0.74.0 (January 20th, 2021) + * enhancement - Download sources for classes in jars with maven coordinates. See [#1664](https://github.com/redhat-developer/vscode-java/issues/1664). + * bug fix - Some refactors are missing when the location has diagnostics. See [JLS#1642](https://github.com/eclipse/eclipse.jdt.ls/issues/1642). + * bug fix - Should not enable preview compiler options if the tooling doesn't support the early access JDK. See [JLS#1644](https://github.com/eclipse/eclipse.jdt.ls/issues/1644). + * bug fix - Importing projects should follow "java.import.exclusions" setting to stop scanning the specified directories. See [#1698](https://github.com/redhat-developer/vscode-java/issues/1698). + * build - Update target platform to use Eclipse 2020-12 Release. See [JLS#1639](https://github.com/eclipse/eclipse.jdt.ls/pull/1639). + * build - Fix some dependency vulnerabilities. See [#1772](https://github.com/redhat-developer/vscode-java/pull/1772). + +## 0.73.0 (December 17th, 2020) + * bug fix - Open a Java file from unmanaged folder, the status bar didn't show language level info. See [#1735](https://github.com/redhat-developer/vscode-java/issues/1735). + * bug fix - Long completionItem/resolve and TimeoutException. See [JLS#1624](https://github.com/eclipse/eclipse.jdt.ls/issues/1624). + * bug fix - Add support to INFO log level. See [JLS#1623](https://github.com/eclipse/eclipse.jdt.ls/pull/1623). + * bug fix - Filter 'sun' packages out of completion type results. See [#1731](https://github.com/redhat-developer/vscode-java/pull/1731). + * bug fix - Dependencies weren't recognized after being added in gradle project. See [#1714](https://github.com/redhat-developer/vscode-java/issues/1714). + * bug fix - Detect Gradle project by settings.gradle as well. See [#1528](https://github.com/redhat-developer/vscode-java/issues/1528). + +## 0.72.0 (December 2nd, 2020) + * enhancement - Support inferSelection when extract to variable. See [#1717](https://github.com/redhat-developer/vscode-java/pull/1717). + * enhancement - Support inferSelection when extract to field. See [#1721](https://github.com/redhat-developer/vscode-java/pull/1721). + * bug fix - jdt.ls distro is 10MB heavier because of com.ibm.icu_64.2.0.v20190507-1337.jar. See [JLS#1351](https://github.com/eclipse/eclipse.jdt.ls/issues/1351). + * bug fix - Java LS crashes on WSL Alpine. See [#1711](https://github.com/redhat-developer/vscode-java/issues/1711). + * bug fix - End of File exception when opening completion in empty file. See [JLS#1611](https://github.com/eclipse/eclipse.jdt.ls/issues/1611). + * other - Update Target Platform to use Eclipse 2020-12 M3. See [JLS#1616](https://github.com/eclipse/eclipse.jdt.ls/pull/1616). + * other - Improve the performance of inferSelection. See [JLS#1609](https://github.com/eclipse/eclipse.jdt.ls/pull/1609). + * other - Allow creation of `abstract class` and `@interface` from "New Java Class" command. See [#1722](https://github.com/redhat-developer/vscode-java/issues/1722). + * other - Spelling error: Update project configuration. See [#1649](https://github.com/redhat-developer/vscode-java/issues/1649). + +## 0.71.0 (November 19th, 2020) + * bug fix - Quarkus: generated sources are not accessible. See [#1675](https://github.com/redhat-developer/vscode-java/issues/1675) + * bug fix - Error in every java file after updating to macOS Big Sur. See [#1700](https://github.com/redhat-developer/vscode-java/issues/1700). + * bug fix - Fix jdk detection: cover symlink folder on Linux. See [#1704](https://github.com/redhat-developer/vscode-java/pull/1704). + * bug fix - Fix jdk detection: cover common JDK installation places on Linux. See [#1706](https://github.com/redhat-developer/vscode-java/pull/1706). + * other - Improve tracing capability of m2e through m2e.logback.configuration. See [JLS#1589](https://github.com/eclipse/eclipse.jdt.ls/pull/1589). + * other - Infer expressions if there is no selection range when extracting method. See [#1680](https://github.com/redhat-developer/vscode-java/pull/1680). + +## 0.70.0 (November 4th, 2020) + * enhancement - Hide inline variable/constant commands when no reference found. See [JLS#1573](https://github.com/eclipse/eclipse.jdt.ls/pull/1573) and [JLS#1575](https://github.com/eclipse/eclipse.jdt.ls/pull/1575). + * enhancement - Convert a lambda expression to method reference. See [#1448](https://github.com/redhat-developer/vscode-java/issues/1448). + * enhancement - Provide method for converting callstack entry to location. See [JLS#1202](https://github.com/eclipse/eclipse.jdt.ls/issues/1202). + * enhancement - Change scope of 'java.home' to machine-overridable. See [#1676](https://github.com/redhat-developer/vscode-java/pull/1676). + * enhancement - Declare semantic token type for modifier keywords. See [#1636](https://github.com/redhat-developer/vscode-java/pull/1636). + * enhancement - Add the java.configuration.maven.globalSettings property. See [#1365](https://github.com/redhat-developer/vscode-java/issues/1365). + * bug fix - GTD is not working if referenced library is updated without file name change. See [JLS#1577](https://github.com/eclipse/eclipse.jdt.ls/issues/1577). + * bug fix - Changing java.semanticHighlighting.enabled does not consistently update semantic tokens. See [JLS#1678](https://github.com/redhat-developer/vscode-java/issues/1678). + * bug fix - Method references are given the CompletionItemKind.Module type by the completion provider. See [#1661](https://github.com/redhat-developer/vscode-java/issues/1661). + * other - Update Target Platform to Eclipse 2020-12 M1. See [JLS#1567](https://github.com/eclipse/eclipse.jdt.ls/issues/1567). + * other - Pass the cancellationtoken to the client request registered by provider. See [#1668](https://github.com/redhat-developer/vscode-java/pull/1668). + +## 0.69.0 (October 15th, 2020) + * enhancement - Embed m2e 1.17. See [JLS#1562](https://github.com/eclipse/eclipse.jdt.ls/pull/1562). + * enhancement - Add code actions to add sealed/final/non-sealed modifier on a permitted type declaration. See [JLS#1555](https://github.com/eclipse/eclipse.jdt.ls/issues/1555). + * enhancement - Created type doesn't implement sealed interface. See [JLS#1553](https://github.com/eclipse/eclipse.jdt.ls/issues/1553). + * enhancement - Improve semantic token modifiers. See [JLS#1539](https://github.com/eclipse/eclipse.jdt.ls/pull/1539). + * enhancement - Find references to fields via getters/setters. See [#1646](https://github.com/redhat-developer/vscode-java/pull/1646). + * bug fix - StringIndexOutOfBoundsException while computing hover and folding range. See [#1644](https://github.com/redhat-developer/vscode-java/issues/1644). + +## 0.68.0 (September 30th, 2020) + * enhancement - JavaFX application produce warning. See [#120](https://github.com/redhat-developer/vscode-java/issues/120). + * enhancement - Add support for JDK 15. See [#1627](https://github.com/redhat-developer/vscode-java/issues/1627). + * enhancement - Embed latest Java textmate grammar. See [#1637](https://github.com/redhat-developer/vscode-java/issues/1637). + * enhancement - Change the code action kind 'Change modifiers to final where possible' to Source Action. See [#1617](https://github.com/redhat-developer/vscode-java/issues/1617). + * enhancement - `java.configuration.runtimes` option configuration error will not prompt an error. See [#1614](https://github.com/redhat-developer/vscode-java/issues/1614). + * enhancement - [Feature Request] Provide more code action options on save. See [#1379](https://github.com/redhat-developer/vscode-java/issues/1379). + * bug fix - Since July update cause java highlight break. See [#1597](https://github.com/redhat-developer/vscode-java/issues/1597). + * bug fix - Corner case in parsing major version of JDK. See [#1331](https://github.com/redhat-developer/vscode-java/issues/1331). + +## 0.67.0 (September 16th, 2020) + * enhancement - Importing mixed (maven,gradle,eclipse) projects. See [#1344](https://github.com/redhat-developer/vscode-java/issues/1344). + * enhancement - Better expose the "Anonymous to nested class" refactoring. See [JLS#1541](https://github.com/eclipse/eclipse.jdt.ls/pull/1541). + * enhancement - [feature request] allow `var` to be fully specified with using 'Show Fixes'. See [#1573](https://github.com/redhat-developer/vscode-java/issues/1573). + * enhancement - Allow devs to override default snippets. See [#1470](https://github.com/redhat-developer/vscode-java/issues/1470). + * bug fix - autocompletion on inherited interface method inserts wrong code. See [#1593](https://github.com/redhat-developer/vscode-java/issues/1593). + * bug fix - Filename extension is .class when saving Untitled file to Java. See [#1618](https://github.com/redhat-developer/vscode-java/issues/1618). + * build - Update TP to use Eclipse 2020-09 RC2. See [JLS#1546](https://github.com/eclipse/eclipse.jdt.ls/pull/1546). + +## 0.66.0 (September 1st, 2020) + * enhancement - new `java.import.resourceFilter` preference to filter folders when refreshing workspace. See [#1460](https://github.com/redhat-developer/vscode-java/issues/1460). + * enhancement - enabled semantic highlighting by default. See [#1584](https://github.com/redhat-developer/vscode-java/pull/1584). + * enhancement - Show a more detailed message about Java 11 requirement. See [#1602](https://github.com/redhat-developer/vscode-java/pull/1602). + * enhancement - Support CancellationToken when calling LSP workspaceCommand. See [#1591](https://github.com/redhat-developer/vscode-java/pull/1591). + * enhancement - Updated to Eclipse 2020-09-M3. See [JLS#1534](https://github.com/eclipse/eclipse.jdt.ls/pull/1534). + * enhancement - Added `,` as signature trigger char. See [JLS#1522](https://github.com/eclipse/eclipse.jdt.ls/pull/1522). + * enhancement - Fixed newline in snippet for new Java files. See [#1564](https://github.com/redhat-developer/vscode-java/issues/1564). + * performance - faster source action resolution. See [JLS#1533](https://github.com/eclipse/eclipse.jdt.ls/pull/1533). + * typo - fixed typo in notification message. See [#1570](https://github.com/redhat-developer/vscode-java/pull/1570). + * typo - fixed Punctuation in import message. See [#1599](https://github.com/redhat-developer/vscode-java/pull/1599). + * bug fix - Document 'Hybrid' serverMode value in api. See [#1586](https://github.com/redhat-developer/vscode-java/pull/1586). + * bug fix - Duplicate snippets displayed in lightweight mode. See [#1579](https://github.com/redhat-developer/vscode-java/issues/1579). + * bug fix - Incorrect semantic tokens for some wildcard import statements. See [#1545](https://github.com/redhat-developer/vscode-java/issues/1545). + * documentation - Remove mention of java.requirements.JDK11Warning from README. See [#1603](https://github.com/redhat-developer/vscode-java/pull/1603). + * build - Add test case for rename file. See [#1574](https://github.com/redhat-developer/vscode-java/pull/1574). + * build - Fixed some vulnerable dependencies. See [#1576](https://github.com/redhat-developer/vscode-java/pull/1576). + * build - Bump elliptic from 6.4.1 to 6.5.3. See [#1554](https://github.com/redhat-developer/vscode-java/pull/1554). + +## 0.65.0 (July 22nd, 2020) + * enhancement - **Require Java 11 to run the extension**. See [#1524](https://github.com/redhat-developer/vscode-java/pull/1524). + * enhancement - Expose the `java.import.gradle.java.home` preference. See [#1536](https://github.com/redhat-developer/vscode-java/issues/1536) & [JLS#1512](https://github.com/eclipse/eclipse.jdt.ls/pull/1512). + * enhancement - Add semantic tokens to class files. See [#1538](https://github.com/redhat-developer/vscode-java/issues/1538). + * enhancement - Adjust the Gradle settings scope to enhance security. See [#1535](https://github.com/redhat-developer/vscode-java/pull/1535). + * enhancement - Tune the user settings about specifying gradle distribution. See [#1534](https://github.com/redhat-developer/vscode-java/pull/1534). + * enhancement - Prevent tab key appending asterisk for import autocompletion. See [#1532](https://github.com/redhat-developer/vscode-java/issues/1532). + * enhancement - Do not show hint when standard server is already activated. See [#1522](https://github.com/redhat-developer/vscode-java/pull/1522). + * enhancement - Add `Introduce Parameter...` code action. See [#1521](https://github.com/redhat-developer/vscode-java/pull/1521). + * enhancement - Semantic highlighting improvements. See [#1488](https://github.com/redhat-developer/vscode-java/issues/1488). + * enhancement - Add Go to Super Implementation to context menu and command palette. See [#1395](https://github.com/redhat-developer/vscode-java/pull/1395). + * enhancement - Support refactoring documentation. See [#1334](https://github.com/redhat-developer/vscode-java/pull/1334). + * bug fix - NPE in CodeActionHandler.getProblemId L.221. See [JLS#1502](https://github.com/eclipse/eclipse.jdt.ls/issues/1502). + * bug fix - fixed Rename from File Explorer. See [#1517](https://github.com/redhat-developer/vscode-java/issues/1517). + * bug fix - Incorrect semantic highlighting for complex constructor invocations. See [#1514](https://github.com/redhat-developer/vscode-java/issues/1514). + * build - Bump lodash from 4.17.15 to 4.17.19. See [#1525](https://github.com/redhat-developer/vscode-java/pull/1525). + +## 0.64.1 (July 8th, 2020) +* bug fix - No response when clicking 'Always' on import. See [#1513](https://github.com/redhat-developer/vscode-java/pull/1513). + +## 0.64.0 (July 7th, 2020) + * enhancement - Give more information in the language level status bar item. See [#1508](https://github.com/redhat-developer/vscode-java/pull/1508). + * enhancement - Register the semantic token provider after standard server is ready. See [#1505](https://github.com/redhat-developer/vscode-java/pull/1505). + * enhancement - Use java:serverMode to avoid conflicts. See [#1504](https://github.com/redhat-developer/vscode-java/pull/1504). + * enhancement - delay resolution of additional text edits. See [#1503](https://github.com/redhat-developer/vscode-java/pull/1503). + * enhancement - Ask users to import projects when opening a new folder. See [#1501](https://github.com/redhat-developer/vscode-java/pull/1501). + * enhancement - Improve Java LS shutdown. See [JLS#1495](https://github.com/eclipse/eclipse.jdt.ls/pull/1495). + * enhancement - Update Buildship to 3.1.5. See [JLS#1494](https://github.com/eclipse/eclipse.jdt.ls/pull/1494). + * bug fix - Unprocessed markdown in settings. See [#1498](https://github.com/redhat-developer/vscode-java/issues/1498). + * bug fix - Gradle 6.4 wrapper incorrectly marked as potentially malicious. See [#1492](https://github.com/redhat-developer/vscode-java/issues/1492). + * bug fix - Prepare rename breaks if you have edited the symbol just before the call. See [JLS#1483](https://github.com/eclipse/eclipse.jdt.ls/issues/1483). + * debt - Decouple the status bar item from each language client to a centralized one. See [#1506](https://github.com/redhat-developer/vscode-java/issues/1506). + * build - npm audit fix. See [#1496](https://github.com/redhat-developer/vscode-java/pull/1496). + +## 0.63.0 (June 18th, 2020) + * enhancement - Avoid unnecessary Gradle re-synch on restart. See [JLS#1485](https://github.com/eclipse/eclipse.jdt.ls/pull/1485). + * enhancement - Optimize default VM management to avoid unnecessary project updates. See [JLS#1484](https://github.com/eclipse/eclipse.jdt.ls/pull/1484). + * enhancement - Update to Eclipse 4.16. See [JLS#1478](https://github.com/eclipse/eclipse.jdt.ls/pull/1478). + * enhancement - Support annotations in semantic highlighting. See [JLS#1477](https://github.com/eclipse/eclipse.jdt.ls/pull/1477). + * enhancement - Wait for jobs to complete when resolving the classpaths. See [JLS#1476](https://github.com/eclipse/eclipse.jdt.ls/pull/1476). + * enhancement - Java runtimes should be configured before projects are imported. See [JLS#1474](https://github.com/eclipse/eclipse.jdt.ls/issues/1474). + * enhancement - Export the public APIs in light weight mode. See [#1480](https://github.com/redhat-developer/vscode-java/issues/1480). + * enhancement - Enable code completion for syntax server. See [#1463](https://github.com/eclipse/eclipse.jdt.ls/pull/1463). + * enhancement - IBuildSupport extension point. See [JLS#1455](https://github.com/eclipse/eclipse.jdt.ls/pull/1455). + * enhancement - Show VM install location on hover. See [#1464](https://github.com/redhat-developer/vscode-java/pull/1464). + * bug fix - Fix NPE in BaseDocumentLifeCycleHandler.publishDiagnostics. See [#1473](https://github.com/eclipse/eclipse.jdt.ls/pull/1473). + * bug fix - Organize import on save should not select ambiguous static import. See [#1459](https://github.com/eclipse/eclipse.jdt.ls/pull/1459). + * bug fix - Link in javadoc causes an error. See [#1437](https://github.com/redhat-developer/vscode-java/issues/1437). + * build - Improve 'launching from source' detection. See [#1473](https://github.com/redhat-developer/vscode-java/pull/1473). + * build - Fix debug mode detection. See [#1467](https://github.com/redhat-developer/vscode-java/pull/1467). + * build - Ignore /node_modules/ when webpack is watching sources. See [#1487](https://github.com/redhat-developer/vscode-java/pull/1487). + +## 0.62.0 (May 21th, 2020) + * enhancement - Expose import projects command. See [#746](https://github.com/redhat-developer/vscode-java/pull/746). + * enhancement - Refactor package name. See [#823](https://github.com/redhat-developer/vscode-java/issues/823). + * enhancement - Provide goToDefinition API . See [#1416](https://github.com/redhat-developer/vscode-java/issues/1416). + * enhancement - Use default JVM when importing gradle project. See [#1426](https://github.com/redhat-developer/vscode-java/issues/1426). + * enhancement - Show Java source level in the status bar. See [#1457](https://github.com/redhat-developer/vscode-java/pull/1457). + * enhancement - Check for suspicious gradle-wrapper.jar +. See [#1440](https://github.com/redhat-developer/vscode-java/pull/1440). + * bug fix - Highlighting is incorrect after imports are automatically inserted. See [#1423](https://github.com/redhat-developer/vscode-java/issues/1423). + * bug fix - Get and Set method generation through intellicode generates javadoc when shouldn't. See [#1411](https://github.com/redhat-developer/vscode-java/issues/1411). + * bug fix - Semantic highlighting doesn't like java.* packages. See [#1434](https://github.com/redhat-developer/vscode-java/issues/1434). + * bug fix - Discard the stale workingcopies that belonged to the deleted folder. See [JLS#1439](https://github.com/eclipse/eclipse.jdt.ls/pull/1439). + +## 0.61.0 (April 30th, 2020) + + * enhancement - organize imports should resolve static imports as well. See [#1386](https://github.com/redhat-developer/vscode-java/issues/1386). + * enhancement - prompt to enable semantic hightlighting on startup. See [#1419](https://github.com/redhat-developer/vscode-java/pull/1419). + * enhancement - refine semantic highlighting. See [JLS#1416](https://github.com/eclipse/eclipse.jdt.ls/pull/1416). + * bug fix - code folding is buggy. See [#1419](https://github.com/eclipse/eclipse.jdt.ls/issues/1419). + * bug fix - New File -> (module|package)-info.java should be handled properly. See [#1405](https://github.com/redhat-developer/vscode-java/issues/1405). + * bug fix - semantic highlighting sometimes looks bad. See [#1396](https://github.com/redhat-developer/vscode-java/issues/1396). + * bug fix - custom color for arguments used in method body. See [#1277](https://github.com/redhat-developer/vscode-java/issues/1277). + * bug fix - missing highlight on some non-ASCII identifiers. See [#826](https://github.com/redhat-developer/vscode-java/issues/826). + * bug fix - syntax highlighting is broken with array syntax. See [#728](https://github.com/redhat-developer/vscode-java/issues/728). + * bug fix - highlighting is wrong. See [#707](https://github.com/redhat-developer/vscode-java/issues/707). + * bug fix - syntax highlighting broken on import containing upper cased letters. See [#351](https://github.com/redhat-developer/vscode-java/issues/351). + * bug fix - syntax highlighting is not working with comment. See [#338](https://github.com/redhat-developer/vscode-java/issues/338). + * bug fix - syntax highlighting is not working on special named classes. See [#299](https://github.com/redhat-developer/vscode-java/issues/299). + +## 0.60.0 (April 16th, 2020) + * enhancement - support semantic tokens. See [#1393](https://github.com/redhat-developer/vscode-java/pull/1393). + * enhancement - preview the updates before applying the changes caused by file rename. See [#1375](https://github.com/redhat-developer/vscode-java/pull/1375). + * enhancement - display a warning about the impending requirement of Java 11 to run the extension. See [#1366](https://github.com/redhat-developer/vscode-java/issues/1366). + * enhancement - organize imports with the asterisk (*) wildcard character. See [#964](https://github.com/redhat-developer/vscode-java/issues/964). + * enhancement - update class name and references when renaming a Java file. See [#1372](https://github.com/redhat-developer/vscode-java/pull/1372). + * enhancement - add "Generate constructor" option in "Show Fixes" options for fields. See [#1358](https://github.com/redhat-developer/vscode-java/issues/1358). + * enhancement - make syntax server support hovering over a type. See [JLS#1403](https://github.com/eclipse/eclipse.jdt.ls/pull/1403). + * bug fix - workspace/notify notification creates no vscode command as expected. See [#1367](https://github.com/redhat-developer/vscode-java/issues/1367). + * bug fix - fix checkJavaVersion for Windows. See [#1360](https://github.com/redhat-developer/vscode-java/pull/1360). + * bug fix - extracted element can not be renamed. See [#1391](https://github.com/redhat-developer/vscode-java/issues/1391). + +## 0.59.1 (April 3rd, 2020) +* enhancement - sort formatter settings. See [#1359](https://github.com/redhat-developer/vscode-java/pull/1359). +* bug fix - fixed failure to start 0.59 in theia 1.0.0/dev - onDidCreateFiles is not a function in workspace. See [#1363](https://github.com/redhat-developer/vscode-java/issues/1363). + +## 0.59.0 (April 1st, 2020) + * enhancement - Enable Java 14 support. See [#1300](https://github.com/redhat-developer/vscode-java/pull/1300). + * enhancement - Support for JDK 14 for Gradle projects. See [#1338](https://github.com/redhat-developer/vscode-java/issues/1338). + * enhancement - Provide `record` snippet. See [JLS#1393](https://github.com/eclipse/eclipse.jdt.ls/issues/1393). + * enhancement - No Javadoc completion for records. See [JLS#1396](https://github.com/eclipse/eclipse.jdt.ls/issues/1396). + * enhancement - Fill in content for newly created files. See [#1222](https://github.com/redhat-developer/vscode-java/issues/1222). + * enhancement - new `java.server.launchMode` to control whether to enable a syntax language server. See [#1329](https://github.com/redhat-developer/vscode-java/pull/1329). + * enhancement - j.i.gradle.arguments and j.i.gradle.jvmArguments aren't properly defined. See [JLS#1387](https://github.com/eclipse/eclipse.jdt.ls/pull/1387). + * enhancement - enable syntax mode when importing a partial folder of maven/gradle project. See [JLS#1364](https://github.com/eclipse/eclipse.jdt.ls/pull/1364). + * enhancement - Add `java.import.gradle.user.home` preference for setting `GRADLE_USER_HOME`. See [#1310](https://github.com/redhat-developer/vscode-java/issues/1310). + * bug fix - root path in the preference manager won't update when workspace folder changes. See [JLS#1388](https://github.com/eclipse/eclipse.jdt.ls/issues/1388). + * bug fix - BadLocationException and diagnostic with negative line number send to client. See [JLS#1374](https://github.com/eclipse/eclipse.jdt.ls/issues/1374). + +## 0.58.0 (March 5th, 2020) +* enhancement - improved support for "standalone file" use cases. See [#1270](https://github.com/redhat-developer/vscode-java/issues/1270). +* enhancement - parallel downloads of jars, for Maven projects. See [JLS#1369](https://github.com/eclipse/eclipse.jdt.ls/pull/1369). +* enhancement - allow renaming of lambda parameters. See [#1298](https://github.com/redhat-developer/vscode-java/issues/1298). +* enhancement - build workspace action can report progress to client. See [JLS#1368](https://github.com/eclipse/eclipse.jdt.ls/pull/1368). +* enhancement - VS Code Java cannot run from read-only location. See [#1301](https://github.com/redhat-developer/vscode-java/issues/1301). +* enhancement - optimize for better memory footprint management. See [#1262](https://github.com/redhat-developer/vscode-java/pull/1262) +* bug fix - fixed error on cancelling source actions. See [#1292](https://github.com/redhat-developer/vscode-java/pull/1292). + +## 0.57.0 (February 19th, 2020) +* bug fix - fixed Gradle project failing to build while fetching non-existing snapshot distro. See [#1285](https://github.com/redhat-developer/vscode-java/issues/1285). +* bug fix - fixed Java suggestion details missing in some circumstances. See [#1258](https://github.com/redhat-developer/vscode-java/issues/1258). + +## 0.56.0 (February 17th, 2020) +* enhancement - added `java.import.gradle.offline.enabled` preference. See [#1157](https://github.com/redhat-developer/vscode-java/issues/1157). +* enhancement - added `java.configuration.runtimes` preference for mapping Java Execution Environments to local JDK runtimes. See [#1207](https://github.com/redhat-developer/vscode-java/pull/1207). +* enhancement - align settings category name with VS Code recommendations. See [#1227](https://github.com/redhat-developer/vscode-java/issues/1227). +* enhancement - added code actions to assign statement to new variable/field. See [#1208](https://github.com/redhat-developer/vscode-java/issues/1208). +* enhancement - added code action to remove redundant interfaces. See [JLS#438](https://github.com/eclipse/eclipse.jdt.ls/issues/438). +* enhancement - added code actions to remove the `final` modifier. See [JLS#441](https://github.com/eclipse/eclipse.jdt.ls/issues/441). +* enhancement - added code action to add missing case labels in switch statements. See [JLS#1140](https://github.com/eclipse/eclipse.jdt.ls/issues/1140). +* bug fix - fixed duplicate labels in progress reports. See [#1230](https://github.com/redhat-developer/vscode-java/issues/1230). +* bug fix - don't set the -noverify flag if JDK >= 13. See [#1250](https://github.com/redhat-developer/vscode-java/pull/1250). +* bug fix - fixed Intellisense not working when attached javadoc can't be read. See [JLS#1314](https://github.com/eclipse/eclipse.jdt.ls/pull/1314). +* bug fix - added default value to `java.project.referencedLibraries`'s exclude and sources. See [JLS#1315](https://github.com/eclipse/eclipse.jdt.ls/pull/1315). + +## 0.55.1 (December 23rd, 2019) +* bug fix - fixed code completion broken with IntelliCode. See [#1213](https://github.com/redhat-developer/vscode-java/issues/1213). + +## 0.55.0 (December 23rd, 2019) +* enhancement - added support for Call Hierarchy. See [#650](https://github.com/redhat-developer/vscode-java/issues/650). +* enhancement - add jars to classpath via new `java.project.referencedLibraries` preference. See [#1196](https://github.com/redhat-developer/vscode-java/pull/1196). +* enhancement - completion results are now limited via `java.completion.maxResults` preference. See [JLS#1298](https://github.com/eclipse/eclipse.jdt.ls/pull/1298). +* enhancement - Remove duplicate call of getRawLocationURI(). See [JLS#1299](https://github.com/eclipse/eclipse.jdt.ls/pull/1299). +* bug fixed - fixed Java Overview breaking the import of invisible projects. See [#1198](https://github.com/redhat-developer/vscode-java/issues/1198). +* bug fixed - fixed build status reporter in multi-root workspaces. See [#1180](https://github.com/redhat-developer/vscode-java/issues/1180). +* bug fixed - fixed incorrect signatures returned by signatureHelp. See [JLS#1290](https://github.com/eclipse/eclipse.jdt.ls/issues/1290). +* bug fixed - fixed broken signatureHelp when previous string parameter has `(` or `{`. See [JLS#1293](https://github.com/eclipse/eclipse.jdt.ls/issues/1293). +* debt - relicensed project to EPL-v2.0. See [commit](https://github.com/redhat-developer/vscode-java/commit/9b0032feb75d07f46231391ae3bf11f53e152a24). + + +## 0.54.2 (December 5th, 2019) +* bug fix - add `java.showBuildStatusOnStart.enabled` setting for revealing build status on startup. See [#1181](https://github.com/redhat-developer/vscode-java/issues/1181). + +## 0.54.1 (December 4th, 2019) +* bug fix - fixed ignored global `java.jdt.ls.vmargs` setting (broke lombok support). See [#1175](https://github.com/redhat-developer/vscode-java/issues/1175). + +## 0.54.0 (December 4th, 2019) +* enhancement - new `java.maven.updateSnapshots` preference to update snapshots/releases for Maven projects. See [#1102](https://github.com/redhat-developer/vscode-java/issues/1102). +* enhancement - jump to definition on break/continue. See [#1145](https://github.com/redhat-developer/vscode-java/issues/1145). +* enhancement - added getDocumentSymbols call to extension API. See [#1151](https://github.com/redhat-developer/vscode-java/pull/1151). +* enhancement - show server tasks in terminal. See [#1153](https://github.com/redhat-developer/vscode-java/pull/1153). +* enhancement - show busy status when there are incomplete tasks. See [#1159](https://github.com/redhat-developer/vscode-java/pull/1159). +* enhancement - always show workspace status in status bar. See [#1163](https://github.com/redhat-developer/vscode-java/pull/1163). +* enhancement - add quickfix to correct access to static elements. See [JLS#439](https://github.com/eclipse/eclipse.jdt.ls/issues/439). +* enhancement - sort code actions by relevance. See [JLS#1250](https://github.com/eclipse/eclipse.jdt.ls/issues/1250). +* enhancement - no need to publish diagnostics in BuildWorkspaceHandler. See [JLS#1282](https://github.com/eclipse/eclipse.jdt.ls/pull/1282). +* bug fix - warn about sensible java preferences in project settings. See [#1154](https://github.com/redhat-developer/vscode-java/issues/1154) and [#1160](https://github.com/redhat-developer/vscode-java/pull/1160). +* bug fix - update problems when changing the name of the package folder. See [#1283](https://github.com/redhat-developer/vscode-java/issues/1152). + +## 0.53.1 (November 15th, 2019) +* bug fix - fixed "Organize Imports" shortcut no longer working. See [#1142](https://github.com/redhat-developer/vscode-java/issues/1142). + +## 0.53.0 (November 14th, 2019) +* enhancement - code action: add 'final' modifier where possible. See [#774](https://github.com/redhat-developer/vscode-java/issues/774). +* enhancement - update m2e to 1.14 (embeds Maven 3.6.2). See [#1103](https://github.com/redhat-developer/vscode-java/issues/1103). +* enhancement - code action: remove unnecessary cast. See [JLS#165](https://github.com/eclipse/eclipse.jdt.ls/issues/165). +* enhancement - provide better symbol details on hover. See [JLS#1227](https://github.com/eclipse/eclipse.jdt.ls/issues/1227). +* enhancement - code action: improve "Invert Condition" refactoring trigger. See [JLS#1230](https://github.com/eclipse/eclipse.jdt.ls/issues/1230). +* enhancement - refresh the extension bundles after uninstalling. See [JLS#1253](https://github.com/eclipse/eclipse.jdt.ls/pull/1253). +* bug fixed - fixed Maven import failure caused by m2e-apt unable to parse maven-compiler-plugin configuration. See [#1131](https://github.com/redhat-developer/vscode-java/issues/1131). +* bug fixed - add Java 13 support for Gradle projects. See [JLS#1196](https://github.com/eclipse/eclipse.jdt.ls/issues/1196). +* bug fixed - fixed errors reported from unrelated gradle projects outside the workspace. See [JLS#1261](https://github.com/eclipse/eclipse.jdt.ls/issues/1261). + +## 0.52.0 (October 23rd, 2019) +* enhancement - define schema for `contribute/javaExtensions` in package.json. See [#1114](https://github.com/redhat-developer/vscode-java/pull/1114). +* enhancement - add text selection support in code snippet. see [JLS#1222](https://github.com/eclipse/eclipse.jdt.ls/pull/1222). +* enhancement - unused imports displayed as faded. See [JLS#1219](https://github.com/eclipse/eclipse.jdt.ls/issues/1219). +* bug fix - fixed pasting with multi-cursor. See [#1112](https://github.com/redhat-developer/vscode-java/issues/1112). +* bug fix - organize imports on paste moved to a specific command (`ctrl+shift+v` - `cmd+shift+v` on Mac). Removed `java.actionsOnPaste.organizeImports` preference. See [#1115](https://github.com/redhat-developer/vscode-java/issues/1115). +* documentation - fixed broken link in CONTRIBUTING.md. See [#1105](https://github.com/redhat-developer/vscode-java/pull/1105) + +## 0.51.0 (October 16th, 2019) +* enhancement - [experimental] automatically trigger auto-import on paste. Can be disabled with `java.actionsOnPaste.organizeImports`. See [#1075](https://github.com/redhat-developer/vscode-java/issues/1075) and [#1098](https://github.com/redhat-developer/vscode-java/issues/1098). +* enhancement - allow negative patterns in `java.import.exclusions` preference, to allow folder inclusions. See [#1084](https://github.com/redhat-developer/vscode-java/issues/1084). +* enhancement - made code snippets context sensitive. See [JLS#977](https://github.com/eclipse/eclipse.jdt.ls/issues/977). +* enhancement - improve snippet documentation rendering. See [JLS#1205](https://github.com/eclipse/eclipse.jdt.ls/issues/1205). +* bug fix - fixed preview features enabled at an invalid source release level 12, preview can be enabled only at source level 13. See [#1086](https://github.com/redhat-developer/vscode-java/issues/1086). +* bug fix - don't return workspace symbols without a name. See [JLS#1204](https://github.com/eclipse/eclipse.jdt.ls/issues/1204). +* bug fix - fixed package fragments not updated when adding a new folder. See [JLS#1137](https://github.com/eclipse/eclipse.jdt.ls/issues/1137). +* bug fix - don't filter method completions from filtered types. See [JLS#1212](https://github.com/eclipse/eclipse.jdt.ls/issues/1212). + +## 0.50.0 (October 1st, 2019) +* enhancement - added Java 13 support for Maven and Eclipse projects. See [JLS#1179](https://github.com/eclipse/eclipse.jdt.ls/issues/1179). +* enhancement - added support for diagnostic tags. See [#1051](https://github.com/redhat-developer/vscode-java/pull/1051). +* enhancement - code-action: fixed methods with reduced visibility. See [JLS#442](https://github.com/eclipse/eclipse.jdt.ls/issues/442). +* enhancement - code-action: inline method/variable/field. See [JLS#656](https://github.com/eclipse/eclipse.jdt.ls/issues/656) and [JLS#771](https://github.com/eclipse/eclipse.jdt.ls/issues/771). +* enhancement - provide more granularity of progress during Maven import. See [JLS#1121](https://github.com/eclipse/eclipse.jdt.ls/issues/1121). +* enhancement - update Buildship to 3.1.2. See [JLS#1195](https://github.com/eclipse/eclipse.jdt.ls/pulls/1195). +* bug - fixed wrong range for `Surround with try/multi-catch` code action. See [JLS#1189](https://github.com/eclipse/eclipse.jdt.ls/issues/1189). + +## 0.49.0 (September 18th, 2019) +* enhancement - navigate to the super implementation. See [#553](https://github.com/redhat-developer/vscode-java/issues/553). +* enhancement - exclude certain packages from autocomplete/autoimport. See [#710](https://github.com/redhat-developer/vscode-java/issues/710). +* enhancement - code action: create non existing package when package declaration mismatch. See [#1030](https://github.com/redhat-developer/vscode-java/issues/1030). +* enhancement - code action: convert anonymous class to nested class. See [#1060](https://github.com/redhat-developer/vscode-java/pull/1060). +* enhancement - code action: fix non accessible references. See [JLS#440](https://github.com/eclipse/eclipse.jdt.ls/issues/440). +* enhancement - code action: convert for-loop to for-each loop. See [JLS#1166](https://github.com/eclipse/eclipse.jdt.ls/issues/1166). +* enhancement - use `vscode.env.appName` instead of hardcoding `VS Code`. See [#1066](https://github.com/redhat-developer/vscode-java/issues/1066). +* bug fix - fixed tables not properly rendered on Javadoc hover. See [#1002](https://github.com/redhat-developer/vscode-java/issues/1002). +* bug fix - extract embedded javadoc images. See [#1007](https://github.com/redhat-developer/vscode-java/issues/1007). +* bug fix - fixed extension never reaching the ready state (always spin). See [#1056](https://github.com/redhat-developer/vscode-java/issues/1056). +* bug fix - fixed wrong completion text for AnonymousDeclarationType. See [JLS#1168](https://github.com/eclipse/eclipse.jdt.ls/issues/1168). +* bug fix - fixed "No delegateCommandHandler for 'xxx'" error. See [JLS#1146](https://github.com/eclipse/eclipse.jdt.ls/issues/1146). +* bug fix - load bundle only once if same bundle occurs multiple times in different locations. See [JLS#1174](https://github.com/eclipse/eclipse.jdt.ls/pull/1174). +* bug fix - fixed incorrect `prepareRename` response when called over import. See [JLS#1175](https://github.com/eclipse/eclipse.jdt.ls/issues/1175). +* documentation - update CONTRIBUTING.md with images for setting up server and remote debugging. See [#1037](https://github.com/redhat-developer/vscode-java/pull/1037). + +## 0.48.0 (September 4th, 2019) +* enhancement - ignore "Unsupported SuppressWarning" warnings by default. See [#507](https://github.com/redhat-developer/vscode-java/issues/507). +* enhancement - code action to move member to another class. See [#980](https://github.com/redhat-developer/vscode-java/issues/980). +* enhancement - code action to move class to another package. See [#1017](https://github.com/redhat-developer/vscode-java/issues/1017). +* enhancement - code action to move inner types to new class. See [#1027](https://github.com/redhat-developer/vscode-java/pull/1027). +* enhancement - code action to 'Invert local variable'. See [#997](https://github.com/redhat-developer/vscode-java/pull/997). +* enhancement - show client & server logs side by side. See [#1016](https://github.com/redhat-developer/vscode-java/issues/1016). +* enhancement - rotate client logs daily. See [#989](https://github.com/redhat-developer/vscode-java/pull/989). +* enhancement - log language client failures. See [#1015](https://github.com/redhat-developer/vscode-java/pull/1015). +* enhancement - code action to create unresolved types. See [JLS#853](https://github.com/eclipse/eclipse.jdt.ls/issues/853). +* enhancement - properly render @ApiNote in javadoc. See [JLS#1069](https://github.com/eclipse/eclipse.jdt.ls/issues/1069). +* enhancement - code action to convert lambda to anonymous class. See [JLS#1119](https://github.com/eclipse/eclipse.jdt.ls/issues/1119). +* bug fix - fixed "Java runtime could not be located" for Windows + Oracle JDK. See [#836](https://github.com/redhat-developer/vscode-java/issues/836). +* bug fix - fixed go to implementation doesn't work for method invocation. See [#886](https://github.com/redhat-developer/vscode-java/issues/886). +* bug fix - fixed find implementation doesn't work on classes. See [JLS#1098](https://github.com/eclipse/eclipse.jdt.ls/issues/1098). +* bug fix - fixed NavigateToDefinitionHandler should not return null. See [JLS#1143](https://github.com/eclipse/eclipse.jdt.ls/pull/1143). +* bug fix - fixed secondary same-line error not reported. See [JLS#1147](https://github.com/eclipse/eclipse.jdt.ls/issues/1147). + +## 0.47.0 (July 18th, 2019) +* enhancement - trigger client autorename after 'extract to variable/constant/method'. See [#333](https://github.com/redhat-developer/vscode-java/issues/333). +* enhancement - added support for semantic selection. See [#780](https://github.com/redhat-developer/vscode-java/issues/780). +* enhancement - Maven projects use the latest Execution Environment when source/target is not yet supported. See [#951](https://github.com/redhat-developer/vscode-java/issues/951). +* enhancement - added code action to convert a local variable to a field. See [#971](https://github.com/redhat-developer/vscode-java/pull/971). +* enhancement - added additional Gradle preferences. See [#973](https://github.com/redhat-developer/vscode-java/pull/973). +* enhancement - added new command to open the Java extension log. See [#985](https://github.com/redhat-developer/vscode-java/issues/985). +* enhancement - prevented aggressive classpath updates when jars don't change. See [JLS#1078](https://github.com/eclipse/eclipse.jdt.ls/pull/1078). +* enhancement - new extension point to register static commands during JDT LS initialization . See [JLS#1084](https://github.com/eclipse/eclipse.jdt.ls/issues/1084). +* bug fix - fixed "Extract Variable" returning a wrong cursor position. See [#952](https://github.com/redhat-developer/vscode-java/issues/952). +* bug fix - use the default `GRADLE_USER_HOME` env var if possible, for Gradle wrappers and modules. See [JLS#1072](https://github.com/eclipse/eclipse.jdt.ls/pull/1072). +* bug fix - fixed signature help returning the wrong active parameter. See [JLS#1039](https://github.com/eclipse/eclipse.jdt.ls/issues/1039). +* bug fix - fixed signature help stopped working after using a lambda. See [JLS#1086](https://github.com/eclipse/eclipse.jdt.ls/issues/1086). +* debt - replaced vscode package with @types/vscode. See [#977](https://github.com/redhat-developer/vscode-java/issues/977). +* documentation - setup the project for development. See [#949](https://github.com/redhat-developer/vscode-java/issues/949). + ## 0.46.0 (June 5th, 2019) * enhancement - new 'try with resources' snippet, triggered by `try_resources`. See [#932](https://github.com/redhat-developer/vscode-java/pull/932). * enhancement - new 'private field' snippet, triggered by `prf`. See [#933](https://github.com/redhat-developer/vscode-java/pull/933). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2dba414564..e63a1b05d3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,67 +11,181 @@ vscode-java is a Visual Studio Code extension that uses a language server for it smartness. Usually vscode-java features depend on the [Eclipse ™ JDT Language Server](https://github.com/eclipse/eclipse.jdt.ls), (a.k.a. eclipse.jdt.ls) and the contributions should be coordinated between the two repositories. -## First Time Setup -1. Install prerequisites: +# + +## Background Info + +For the whole language server to get up and running it requires +two parts. + + **A)** The Client Side (this repo): [VSCode Java](https://github.com/redhat-developer/vscode-java) + +**B)** The Server Side: [JDT LS](https://github.com/eclipse/eclipse.jdt.ls) + +# + +## Complete Setup Guide + +The following will be a start to finish guide to get the entire language server up and running. + +# + +## **A)** Client Side Setup + +1. Install the required software: * latest [Visual Studio Code](https://code.visualstudio.com/) - * [Node.js](https://nodejs.org/) v4.0.0 or higher -2. Fork and clone the repository + * [Node.js](https://nodejs.org/) v18.17.1 (with npm 9.6.7) or higher +2. Fork and clone [this repository](https://github.com/redhat-developer/vscode-java) + + Keep in mind the final directories will look like: + + ``` + PROJECT_FOLDER/ + | + |--- vscode-java/ + |--- eclipse.jdt.ls/ + + ``` + + 3. `cd vscode-java` 4. Install the dependencies: ```bash $ npm install ``` -5. Open the folder in VS Code +5. (**\*Optional**) Build a platform specific JRE: -## Building Eclipse ™ JDT Language Server + ```bash + $ npm run download-jre + ``` + You can also use the options `--target` and `--javaVersion` to build the specified JRE version for the specified target architecture. + +# + +## **B)** Server Side Setup This assumes that you are starting on the `vscode-java` directory 1. `cd ..` 2. Fork and clone the [eclipse.jdt.ls](https://github.com/eclipse/eclipse.jdt.ls) repository + + Ensure the directory looks like: + ``` + PROJECT_FOLDER/ + | + |--- vscode-java/ + |--- eclipse.jdt.ls/ + + ``` 3. Build server ```bash - $ cd ..\vscode-java - $ npm run build-server + $ cd ./vscode-java + $ npm run build ``` -You can run faster server builds during development by calling `./node_modules/.bin/gulp dev_server` script instead, this will build server binaries that are required by your host OS only. You can also use `npm run watch-server` which will build and place them on the extension for Java changes. These commands run Maven in offline mode, so you might need to run `build-server` at least once, to fetch all the dependencies. +If the eclipse.jdt.ls directory is not found as a sibling directory (see the desired hierarchy in the previous step), a snapshot of the language server will be downloaded instead. + +To build the server using only the local eclipse.jdt.ls repository, use `npm run build-server`. + +**\*Optional:** +You can run faster server builds during development by calling `npm run fast-build-server` script instead, this will build server binaries that are required by your host OS only. You can also use `npm run watch-server` which will build and place them on the extension for Java changes. These commands run Maven in offline mode, so you might need to run `build-server` at least once, to fetch all the dependencies. This will build and place the binaries under the `server` folder. Alternately you can download and use the latest snapshot build from [Eclipse ™ JDT Language Server](https://github.com/eclipse/eclipse.jdt.ls) project with the following - ```bash - $ cd ..\vscode-java - $ ./node_modules/.bin/gulp download_server - ``` +```bash +$ cd ../vscode-java +$ npm run download-server +``` +### Setting up the JDT Language Server +Below are the details about how to set up the JDT Language Server in different IDEs. **Notice**: You only need set up it once in any of your preferred IDE. -## Run with a remote JDT language server +### B-1) Setting up the JDT Language Server in VS Code +1) Please install [Eclipse PDE support](https://marketplace.visualstudio.com/items?itemName=yaozheng.vscode-pde) extension in your VS Code first. The PDE extension's home page provides more usage details about _Reload Target Platform_, _Run JUnit Plug-in Test_, _Run Eclipse Application_. -While developing the language server and the extension, you don't need to deploy the server every time to try out changes. Instead you can run the language server out of its Eclipse workspace: +2) Open VS Code on the `eclipse.jdt.ls` folder. The PDE extension will work with Java extension together to automatically load the eclipse.jdt.ls project. Check the status of the language tools on the lower right corner. It should show ready (thumbs up) as the image below. + ![status indicator](images/statusMarker.png) -### _Launch Extension - Remote Server_ +### B-2) Setting up the JDT Language Server in Eclipse +1) In Eclipse, import a maven project: -- Open VSCode on the `vscode-java` folder -- In the debug viewlet, run the launch _Launch Extension - Remote Server_ -- The extension will open a socket on port 3333 and will wait for the JDT language server to connect -- In Eclipse, run the JDT language server as an Eclipse application. - - Create a debug configuration of type _Eclipse Application_. - - in the main tab of the debug configuration set the product to `org.eclipse.jdt.ls.core.product`. - - in the Environment tab, define a variable `CLIENT_PORT` with value `3333`. - - if your workspace contains 'org.eclipse.jdt.ui', use the Plug-Ins tab in the debug configuration to exclude the plug-in. The presence of 'org.eclipse.jdt.ui' will cause the language server to hang. - - You can also use the `jdt.ls.remote.server` launch configuration. + ![Import Project](images/changelog/importProject.png) + + ![Import Project](images/changelog/importMavenProject.png) + + Select the `eclipse.jdt.ls` folder, then click yes/accept to all +following prompts: + + ![Import Project](images/changelog/importedMavenProject.png) + +2) Now we need to use Tycho to download the dependencies, +this will get rid of the errors. + + At the top right arrow it will say `Set Target Platform`, select that and continue. + + ![Import Project](images/changelog/setTargetPlatform.png) + + After it will change to `Reload Target Platform` select that: + + ![Import Project](images/changelog/reloadTargetPlatform.png) + +3) Wait till the bottom right is done loading: + + ![Import Project](images/changelog/loadingTargetPlatform.png) + + once 100%: + + + + The errors should now be gone. + +# +# Running Everything + +## **C)** Run with a remote JDT language server + +While developing the language server and the extension, you don't need to deploy the server every time to try out changes. Instead you can run the language server out of its Eclipse workspace. Currently we provide two kinds of connection modes between the extension and the language server. +## **C-1)** The extension opens the connection first, and waits the language server to connect to it. +### a) _Launch Extension - Client Side_ + +1. Open VSCode on the `vscode-java` folder + +2. In the debug viewlet, run the launch _Launch Extension - Remote Server_ +![Remote Server](images/changelog/RemoteServer.png) + +3. The extension will open a socket on port 3333 and will wait for the JDT language server to connect + +### b) _Launch Debug Server - Server Side_ + +- With the client side **(vscode-java) running**, you can start the remote server in your preferred IDE. + - Start the remote server via VS Code. + ![Remote Server In VS Code](images/changelog/RemoteServerInVSCode.png) + + - Start the remote server via Eclipse. + ![Remote Server In Eclipse](images/changelog/DebugRemoteServer.png) - In the debug console of VSCode you can see if the connection was successful. - When the server is running breakpoints can be reached and hot code replace can be used to make fixes without restarting the server. - You can modify `launch.json` to use a different port: - - Modify `SERVER_PORT` to specify the port the JDT LS server should connect to. + - Modify `JDTLS_SERVER_PORT` to specify the port the JDT LS server should connect to. -### _Launch Extension - JDTLS Client_ +## C-2) The language server opens the connection first, and waits the extension to connect to it. +- Start the language server via `jdt.ls.socket-stream` launch configuration in VS Code or Eclipse + ![Socket Steam in VS Code](images/changelog/SocketSteamInVSCode.png) -- start the `jdt.ls.socket-stream` launch configuration in Eclipse -- start the _Launch Extension - JDTLS Client_ in VS Code +- Start the extension via _Launch Extension - JDTLS Client_ in VS Code - You can modify `launch.json` to use a different port: - Modify `JDTLS_CLIENT_PORT` to specify the port VS Code should connect to. +## C-3) Set location to a local copy of JDT-LS + +This approach is mainly targeting developers of JDT-LS who want to test their changes in VSCode without having to rebuild vscode-java and to deal with the npm and vsix toolchains. + +- Make sure a recent snapshot of vscode-java is installed in your VSCode instance (as of vscode-java 1.20.0) +- (Optionally) clear the workspace state: `$ rm -r $HOME/.config/Code/User/workspaceStorage/0123456789abcdef01234567890abcdef/redhat.java/jdt_ws` +- Start VSCode with the `JDT_LS_PATH` environment variable set to the local copy of JDT-LS you want to try: `$ JDT_LS_PATH=$HOME/git/eclipse.jdt.ls/org.eclipse.jdt.ls.product/target/repository code` + +Most other options such as `DEBUG_VSCODE_JAVA` are still usable with this approach. + ## Sideloading You can create a binary that you can sideload to your VS Code installation. @@ -84,11 +198,18 @@ You can create a binary that you can sideload to your VS Code installation. $ npm install ``` 4. Optionally, follow the instruction to build the server. -5. See documentation on [extension installation](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensions/publish-extension.md) +5. See documentation on [extension installation](https://github.com/microsoft/vscode-docs/blob/main/api/working-with-extensions/publishing-extension.md) on ways to sideload or share. # Reporting issues If you encounter a problem and know it is caused by eclipse.jdt.ls, then please open a bug report over [there](https://github.com/eclipse/eclipse.jdt.ls/issues). In doubt, you can report issues in the [vscode-java issue tracker](https://github.com/redhat-developer/vscode-java/issues). -Try to collect as much informations as you can to describe the issue and help us reproduce the problem. Head over to the [troubleshooting page](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting#enable-logging) to see how to collect useful logging informations. +Try to collect as much information as you can to describe the issue and help us reproduce the problem. Head over to the [troubleshooting page](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting#enable-logging) to see how to collect useful logging information. + +### Certificate of Origin + +By contributing to this project you agree to the Developer Certificate of +Origin (DCO). This document was created by the Linux Kernel community and is a +simple statement that you, as a contributor, have the legal right to make the +contribution. See the [DCO](DCO) file for details. diff --git a/DCO b/DCO new file mode 100644 index 0000000000..8201f99215 --- /dev/null +++ b/DCO @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index c055910308..0000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env groovy - -def installBuildRequirements(){ - def nodeHome = tool 'nodejs-10.9.0' - env.PATH="${env.PATH}:${nodeHome}/bin" - sh "npm install -g typescript" - sh "npm install -g vsce" -} - -def buildVscodeExtension(){ - sh "npm install" - sh "npm run vscode:prepublish" -} - -node('rhel7'){ - stage 'Build JDT LS' - - env.JAVA_HOME="${tool 'openjdk-1.8'}" - env.PATH="${env.JAVA_HOME}/bin:${env.PATH}" - sh 'java -version' - - git url: 'https://github.com/eclipse/eclipse.jdt.ls.git' - sh "./mvnw clean verify -B -U -e -Pserver-distro -Dtycho.disableP2Mirrors=true -DskipTests -P!jboss-maven-repos,!redhat-ga-repository,!redhat-ea-repository" - - def files = findFiles(glob: '**/org.eclipse.jdt.ls.product/distro/**.tar.gz') - stash name: 'server_distro', includes :files[0].path -} - -node('rhel7'){ - stage 'Checkout vscode-java code' - deleteDir() - git url: 'https://github.com/redhat-developer/vscode-java.git' - - stage 'install vscode-java build requirements' - installBuildRequirements() - - stage 'Build vscode-java' - buildVscodeExtension() - unstash 'server_distro' - def files = findFiles(glob: '**/org.eclipse.jdt.ls.product/distro/**.tar.gz') - sh "rm -rf ./out" - sh "mkdir ./server" - sh "tar -xvzf ${files[0].path} -C ./server" - - stage "Package vscode-java" - def packageJson = readJSON file: 'package.json' - sh "vsce package -o java-${packageJson.version}-${env.BUILD_NUMBER}.vsix" - - stage 'Test vscode-java for staging' - wrap([$class: 'Xvnc']) { - sh "npm run compile" //compile the test code too - sh "npm test --silent" - } - - stage 'Upload vscode-java to staging' - def vsix = findFiles(glob: '**.vsix') - sh "rsync -Pzrlt --rsh=ssh --protocol=28 ${vsix[0].path} ${UPLOAD_LOCATION}/jdt.ls/staging" - stash name:'vsix', includes:files[0].path -} - -node('rhel7'){ - if(publishToMarketPlace.equals('true')){ - timeout(time:5, unit:'DAYS') { - input message:'Approve deployment?', submitter: 'fbricon' - } - - stage "Publish to Marketplace" - unstash 'vsix' - withCredentials([[$class: 'StringBinding', credentialsId: 'vscode_java_marketplace', variable: 'TOKEN']]) { - def vsix = findFiles(glob: '**.vsix') - sh 'vsce publish -p ${TOKEN} --packagePath' + " ${vsix[0].path}" - } - archive includes:"**.vsix" - - stage "Publish to http://download.jboss.org/jbosstools/static/jdt.ls/stable/" - // copy this stable build to Akamai-mirrored /static/ URL, so staging can be cleaned out more easily - def vsix = findFiles(glob: '**.vsix') - sh "rsync -Pzrlt --rsh=ssh --protocol=28 ${vsix[0].path} ${UPLOAD_LOCATION}/static/jdt.ls/stable/" - }// if publishToMarketPlace -} diff --git a/LICENSE b/LICENSE index 5032843775..e55f34467e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,203 +1,277 @@ -Eclipse Public License - v 1.0 +Eclipse Public License - v 2.0 -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC -LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM -CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: -a) in the case of the initial Contributor, the initial code and documentation - distributed under this Agreement, and -b) in the case of each subsequent Contributor: - i) changes to the Program, and - ii) additions to the Program; + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and - where such changes and/or additions to the Program originate from and are - distributed by that particular Contributor. A Contribution 'originates' - from a Contributor if it was added to the Program by such Contributor - itself or anyone acting on such Contributor's behalf. Contributions do not - include additions to the Program which: (i) are separate modules of - software distributed in conjunction with the Program under their own - license agreement, and (ii) are not derivative works of the Program. + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. -"Contributor" means any person or entity that distributes the Program. +"Contributor" means any person or entity that Distributes the Program. -"Licensed Patents" mean patent claims licensable by a Contributor which are -necessarily infringed by the use or sale of its Contribution alone or when -combined with the Program. +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. -"Program" means the Contributions distributed in accordance with this +"Program" means the Contributions Distributed in accordance with this Agreement. -"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors. +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. 2. GRANT OF RIGHTS - a) Subject to the terms of this Agreement, each Contributor hereby grants - Recipient a non-exclusive, worldwide, royalty-free copyright license to - reproduce, prepare derivative works of, publicly display, publicly - perform, distribute and sublicense the Contribution of such Contributor, - if any, and such derivative works, in source code and object code form. - b) Subject to the terms of this Agreement, each Contributor hereby grants - Recipient a non-exclusive, worldwide, royalty-free patent license under - Licensed Patents to make, use, sell, offer to sell, import and otherwise - transfer the Contribution of such Contributor, if any, in source code and - object code form. This patent license shall apply to the combination of - the Contribution and the Program if, at the time the Contribution is - added by the Contributor, such addition of the Contribution causes such - combination to be covered by the Licensed Patents. The patent license - shall not apply to any other combinations which include the Contribution. - No hardware per se is licensed hereunder. - c) Recipient understands that although each Contributor grants the licenses - to its Contributions set forth herein, no assurances are provided by any - Contributor that the Program does not infringe the patent or other - intellectual property rights of any other entity. Each Contributor - disclaims any liability to Recipient for claims brought by any other - entity based on infringement of intellectual property rights or - otherwise. As a condition to exercising the rights and licenses granted - hereunder, each Recipient hereby assumes sole responsibility to secure - any other intellectual property rights needed, if any. For example, if a - third party patent license is required to allow Recipient to distribute - the Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - d) Each Contributor represents that to its knowledge it has sufficient - copyright rights in its Contribution, if any, to grant the copyright - license set forth in this Agreement. + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). 3. REQUIREMENTS -A Contributor may choose to distribute the Program in object code form under -its own license agreement, provided that: - - a) it complies with the terms and conditions of this Agreement; and - b) its license agreement: - i) effectively disclaims on behalf of all Contributors all warranties - and conditions, express and implied, including warranties or - conditions of title and non-infringement, and implied warranties or - conditions of merchantability and fitness for a particular purpose; - ii) effectively excludes on behalf of all Contributors all liability for - damages, including direct, indirect, special, incidental and - consequential damages, such as lost profits; - iii) states that any provisions which differ from this Agreement are - offered by that Contributor alone and not by any other party; and - iv) states that source code for the Program is available from such - Contributor, and informs licensees how to obtain it in a reasonable - manner on or through a medium customarily used for software exchange. - -When the Program is made available in source code form: - - a) it must be made available under this Agreement; and - b) a copy of this Agreement must be included with each copy of the Program. - Contributors may not remove or alter any copyright notices contained - within the Program. - -Each Contributor must identify itself as the originator of its Contribution, -if -any, in a manner that reasonably allows subsequent Recipients to identify the -originator of the Contribution. +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. 4. COMMERCIAL DISTRIBUTION -Commercial distributors of software may accept certain responsibilities with -respect to end users, business partners and the like. While this license is -intended to facilitate the commercial use of the Program, the Contributor who -includes the Program in a commercial product offering should do so in a manner -which does not create potential liability for other Contributors. Therefore, -if a Contributor includes the Program in a commercial product offering, such -Contributor ("Commercial Contributor") hereby agrees to defend and indemnify -every other Contributor ("Indemnified Contributor") against any losses, -damages and costs (collectively "Losses") arising from claims, lawsuits and -other legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such Commercial -Contributor in connection with its distribution of the Program in a commercial -product offering. The obligations in this section do not apply to any claims -or Losses relating to any actual or alleged intellectual property -infringement. In order to qualify, an Indemnified Contributor must: -a) promptly notify the Commercial Contributor in writing of such claim, and -b) allow the Commercial Contributor to control, and cooperate with the -Commercial Contributor in, the defense and any related settlement -negotiations. The Indemnified Contributor may participate in any such claim at -its own expense. - -For example, a Contributor might include the Program in a commercial product -offering, Product X. That Contributor is then a Commercial Contributor. If -that Commercial Contributor then makes performance claims, or offers -warranties related to Product X, those performance claims and warranties are -such Commercial Contributor's responsibility alone. Under this section, the -Commercial Contributor would have to defend claims against the other -Contributors related to those performance claims and warranties, and if a -court requires any other Contributor to pay any damages as a result, the -Commercial Contributor must pay those damages. +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. 5. NO WARRANTY -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each -Recipient is solely responsible for determining the appropriateness of using -and distributing the Program and assumes all risks associated with its -exercise of rights under this Agreement , including but not limited to the -risks and costs of program errors, compliance with applicable laws, damage to -or loss of data, programs or equipment, and unavailability or interruption of -operations. +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY -CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION -LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGES. +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of the -remainder of the terms of this Agreement, and without further action by the -parties hereto, such provision shall be reformed to the minimum extent -necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Program itself -(excluding combinations of the Program with other software or hardware) -infringes such Recipient's patent(s), then such Recipient's rights granted -under Section 2(b) shall terminate as of the date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it fails to -comply with any of the material terms or conditions of this Agreement and does -not cure such failure in a reasonable period of time after becoming aware of -such noncompliance. If all Recipient's rights under this Agreement terminate, -Recipient agrees to cease use and distribution of the Program as soon as -reasonably practicable. However, Recipient's obligations under this Agreement -and any licenses granted by Recipient relating to the Program shall continue -and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, but in -order to avoid inconsistency the Agreement is copyrighted and may only be -modified in the following manner. The Agreement Steward reserves the right to -publish new versions (including revisions) of this Agreement from time to -time. No one other than the Agreement Steward has the right to modify this -Agreement. The Eclipse Foundation is the initial Agreement Steward. The -Eclipse Foundation may assign the responsibility to serve as the Agreement -Steward to a suitable separate entity. Each new version of the Agreement will -be given a distinguishing version number. The Program (including -Contributions) may always be distributed subject to the version of the -Agreement under which it was received. In addition, after a new version of the -Agreement is published, Contributor may elect to distribute the Program -(including its Contributions) under the new version. Except as expressly -stated in Sections 2(a) and 2(b) above, Recipient receives no rights or -licenses to the intellectual property of any Contributor under this Agreement, -whether expressly, by implication, estoppel or otherwise. All rights in the -Program not expressly granted under this Agreement are reserved. - -This Agreement is governed by the laws of the State of New York and the -intellectual property laws of the United States of America. No party to this -Agreement will bring a legal action under this Agreement more than one year -after the cause of action arose. Each party waives its rights to a jury trial in -any resulting litigation. \ No newline at end of file +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. \ No newline at end of file diff --git a/README.md b/README.md index 205b5a496e..d5e2fec88d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ Language support for Java ™ for Visual Studio Code ===================== -[![Join the chat at https://gitter.im/redhat-developer/vscode-java](https://badges.gitter.im/redhat-developer/vscode-java.svg)](https://gitter.im/redhat-developer/vscode-java?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/redhat-developer/vscode-java.svg?branch=master)](https://travis-ci.org/redhat-developer/vscode-java) [![Marketplace Version](https://vsmarketplacebadge.apphb.com/version/redhat.java.svg "Current Release")](https://marketplace.visualstudio.com/items?itemName=redhat.java) +[![Visual Studio Marketplace](https://img.shields.io/visual-studio-marketplace/v/redhat.java?style=for-the-badge&label=VS%20Marketplace&logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=redhat.java) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/redhat.java?style=for-the-badge)](https://marketplace.visualstudio.com/items?itemName=redhat.java) +[![Join the chat at https://gitter.im/redhat-developer/vscode-java](https://img.shields.io/gitter/room/redhat-developer/vscode-java?style=for-the-badge&logo=gitter)](https://gitter.im/redhat-developer/vscode-java) +[![Build Status](https://img.shields.io/github/actions/workflow/status/redhat-developer/vscode-java/pr-verify.yml?branch=main&style=for-the-badge&logo=github)](https://github.com/redhat-developer/vscode-java/actions?query=workflow:pr-verify) +[![License](https://img.shields.io/github/license/redhat-developer/vscode-java?style=for-the-badge&logo=eclipse)](https://github.com/redhat-developer/vscode-java/blob/main/LICENSE) Provides Java ™ language support via [Eclipse ™ JDT Language Server](https://github.com/eclipse/eclipse.jdt.ls), which utilizes @@ -11,24 +14,27 @@ Provides Java ™ language support via Quick Start ============ 1. Install the Extension -2. If you do not have a _Java_ Development Kit correctly [set](#setting-the-jdk) - * Download and install a recent Java Development Kit (latest Java 8 is the minimum requirement). -3. Extension is activated when you first access a Java file +2. On the following platforms, the extension should activate without any setup : `win32-x64`, `win32-arm64`, `darwin-x64`, `darwin-arm64`, `linux-x64`, `linux-arm64`.\ +If on another platform, or using the "universal" version, you can [set](#setting-the-jdk) a _Java_ Development Kit. It must be Java 21 or above. +3. Optionally, download and install a Java Development Kit for your project (Java 1.8 or above is supported). See [Project JDKs](#project-jdks) for more details +4. Extension is activated when you first access a Java file * Recognizes projects with *Maven* or *Gradle* build files in the directory hierarchy. Features ========= -![ screencast ](https://raw.githubusercontent.com/redhat-developer/vscode-java/master/images/vscode-java.0.0.1.gif) +![ screencast ](https://raw.githubusercontent.com/redhat-developer/vscode-java/main/images/vscode-java.0.0.1.gif) -* Supports code from Java 1.5 to Java 12 +* Supports code from Java 1.8 to Java 26 * Maven pom.xml project support -* Basic Gradle Java project support +* Gradle project support (with experimental Android project import support) * Standalone Java files support * As-you-type reporting of parsing and compilation errors * Code completion * Code/Source actions / Refactoring * Javadoc hovers * Organize imports + - triggered manually or on save + - when pasting code into a java file with `Ctrl+Shift+v` (`Cmd+Shift+v` on Mac). * Type search * Code outline * Code folding @@ -38,8 +44,11 @@ Features * Code formatting (on-type/selection/file) * Code snippets * Annotation processing support (automatic for Maven projects) - -Please note that [Gradle-based Android projects are not supported](https://github.com/redhat-developer/vscode-java/issues/10#issuecomment-268834749). +* Semantic selection +* Diagnostic tags +* Call Hierarchy +* Type Hierarchy +* Inlay Hints To launch and debug your Java programs, it's recommended you install *[Java Debug Extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug)*. @@ -47,58 +56,114 @@ See the [changelog](CHANGELOG.md) for the latest release. You might also find us Setting the JDK =============== -The path to the Java Development Kit is searched in the following order: +## Java Tooling JDK +Now that Java extension will publish platform specific versions, it will embed a JRE for supported platforms such as `win32-x64`, `win32-arm64`, `linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`. The embedded JRE is used to launch the Language Server for Java. Users are only responsible for configuring [Project JDKs](#project-jdks) to compile your Java projects. + +The following part is only kept for the universal version without embedded JRE. + +>The tooling JDK will be used to launch the Language Server for Java. And by default, will also be used to compile your projects. Java 21 is the minimum required version.\ +\ +The path to the Java Development Kit can be specified by the `java.jdt.ls.java.home` setting in VS Code settings (workspace/user settings). If not specified, it is searched in the following order until a JDK meets current minimum requirement. +>- the `JDK_HOME` environment variable +>- the `JAVA_HOME` environment variable +>- on the current system path + +## Project JDKs +If you need to compile your projects against a different JDK version, it's recommended you configure the `java.configuration.runtimes` property in your user settings, eg: -- the `java.home` setting in VS Code settings (workspace then user settings) -- the `JDK_HOME` environment variable -- the `JAVA_HOME` environment variable -- on the current system path +```json +"java.configuration.runtimes": [ + { + "name": "JavaSE-1.8", + "path": "/path/to/jdk-8", + }, + { + "name": "JavaSE-11", + "path": "/path/to/jdk-11", + }, + { + "name": "JavaSE-25", + "path": "/path/to/jdk-25", + "default": true + }, + , + { + "name": "JavaSE-26", + "path": "/path/to/jdk-26", + "default": true + }, +] +``` +The default runtime will be used when you open standalone Java files. Available commands ========================== The following commands are available: -- `Java:Update Project configuration` (`Shift+Alt+U`): is available when the editor is focused on a Maven pom.xml or a Gradle file. It forces project configuration / classpath updates (eg. dependency changes or Java compilation level), according to the project build descriptor. -- `Java:Open Java Language Server log file`: opens the Java Language Server log file, useful for troubleshooting problems. -- `Java:Force Java compilation` (`Shift+Alt+B`): manually triggers compilation of the workspace. -- `Java:Open Java formatter settings`: Open the Eclipse formatter settings. Creates a new settings file if none exists. -- `Java:Clean the Java language server workspace`: Clean the Java language server workspace. -- `Java:Attach Source`: Attach a jar/zip source to the currently opened binary class file. This command is only available in the editor context menu. +- `Switch to Standard Mode`: switches the Java Language Server to `Standard` mode. This command is only available when the Java Language Server is in `LightWeight` mode. +- `Java: Reload Projects` (`Shift+Alt+U`): It forces project configuration / classpath updates (eg. dependency changes or Java compilation level), according to the project build descriptor. +- `Java: Import Java Projects into Workspace`: detects and imports all the Java projects into the Java Language Server workspace. +- `Java: Open Java Language Server Log File`: opens the Java Language Server log file, useful for troubleshooting problems. +- `Java: Open Java Extension Log File`: opens the Java extension log file, useful for troubleshooting problems. +- `Java: Open All Log Files`: opens both the Java Language Server log file and the Java extension log file. +- `Java: Force Java Compilation` (`Shift+Alt+B`): manually triggers compilation of the workspace. +- `Java: Rebuild Projects`: manually triggers a full build of the selected projects. +- `Java: Open Java Formatter Settings`: opens the Eclipse formatter settings. Creates a new settings file if none exists. +- `Java: Clean Java Language Server Workspace`: cleans the Java language server workspace. +- `Java: Attach Source`: attaches a jar/zip source to the currently opened binary class file. This command is only available in the editor context menu. +- `Java: Add Folder to Java Source Path`: adds the selected folder to its project source path. This command is only available in the file explorer context menu and only works for unmanaged folders. +- `Java: Remove Folder from Java Source Path`: removes the selected folder from its project source path. This command is only available in the file explorer context menu and only works for unmanaged folders. +- `Java: List All Java Source Paths`: lists all the Java source paths recognized by the Java Language Server workspace. +- `Java: Show Build Job Status`: shows the Java Language Server job status in Visual Studio Code terminal. +- `Java: Go to Super Implementation`: goes to the super implementation for the current selected symbol in editor. +- `Java: Restart Java Language Server`: restarts the Java language server. Supported VS Code settings ========================== The following settings are supported: -* `java.home` : Absolute path to JDK home folder used to launch the Java Language Server. Requires VS Code restart. +* `java.home` : **Deprecated, please use 'java.jdt.ls.java.home' instead.** Absolute path to JDK home folder used to launch the Java Language Server. Requires VS Code restart. +* `java.jdt.ls.lombokSupport.enabled`: Whether to enable lombok support. Defaults to `true`. * `java.jdt.ls.vmargs` : Extra VM arguments used to launch the Java Language Server. Requires VS Code restart. -* `java.configuration.updateBuildConfiguration` : Specifies how modifications on build files update the Java classpath/configuration. Supported values are `disabled` (nothing happens), `interactive` (asks about updating on every modification), `automatic` (updating is automatically triggered). * `java.errors.incompleteClasspath.severity` : Specifies the severity of the message when the classpath is incomplete for a Java file. Supported values are `ignore`, `info`, `warning`, `error`. * `java.trace.server` : Traces the communication between VS Code and the Java language server. -* `java.configuration.maven.userSettings` : Path to Maven's settings.xml. -* `java.import.exclusions` : Exclude folders from import via glob patterns. +* `java.configuration.updateBuildConfiguration` : Specifies how modifications on build files update the Java classpath/configuration. Supported values are `disabled` (nothing happens), `interactive` (asks about updating on every modification), `automatic` (updating is automatically triggered). +* `java.configuration.maven.userSettings` : Path to Maven's user settings.xml. +* `java.configuration.checkProjectSettingsExclusions`: **Deprecated, please use 'java.import.generatesMetadataFilesAtProjectRoot' to control whether to generate the project metadata files at the project root. And use 'files.exclude' to control whether to hide the project metadata files from the file explorer.** Controls whether to exclude extension-generated project settings files (`.project`, `.classpath`, `.factorypath`, `.settings/`) from the file explorer. Defaults to `false`. * `java.referencesCodeLens.enabled` : Enable/disable the references code lenses. -* `java.implementationsCodeLens.enabled` : Enable/disable the implementations code lenses. +* `java.implementationCodeLens` : Enable/disable the implementations code lens for the provided categories. * `java.signatureHelp.enabled` : Enable/disable signature help support (triggered on `(`). -* `java.format.enabled` : Enable/disable the default Java formatter. +* `java.signatureHelp.description.enabled` : Enable/disable to show the description in signature help. Defaults to `false`. * `java.contentProvider.preferred` : Preferred content provider (see 3rd party decompilers available in [vscode-java-decompiler](https://github.com/dgileadi/vscode-java-decompiler)). +* `java.import.exclusions` : Exclude folders from import via glob patterns. Use `!` to negate patterns to allow subfolders imports. You have to include a parent directory. The order is important. * `java.import.gradle.enabled` : Enable/disable the Gradle importer. -* `java.import.gradle.wrapper.enabled`: Enable/disable the Gradle wrapper. -* `java.import.gradle.version`: Gradle version, used if the gradle wrapper is missing or disabled. +* Specify the Gradle distribution used by the Java extension: + * `java.import.gradle.wrapper.enabled`: Use Gradle from the 'gradle-wrapper.properties' file. Defaults to `true`. + * `java.import.gradle.version`: Use Gradle from the specific version if the Gradle wrapper is missing or disabled. + * `java.import.gradle.home`: Use Gradle from the specified local installation directory or GRADLE_HOME if the Gradle wrapper is missing or disabled and no 'java.import.gradle.version' is specified. +* `java.import.gradle.arguments`: Arguments to pass to Gradle. +* `java.import.gradle.jvmArguments`: JVM arguments to pass to Gradle. +* `java.import.gradle.user.home`: setting for GRADLE_USER_HOME. +* `java.import.gradle.offline.enabled`: Enable/disable the Gradle offline mode. Defaults to `false`. * `java.import.maven.enabled` : Enable/disable the Maven importer. * `java.autobuild.enabled` : Enable/disable the 'auto build'. * `java.maxConcurrentBuilds`: Set max simultaneous project builds. +* `java.completion.enabled` : Enable/disable code completion support. +* `java.completion.guessMethodArguments` : Specify how the arguments will be filled during completion. Defaults to `auto`. + - `auto`: Use `off` only when using Visual Studio Code - Insiders, other platform will defaults to `insertBestGuessedArguments`. + - `off`: Method arguments will not be inserted during completion. + - `insertParameterNames`: The parameter names will be inserted during completion. + - `insertBestGuessedArguments`: The best guessed arguments will be inserted during completion according to the code context. +* `java.completion.filteredTypes`: Defines the type filters. All types whose fully qualified name matches the selected filter strings will be ignored in content assist or quick fix proposals and when organizing imports. For example 'java.awt.*' will hide all types from the awt packages. * `java.completion.favoriteStaticMembers` : Defines a list of static members or types with static members. * `java.completion.importOrder` : Defines the sorting order of import statements. -* `java.progressReports.enabled` : [Experimental] Enable/disable progress reports from background processes on the server. -* `java.completion.overwrite` : When set to true, code completion overwrites the current text. When set to false, code is simply added instead. +* `java.format.enabled` : Enable/disable the default Java formatter. * `java.format.settings.url` : Specifies the url or file path to the [Eclipse formatter xml settings](https://github.com/redhat-developer/vscode-java/wiki/Formatter-settings). * `java.format.settings.profile` : Optional formatter profile name from the Eclipse formatter settings. * `java.format.comments.enabled` : Includes the comments during code formatting. * `java.format.onType.enabled` : Enable/disable on-type formatting (triggered on `;`, `}` or ``). -* `java.completion.guessMethodArguments` : When set to true, method arguments are guessed when a method is selected from as list of code assist proposals. -* `java.completion.enabled` : Enable/disable code completion support. -* `java.configuration.checkProjectSettingsExclusions`: Checks if the extension-generated project settings files (`.project`, `.classpath`, `.factorypath`, `.settings/`) should be excluded from the file explorer. Defaults to `true`. * `java.foldingRange.enabled`: Enable/disable smart folding range support. If disabled, it will use the default indentation-based folding range provided by VS Code. -* `java.maven.downloadSources`: Enable/disable eager download of Maven source artifacts. +* `java.maven.downloadSources`: Enable/disable download of Maven source artifacts as part of importing Maven projects. +* `java.maven.updateSnapshots`: Force update of Snapshots/Releases. Defaults to `false`. * `java.codeGeneration.hashCodeEquals.useInstanceof`: Use 'instanceof' to compare types when generating the hashCode and equals methods. Defaults to `false`. * `java.codeGeneration.hashCodeEquals.useJava7Objects`: Use Objects.hash and Objects.equals when generating the hashCode and equals methods. This setting only applies to Java 7 and higher. Defaults to `false`. * `java.codeGeneration.useBlocks`: Use blocks in 'if' statements when generating the methods. Defaults to `false`. @@ -108,13 +173,113 @@ The following settings are supported: * `java.codeGeneration.toString.skipNullValues`: Skip null values when generating the toString method. Defaults to `false`. * `java.codeGeneration.toString.listArrayContents`: List contents of arrays instead of using native toString(). Defaults to `true`. * `java.codeGeneration.toString.limitElements`: Limit number of items in arrays/collections/maps to list, if 0 then list all. Defaults to `0`. +* `java.selectionRange.enabled`: Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection. +* `java.showBuildStatusOnStart.enabled`: Automatically show build status on startup, defaults to `notification`. + - `notification`: Show the build status via progress notification. + - `terminal`: Show the build status via terminal. + - `off`: Do not show any build status. + > For backward compatibility, this setting also accepts boolean value, where `true` has the same meaning as `notification` and `false` has the same meaning as `off`. +* `java.project.outputPath`: A relative path to the workspace where stores the compiled output. `Only` effective in the `WORKSPACE` scope. The setting will `NOT` affect Maven or Gradle project. +* `java.project.referencedLibraries`: Configure glob patterns for referencing local libraries to a Java project. +* `java.completion.maxResults`: Maximum number of completion results (not including snippets). `0` (the default value) disables the limit, all results are returned. In case of performance problems, consider setting a sensible limit. +* `java.configuration.runtimes`: Map Java Execution Environments to local JDKs. +* `java.server.launchMode`: + - `Standard`: Provides full features such as intellisense, refactoring, building, Maven/Gradle support etc. + - `LightWeight`: Starts a syntax server with lower start-up cost. Only provides syntax features such as outline, navigation, javadoc, syntax errors. The lightweight mode won't load thirdparty extensions, such as java test runner, java debugger, etc. + - `Hybrid`: Provides full features with better responsiveness. It starts a standard language server and a secondary syntax server. The syntax server provides syntax features until the standard server is ready. And the syntax server will be shutdown automatically after the standard server is fully ready. -*New in 0.47.0* + Default launch mode is `Hybrid`. Legacy mode is `Standard` +* `java.sources.organizeImports.starThreshold`: Specifies the number of imports added before a star-import declaration is used, default is 99. +* `java.sources.organizeImports.staticStarThreshold`: Specifies the number of static imports added before a star-import declaration is used, default is 99. +* `java.updateImportsOnPaste.enabled` : Enable/disable auto organize imports when pasting code. Defaults to `true`. +* `java.imports.gradle.wrapper.checksums`: Defines allowed/disallowed SHA-256 checksums of Gradle Wrappers. +* `java.project.importOnFirstTimeStartup`: Specifies whether to import the Java projects, when opening the folder in Hybrid mode for the first time. Supported values are `disabled` (never imports), `interactive` (asks to import or not), `automatic` (always imports). Default to `automatic`. +* `java.project.importHint`: Enable/disable the server-mode switch information, when Java projects import is skipped on startup. Defaults to `true`. +* `java.import.gradle.java.home`: Specifies the location to the JVM used to run the Gradle daemon. +* `java.project.resourceFilters`: Excludes files and folders from being refreshed by the Java Language Server, which can improve the overall performance. For example, ["node_modules","\.git"] will exclude all files and folders named 'node_modules' or '.git'. Pattern expressions must be compatible with `java.util.regex.Pattern`. Defaults to ["node_modules","\.git"]. +* `java.templates.fileHeader`: Specifies the file header comment for new Java file. Supports configuring multi-line comments with an array of strings, and using ${variable} to reference the [predefined variables](https://github.com/redhat-developer/vscode-java/wiki/Predefined-Variables-for-Java-Template-Snippets). +* `java.templates.typeComment`: Specifies the type comment for new Java type. Supports configuring multi-line comments with an array of strings, and using ${variable} to reference the [predefined variables](https://github.com/redhat-developer/vscode-java/wiki/Predefined-Variables-for-Java-Template-Snippets). +* `java.templates.newFile.enabled` : Enable/disable automatic generation of class body and package declaration when creating a new Java file. Set to `false` to create empty Java files. Defaults to `true`. +* `java.references.includeAccessors`: Include getter, setter and builder/constructor when finding references. Default to true. +* `java.configuration.maven.globalSettings` : Path to Maven's global settings.xml. +* `java.configuration.maven.lifecycleMappings` : Path to Maven's lifecycle mappings xml. +* `java.eclipse.downloadSources` : Enable/disable download of Maven source artifacts for Eclipse projects. +* `java.references.includeDecompiledSources` : Include the decompiled sources when finding references. Default to true. +* `java.project.sourcePaths`: Relative paths to the workspace where stores the source files. `Only` effective in the `WORKSPACE` scope. The setting will `NOT` affect Maven or Gradle project. +* `java.typeHierarchy.lazyLoad`: Enable/disable lazy loading the content in type hierarchy. Lazy loading could save a lot of loading time but every type should be expanded manually to load its content. +* `java.codeGeneration.insertionLocation`: Specifies the insertion location of the code generated by source actions. Defaults to `afterCursor`. + - `afterCursor`: Insert the generated code after the member where the cursor is located. + - `beforeCursor`: Insert the generated code before the member where the cursor is located. + - `lastMember`: Insert the generated code as the last member of the target type. +* `java.codeGeneration.addFinalForNewDeclaration`: Whether to generate the 'final' modifer for code actions that create new declarations. Defaults to `none`. + - `none`: Do not generate final modifier + - `fields`: Generate 'final' modifier only for new field declarations + - `variables`: Generate 'final' modifier only for new variable declarations + - `all`: Generate 'final' modifier for all new declarations +* `java.settings.url` : Specifies the url or file path to the workspace Java settings. See [Setting Global Preferences](https://github.com/redhat-developer/vscode-java/wiki/Settings-Global-Preferences) +* `java.symbols.includeSourceMethodDeclarations` : Include method declarations from source files in symbol search. Defaults to `false`. +* `java.symbols.includeGeneratedCode` : Include generated code (e.g. Lombok getters, setters, constructors) in document outline/symbols. Defaults to `false`. +* `java.quickfix.showAt` : Show quickfixes at the problem or line level. +* `java.configuration.workspaceCacheLimit` : The number of days (if enabled) to keep unused workspace cache data. Beyond this limit, cached workspace data may be removed. +* `java.import.generatesMetadataFilesAtProjectRoot` : Specify whether the project metadata files(.project, .classpath, .factorypath, .settings/) will be generated at the project root. Defaults to `false`. +* `java.inlayHints.parameterNames.enabled`: Enable/disable inlay hints for parameter names. Supported values are: `none`(disable parameter name hints), `literals`(Enable parameter name hints only for literal arguments) and `all`(Enable parameter name hints for literal and non-literal arguments). Defaults to `literals`. +* `java.inlayHints.parameterTypes.enabled`: Enable/disable inlay hints for (lambda) parameter types. Defaults to `false`. +* `java.compile.nullAnalysis.nonnull`: Specify the Nonnull annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in your project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`. +* `java.compile.nullAnalysis.nullable`: Specify the Nullable annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in your project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`. +* `java.compile.nullAnalysis.nonnullbydefault`: Specify the NonNullByDefault annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in your project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`. +* `java.import.maven.offline.enabled`: Enable/disable the Maven offline mode. Defaults to `false`. +* `java.codeAction.sortMembers.avoidVolatileChanges`: Reordering of fields, enum constants, and initializers can result in semantic and runtime changes due to different initialization and persistence order. This setting prevents this from occurring. Defaults to `true`. +* `java.jdt.ls.protobufSupport.enabled`: Specify whether to automatically add Protobuf output source directories to the classpath. **Note:** Only works for Gradle `com.google.protobuf` plugin `0.8.4` or higher. Defaults to `true`. +* `java.jdt.ls.aspectjSupport.enabled`: Specify whether to enable `io.freefair.aspectj` plugin in Gradle projects. Defaults to `false`. +* `java.jdt.ls.androidSupport.enabled`: [Experimental] Specify whether to enable Android project importing. When set to `auto`, the Android support will be enabled in Visual Studio Code - Insiders. **Note:** Only works for Android Gradle Plugin `3.2.0` or higher. Defaults to `auto`. +* `java.jdt.ls.kotlinSupport.enabled`: [Experimental] Specify whether to enable `org.jetbrains.kotlin.jvm` plugin in Gradle projects. Defaults to `true`. +* `java.jdt.ls.groovySupport.enabled`: [Experimental] Specify whether to enable `groovy` plugin in Gradle projects. Defaults to `true`. +* `java.jdt.ls.scalaSupport.enabled`: [Experimental] Specify whether to enable `scala` plugin in Gradle projects. Defaults to `true`. +* `java.completion.postfix.enabled`: Enable/disable postfix completion support. Defaults to `true`. +* `java.completion.chain.enabled`: Enable/disable chain completion support. Defaults to `false`. +* `java.completion.matchCase`: Specify whether to match case for code completion. Defaults to `firstLetter`. +* `java.compile.nullAnalysis.mode`: Specify how to enable the annotation-based null analysis. Supported values are `disabled` (disable the null analysis), `interactive` (asks when null annotation types are detected), `automatic` (automatically enable null analysis when null annotation types are detected). Defaults to `interactive`. +* `java.cleanup.actionsOnSave`: **Deprecated, please use 'java.cleanup.actions' instead.** The list of clean ups to be run on the current document when it's saved. Clean ups can automatically fix code style or programming mistakes. [Click here](document/_java.learnMoreAboutCleanUps.md#java-clean-ups) to learn more about what each clean up does. +* `java.cleanup.actions`: The list of clean ups to be run on the current document when it's saved or when the cleanup command is issued. Clean ups can automatically fix code style or programming mistakes. [Click here](document/_java.learnMoreAboutCleanUps.md#java-clean-ups) to learn more about what each clean up does. +* `java.saveActions.cleanup`: Enable/disable cleanup actions on save. +* `java.import.gradle.annotationProcessing.enabled`: Enable/disable the annotation processing on Gradle projects and delegate to JDT APT. Only works for Gradle 5.2 or higher. +* `java.sharedIndexes.enabled`: [Experimental] Specify whether to share indexes between different workspaces. Defaults to `auto` and the shared indexes is automatically enabled in Visual Studio Code - Insiders. + - auto + - on + - off +* `java.sharedIndexes.location`: Specifies a common index location for all workspaces. See default values as follows: + - Windows: First use `"$APPDATA\\.jdt\\index"`, or `"~\\.jdt\\index"` if it does not exist + - macOS: `"~/Library/Caches/.jdt/index"` + - Linux: First use `"$XDG_CACHE_HOME/.jdt/index"`, or `"~/.cache/.jdt/index"` if it does not exist +* `java.refactoring.extract.interface.replace`: Specify whether to replace all the occurrences of the subtype with the new extracted interface. Defaults to `true`. +* `java.import.maven.disableTestClasspathFlag` : Enable/disable test classpath segregation. When enabled, this permits the usage of test resources within a Maven project as dependencies within the compile scope of other projects. Defaults to `false`. +* `java.configuration.maven.defaultMojoExecutionAction` : Specifies default mojo execution action when no associated metadata can be detected. Defaults to `ignore`. +* `java.completion.lazyResolveTextEdit.enabled`: [Experimental] Enable/disable lazily resolving text edits for code completion. Defaults to `true`. +* `java.edit.validateAllOpenBuffersOnChanges`: Specifies whether to recheck all open Java files for diagnostics when editing a Java file. Defaults to `false`. +* `java.editor.reloadChangedSources`: Specifies whether to reload the sources of the open class files when their source jar files are changed. Defaults to `ask`. + - `ask`: Ask to reload the sources of the open class files + - `auto`: Automatically reload the sources of the open class files + - `manual`: Manually reload the sources of the open class files +* `java.edit.smartSemicolonDetection.enabled`: Defines the `smart semicolon` detection. Defaults to `false`. +* `java.configuration.detectJdksAtStart`: Automatically detect JDKs installed on local machine at startup. If you have specified the same JDK version in `java.configuration.runtimes`, the extension will use that version first. Defaults to `true`. +* `java.completion.collapseCompletionItems`: Enable/disable the collapse of overloaded methods in completion items. Overrides `java.completion.guessMethodArguments`. Defaults to `false`. +* `java.diagnostic.filter`: Specifies a list of file patterns for which matching documents should not have their diagnostics reported (eg. '\*\*/Foo.java'). +* `java.search.scope`: Specifies the scope which must be used for search operation like + - Find Reference + - Call Hierarchy + - Workspace Symbols +* `java.jdt.ls.javac.enabled`: [Experimental] Specify whether to enable Javac-based compilation in the language server. Requires running this extension with Java 24. Defaults to `off`. +* `java.completion.engine`: [Experimental] Select code completion engine. Defaults to `ecj`. +* `java.references.includeDeclarations`: Include declarations when finding references. Defaults to `true` +* `java.jdt.ls.appcds.enabled` : [Experimental] Enable Java AppCDS (Application Class Data Sharing) for improvements to extension activation. When set to `auto`, AppCDS will be enabled in Visual Studio Code - Insiders, and for pre-release versions. +* `java.hover.javadoc.enabled` : Enable/disable displaying Javadoc on hover. Defaults to `true`. -* `java.import.gradle.arguments`: Arguments to pass to Gradle. -* `java.import.gradle.jvmArguments`: JVM arguments to pass to Gradle. -* `java.import.gradle.home`: setting for GRADLE_HOME. +New in 1.54.0 +* `java.inlayHints.formatParameters.enabled`: Enable/disable inlay hints for format specifiers in format strings (e.g. `String.format()`, `String.formatted()`, `PrintStream.printf()`). Shows which argument corresponds to each format specifier. Defaults to `false`. +Semantic Highlighting +=============== +[Semantic Highlighting](https://github.com/redhat-developer/vscode-java/wiki/Semantic-Highlighting) fixes numerous syntax highlighting issues with the default Java Textmate grammar. However, you might experience a few minor issues, particularly a delay when it kicks in, as it needs to be computed by the Java Language server, when opening a new file or when typing. Semantic highlighting can be disabled for all languages using the `editor.semanticHighlighting.enabled` setting, or for Java only using [language-specific editor settings](https://code.visualstudio.com/docs/getstarted/settings#_languagespecific-editor-settings). Troubleshooting =============== @@ -122,7 +287,7 @@ Troubleshooting It should show ready (thumbs up) as on the image below. You can click on the status and open the language tool logs for further information in case of a failure. -![ status indicator ](https://raw.githubusercontent.com/redhat-developer/vscode-java/master/images/statusMarker.png) +![ status indicator ](https://raw.githubusercontent.com/redhat-developer/vscode-java/main/images/statusMarker.png) 2. Read the [troubleshooting guide](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting) for collecting informations about issues you might encounter. @@ -137,10 +302,11 @@ For information on getting started, refer to the [CONTRIBUTING instructions](CON Continuous Integration builds can be installed from [http://download.jboss.org/jbosstools/jdt.ls/staging/](http://download.jboss.org/jbosstools/jdt.ls/staging/?C=M;O=D). Download the most recent `java-.vsix` file and install it by following the instructions [here](https://code.visualstudio.com/docs/editor/extension-gallery#_install-from-a-vsix). Stable releases are archived under http://download.jboss.org/jbosstools/static/jdt.ls/stable/. -Also, you can contribute your own VSCode extension to enhance the existing features by following the instructions [here](https://github.com/redhat-developer/vscode-java/wiki/Contribute-a-Java-Extension). +Also, you can contribute your own VS Code extension to enhance the existing features by following the instructions [here](https://github.com/redhat-developer/vscode-java/wiki/Contribute-a-Java-Extension). Feedback =============== +* Have a question? Start a discussion on [GitHub Discussions](https://github.com/redhat-developer/vscode-java/discussions), * File a bug in [GitHub Issues](https://github.com/redhat-developer/vscode-java/issues), * Chat with us on [Gitter](https://gitter.im/redhat-developer/vscode-java), * [Tweet us](https://twitter.com/VSCodeJava/) with other feedback. @@ -148,4 +314,4 @@ Feedback License =============== -EPL 1.0, See [LICENSE](LICENSE) for more information. +EPL 2.0, See [LICENSE](LICENSE) for more information. diff --git a/USAGE_DATA.md b/USAGE_DATA.md new file mode 100644 index 0000000000..c977296de0 --- /dev/null +++ b/USAGE_DATA.md @@ -0,0 +1,38 @@ +# Data collection + +vscode-java has opt-in telemetry collection, provided by [vscode-redhat-telemetry](https://github.com/redhat-developer/vscode-redhat-telemetry). + +## What's included in the vscode-java telemetry data + + * vscode-java emits telemetry events when the extension starts and stops, + which contain the common data mentioned on the + [vscode-redhat-telemetry page](https://github.com/redhat-developer/vscode-redhat-telemetry/blob/main/USAGE_DATA.md#common-data). + * The name of the build tool used to import a project (eg. Maven, Gradle, Invisible (project), etc.) + * The total number of Java projects within the workspace + * The lowest and highest Java compiler source level used (eg. 11 & 17) + * Whether the project(s) are being imported for the first time (eg. true) + * The elapsed time (in milliseconds) at which the language server initialized the workspace project(s), declared as ready for requests, and completed building the project(s) + * The number of libraries that were indexed after project initialization + * The total size (in bytes) of libraries that were indexed after project initialization + * The number of error markers on the project(s) + * The number of unresolved imports within the project(s) + * Errors relating to running the language server, such as the message & stacktrace + * Whether there is a mismatch between the project's requested source level, and the JDK used for the project (eg. true) + * Information about the following settings. In the case of settings that store a well defined value (eg. path/url/string), we simply collect whether the setting has been set. + * `java.settings.url`, `java.format.settings.url`, `java.quickfix.showAt`, `java.symbols.includeSourceMethodDeclarations`, `java.completion.collapseCompletionItems`, `java.completion.guessMethodArguments`, `java.completion.postfix.enabled`, `java.cleanup.actionsOnSave`, `java.sharedIndexes.enabled`, `java.inlayHints.parameterNames.enabled`, `java.inlayHints.parameterNames.suppressWhenSameNameNumbered`, `java.inlayHints.variableTypes.enabled`, `java.inlayHints.parameterTypes.enabled`, `java.server.launchMode`, `java.autobuild.enabled`, `java.jdt.ls.javac.enabled` + * The extension name and the choice made when a recommendation to install a 3rd party extension is proposed + * The name of Java commands being manually executed, and any resulting errors + * The number of results (eg. 20), whether an error occurred (eg. false), engine type (eg. 'ecj', 'dom') and duration (in milliseconds) when code assist is activated + * Whether the language server ran out of memory and the maximum allocated memory at which that occurred (eg. 200m) + +## What's included in the general telemetry data + +Please see the +[vscode-redhat-telemetry data collection information](https://github.com/redhat-developer/vscode-redhat-telemetry/blob/HEAD/USAGE_DATA.md#usage-data-being-collected-by-red-hat-extensions) +for information on what data it collects. + +## How to opt in or out + +Use the `redhat.telemetry.enabled` setting in order to enable or disable telemetry collection. + +This extension also abides by Visual Studio Code's telemetry level: if `telemetry.telemetryLevel` is set to `off`, then no telemetry events will be sent to Red Hat, even if `redhat.telemetry.enabled` is set to `true`. If `telemetry.telemetryLevel` is set to `error` or `crash`, only events containing an error or errors property will be sent to Red Hat. diff --git a/changes b/changes new file mode 100644 index 0000000000..92b7e65b1b --- /dev/null +++ b/changes @@ -0,0 +1,7 @@ +Fetching issues from https://api.github.com/repos/redhat-developer/vscode-java/issues?state=closed&milestone=154&page=1 + * enhancement - Fix #3210: map decorator token to annotation scope. See [#4421](https://github.com/redhat-developer/vscode-java/pull/4421). + * enhancement - Add feature: copy fully qualified name . See [#374](https://github.com/redhat-developer/vscode-java/issues/374). + * bug fix - Sanitize existing command links from hover Javadocs. See [#4429](https://github.com/redhat-developer/vscode-java/pull/4429). + * bug fix - Maven project 5 folders deap are not loaded as java projects. See [#4364](https://github.com/redhat-developer/vscode-java/issues/4364). + * bug fix - Very long Javadoc is truncated on hover. See [#4219](https://github.com/redhat-developer/vscode-java/issues/4219). + * bug fix - Failed to initialize language server due to "Internal error. Caused by: NPE: Cannot invoke 'o.e.m.c.e.IMaven.getSettings()' because the return value of 'o.e.m.c.MavenPlugin.getMaven()' is null". See [#3469](https://github.com/redhat-developer/vscode-java/issues/3469). diff --git a/document/_java.learnMoreAboutCleanUps.md b/document/_java.learnMoreAboutCleanUps.md new file mode 100644 index 0000000000..635eaaf041 --- /dev/null +++ b/document/_java.learnMoreAboutCleanUps.md @@ -0,0 +1,585 @@ +# Java Clean Ups + +Java clean ups are run on the current document whenever it's saved. +They can fix a wide variety of issues, from code style to programming mistakes, +and can even modernize the sources based on new Java language features. +Here is some information on the supported cleanups and the details of what they do. + +### `qualifyMembers` + +Whenever a member (field or method) of a class is accessed from within the class, +prefix the access with `this`. +This is similar to how Python requires the programmer to access members using `self`. + +For instance: + +```java +private int value; + +public int getValue() { + return value; +} +``` + +becomes: + +```java +private int value; + +public int getValue() { + return this.value; +} +``` + +### `qualifyStaticMembers` + +Whenever there is a static variable or function, prefix the access with the name of the class that the static variable or function belongs to. + +For instance: + +```java +import static java.lang.System.out; + +public class MyClass { + public static final double FACTOR = 0.5; + + public double getNumber(double value) { + out.println("moo"); + return value * FACTOR; + } +} +``` + +becomes: + +```java +import static java.lang.System.out; + +public class MyClass { + public static final double FACTOR = 0.5; + + public double getNumber(double value) { + System.out.println("moo"); + return value * MyClass.FACTOR; + } +} +``` + +### `addOverride` + +When a method of a class that overrides a method from a parent class or provides an implementation for a method from an interface, add the `@Override` annotation. + +For example: + +```java +public class MyRunner implements Runnable { + public void run() { + System.out.println("Hello, World!"); + } +} +``` + +becomes: + +```java +public class MyRunner implements Runnable { + @Override + public void run() { + System.out.println("Hello, World!"); + } +} +``` + +### `addDeprecated` + +When a method is marked `@deprecated` in the Javadoc, but doesn't have the `@Deprecated` annotation, add the `@Deprecated` annotation. +This only works if the compiler has been configured to mark deprecated methods without the deprecated annotation +as an info/warning/error in the JDT settings. + +For example: + +```java +/** + * Not used anymore, please stop using. + * + * @deprecated + */ +public boolean isAGoat() { + return false; +} +``` + +becomes: + +```java +/** + * Not used anymore, please stop using. + * + * @deprecated + */ +@Deprecated +public boolean isAGoat() { + return false; +} +``` + +### `stringConcatToTextBlock` + +Appropriate String concatenations will be converted into Java `Text Blocks`. Appropriate String concatenations must have at least 3 non-empty substrings with one per line and the Java level must be 15 or higher. Line comments for all substrings but the last line will be lost after conversion. Spaces at the end of substrings preceding the newline will result in `\s` being substituted while substrings that do not end with newlines will have a `\` added at the end of the line to preserve concatenation. + +For example: + +```java +String x = "" + + "public class A {\n" + + " public void m() {\n" + + " System.out.println(\"abc\");\n" + + " }\n" + + "}"; +``` + +becomes: + +```java +String x = """ + public class A { + public void m() { + System.out.println("abc"); + } + }"""; +``` + +### `invertEquals` + +Inverts calls to `Object.equals(Object)` and `String.equalsIgnoreCase(String)` to avoid useless null pointer exception. + +The caller must be nullable and the parameter must not be nullable. + +By avoiding null pointer exceptions, the behavior may change. + +For example: + +```java +String message = getMessage(); +boolean result1 = message.equals("text"); +boolean result2 = message.equalsIgnoreCase("text"); +``` + +becomes: + +```java +String message = getMessage(); +boolean result1 = "text".equals(message); +boolean result2 = "text".equalsIgnoreCase(message); +``` + +### `addFinalModifier` + +Use the `final` modifier for variable declarations wherever it is possible. + +For example: + +```java +private int i= 0; +public void foo(int j) { + int k, h; + h= 0; +} +``` + +becomes: + +```java +private final int i= 0; +public void foo(final int j) { + final int k; + int h; + h= 0; +} +``` + +### `instanceofPatternMatch` + +Use pattern matching for the `instanceof` operator wherever possible. It is only applicable for Java level 15 or higher. + +For example: + +```java +if (object instanceof Integer) { + Integer i = (Integer) object; + return i.intValue(); +} +``` + +becomes: + +```java +if (object instanceof Integer i) { + return i.intValue(); +} +``` + + +### `lambdaExpressionFromAnonymousClass` + +Convert anonymous class declarations for functional interfaces to lambda expressions wherever possible. It is only applicable for Java level 8 or above. + +For example: + +```java +IntConsumer c = new IntConsumer() { + @Override public void accept(int value) { + System.out.println(i); + } +}; +``` + +becomes: + +```java +IntConsumer c = i -> { + System.out.println(i); +}; +``` + +### `switchExpression` + +Convert switch statements to switch expressions wherever possible. It is only applicable for Java level 14 or above. + +**Note** : _Switch statements that use control statements such as nested switch statements, if/else blocks, for/while loops are not considered as is the case for return/continue statements. All cases of the switch statement must either have a last assignment statement that sets the same variable/field as other cases, or else has a throw statement. Fall-through is allowed between cases but only if there are no other statements in between. The switch statement must have a default case unless the switch expression is an enum type and all possible enum values are represented in the cases._ + +For example: + +```java +int i; +switch(j) { + case 1: + i = 3; + break; + case 2: + i = 4; + break; + default: + i = 0; + break; +} +``` + +becomes: + +```java +int i = switch(j) { + case 1 -> 3; + case 2 -> 4; + default -> 0; +}; +``` + +### `tryWithResource` + +Simplifies the finally block to use the `try-with-resource` statement. + +For example: + +```java +final FileInputStream inputStream = new FileInputStream("out.txt"); +try { + System.out.println(inputStream.read()); +} finally { + inputStream.close(); +} +``` + +becomes: + +```java +final FileInputStream inputStream = new FileInputStream("out.txt"); +try (inputStream) { + System.out.println(inputStream.read()); +} +``` + +### `lambdaExpression` + +Cleans up lambda expression wherever possible in the following ways: + +1. Removes unnecessary parentheses. + + For example: + + ```java + (someString) -> someString.trim().toLowerCase(); + ``` + + becomes: + + ```java + someString -> someString.trim().toLowerCase(); + ``` + +2. Converts lambda expression blocks to a single statement when possible. + + For example: + + ```java + someString -> {return someString.trim().toLowerCase();}; + ``` + + becomes: + + ```java + someString -> someString.trim().toLowerCase(); + ``` + +3. Converts lambda expression to method reference. + + For example: + + ```java + () -> new ArrayList<>(); + ``` + + becomes: + + ```java + ArrayList::new; + ``` + +### `organizeImports` + +Performs the "Organize Imports" operation. + +**Note** : Since clean ups are meant to be applied without user feedback (eg. prompts about ambiguous types), this may leave some types unresolved. To properly resolve these ambiguous types, one can do so manually (code actions, source actions), or by calling "Organize Imports" through the command palette / key binding (shift + alt + o). + +For example: + +```java +package test1; +public class A { + public void test() { + List a1; + Iterator a2; + Map a3; + Set a4; + JarFile a5; + StringTokenizer a6; + Path a7; + URI a8; + HttpURLConnection a9; + InputStream a10; + Field a11; + Parser a12; + } +} +``` + +becomes: + +```java +package test1; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.jar.JarFile; + +public class A { + public void test() { + List a1; + Iterator a2; + Map a3; + Set a4; + JarFile a5; + StringTokenizer a6; + Path a7; + URI a8; + HttpURLConnection a9; + InputStream a10; + Field a11; + Parser a12; + } +} +``` + +### `renameUnusedLocalVariables` + +Rename unused loop variables, try-with-resource variables, catch parameters, lambda parameters, pattern variables to `_`. + +For example: + +```java +J j = (a, b) -> System.out.println(a); + +switch (r) { + case R(_, long l) -> {} + case R r2 -> {} +} +``` + +becomes: + +```java +J j = (a, _) -> System.out.println(a); + +switch (r) { + case R(_, _) -> {} + case R _ -> {} +} +``` + +### `useSwitchForInstanceofPattern` + +Convert if/else chains to pattern matching switch statements. + +For example: + +```java +int i, j; +double d; +boolean b; +if (x instanceof Integer xint) { + i = xint.intValue(); +} else if (x instanceof Double xdouble) { + d = xdouble.doubleValue(); +} else if (x instanceof Boolean xboolean) { + b = xboolean.booleanValue(); +} else { + i = 0; + d = 0.0D; + b = false; +} +``` + +becomes: + +```java +int i, j; +double d; +boolean b; +switch (x) { + case Integer xint -> i = xint.intValue(); + case Double xdouble -> d = xdouble.doubleValue(); + case Boolean xboolean -> b = xboolean.booleanValue(); + case null, default -> { + i = 0; + d = 0.0D; + b = false; + } +} +``` + +### `redundantComparisonStatement` + +Remove redundant comparison statement. + +For example: + +```java +if (i != 123) { + return i; +} else { + return 123; +} +``` + +becomes: + +```java +return i; +``` + +### `redundantFallingThroughBlockEnd` + +Remove redundant end of block with jump statement. + +For example: + +```java +if (0 < i) { + System.out.println("Doing something"); + return i + 10; +} +return i + 10; +``` + +becomes: + +```java +if (0 < i) { + System.out.println("Doing something"); +} +return i + 10; +``` + +### `redundantIfCondition` + +Remove redundant if condition. + +For example: + +```java +if (isValid) { + return 0; +} else if (!isValid) { + return -1; +} +``` + +becomes: + +```java +if (isValid) { + return 0; +} else { + return -1; +} +``` + +### `redundantModifiers` + +Remove redundant modifiers. + +For example: + +```java +public abstract interface IFoo { + public static final int MAGIC_NUMBER = 646; + public abstract int foo (); + public int bar (int bazz); +} +``` + +becomes: + +```java +public interface IFoo { + int MAGIC_NUMBER = 646; + int foo (); + int bar (int bazz); +} +``` + +### `redundantSuperCall` + +Remove redundant `super()` class in constructor. + +For example: + +```java +MyClass() { + super(); +} +``` + +becomes: + +```java +MyClass() { +} +``` diff --git a/document/_java.learnMoreAboutRefactorings.md b/document/_java.learnMoreAboutRefactorings.md new file mode 100644 index 0000000000..e153dace4a --- /dev/null +++ b/document/_java.learnMoreAboutRefactorings.md @@ -0,0 +1,660 @@ +# Java Refactoring + +## Table of Content +- [Introduction](#introduction) +- [Assign to variable](#assign-to-variable) +- [Change modifiers to final](#change-modifiers-to-final) +- [Convert anonymous to nested class](#convert-anonymous-to-nested-class) +- [Convert to anonymous class creation](#convert-to-anonymous-class-creation) +- [Convert to enhanced for loop](#convert-to-enhanced-for-loop) +- [Convert to lambda expression](#convert-to-lambda-expression) +- [Convert to static import](#convert-to-static-import) +- Extract refactorings + - [Extract to constant](#extract-to-constant) + - [Extract to field](#extract-to-field) + - [Extract to method](#extract-to-method) + - [Extract to local variable](#extract-to-local-variable) +- Inline refactorings + - [Inline constant](#inline-constant) + - [Inline local variable](#inline-local-variable) + - [Inline method](#inline-method) +- Method signature + - [Introduce Parameter](#introduce-parameter) + - [Change method signature](#change-method-signature) +- Invert boolean + - [Invert conditions](#invert-conditions) + - [Invert local variable](#invert-local-variable) +- [Move](#move) +- [Rename](#rename) +- Type change + - [Change resolved type to var type](#change-resolved-type-to-var-type) + - [Change var type to resolved type](#change-var-type-to-resolved-type) + +--- + +## Introduction + +The goal of the Java program refactoring is to make system-wide code changes without affecting the behavior of the program. The **Java Language Support for __VSCODE_ENV_APPNAME_PLACEHOLDER__** provides assistance in easily refactoring code. + +### Invoke refactoring +Refactoring commands are available from the context menu of the editor. Select the element you want to refactor, right-click to open the context menu and choose `Refactor...`: + +![menu](./refactoring_menu.png) + +Then you will see all the available refactoring options. + +--- + +## Assign to variable +Assigns an expression to a local variable or a field. + +### Example +#### Before + +```java +Arrays.asList("apple", "lemon", "banana"); +``` +#### After +```java +List fruits = Arrays.asList("apple", "lemon", "banana"); +``` + +--- + +## Change modifiers to final +Adds `final` modifier to all the variables and parameters in the current source file. + +### Example +#### Before + +```java +public class Clazz { + public void method(int value) { + boolean notValid = value > 5; + if (notValid) { + // do something + } + } +} +``` +#### After +```java +public class Clazz { + public void method(final int value) { + final boolean notValid = value > 5; + if (notValid) { + // do something + } + } +} +``` + +--- + +## Convert anonymous to nested class +Converts an anonymous inner class to a member class. + +### Example +Let's convert the anonymous class `Interface(){...}` to a member of the class `Clazz`. +#### Before + +```java +public class Clazz { + public Interface method() { + final boolean isValid = true; + return new Interface() { + public boolean isValid() { + return isValid; + } + }; + } +} +``` +#### After +```java +public class Clazz { + private final class MyInterface extends Interface { + private final boolean isValid; + + private MyInterface(boolean isValid) { + this.isValid = isValid; + } + + public boolean isValid() { + return isValid; + } + } + + public Interface method() { + final boolean isValid = true; + return new MyInterface(isValid); + } +} +``` + +--- + +## Convert to anonymous class creation +Converts lambda expression to anonymous class creation. + +### Example +The variable `runnable` is assigned with a lambda expression. Let's convert it to an anonymous class creation. +#### Before + +```java +public void method() { + Runnable runnable = () -> { + // do something + }; +} +``` +#### After +```java +public void method() { + Runnable runnable = new Runnable() { + @Override + public void run() { + // do something + } + }; +} +``` + +> Also see: [Convert to lambda expression](#convert-to-lambda-expression) + +--- + +## Convert to enhanced for loop +Converts the simple `for` loop to `for-each` style. + +### Example +#### Before + +```java +public void order(String[] books) { + for (int i = 0; i < books.length; i++) { + // do something + } +} +``` +#### After +```java +public void order(String[] books) { + for (String book : books) { + // do something + } +} +``` + +--- + +## Convert to lambda expression +Converts an anonymous class creation to the lambda expression. + +### Example +Let's convert the anonymous class `Runnable(){...}` to a lambda expression. +#### Before + +```java +public void method() { + Runnable runnable = new Runnable(){ + @Override + public void run() { + // do something + } + }; +} +``` +#### After +```java +public void method() { + Runnable runnable = () -> { + // do something + }; + } +``` +> Also see: [Convert to anonymous class creation](#convert-to-anonymous-class-creation) + +--- + +## Convert to static import +Converts the field or method to static import. + +### Example +Let's transform the `Assert.assertEquals()` invocation to a static import. +#### Before + +```java +import org.junit.Assert; +... +public void test() { + Assert.assertEquals(expected, actual); +} +``` +#### After +```java +import static org.junit.Assert.assertEquals; +... +public void test() { + assertEquals(expected, actual); +} +``` + +--- + +## Extract to constant +Creates a static final field from the selected expression and substitutes a field reference, then rewrites other places where the same expression occurs. + +### Examples +Let's extract the value of π: `3.14` to a constant. +#### Before + +```java +public double getArea(double r) { + return 3.14 * r * r; +} +``` +#### After +```java +private static final double PI = 3.14; + +public double getArea(double r) { + return PI * r * r; +} +``` + +> Also see: [Inline constant](#inline-constant) + +--- + +## Extract to field +Declares a new field and initializes it with the selected expression. The original expression is replaced with the usage of the field. + +### Examples +Let's extract the variable `area` to a field of the class `Square`. +#### Before + +```java +class Square { + public void calculateArea() { + int height = 1; + int width = 2; + int area = height * width; + } +} +``` +#### After +```java +class Square { + private int area; + + public void calculateArea() { + int height = 1; + int width = 2; + area = height * width; + } +} +``` + +--- + +## Extract to method +Creates a new method containing the statements or expressions currently selected and replaces the selection with a reference to the new method. This feature is useful for cleaning up lengthy, cluttered, or overly-complicated methods. + +### Examples +Let's extract the expression `height * width` to a new method. +#### Before + +```java +public void method() { + int height = 1; + int width = 2; + int area = height * width; +} +``` +#### After +```java +public void method() { + int height = 1; + int width = 2; + int area = getArea(height, width); +} + +private int getArea(int height, int width) { + return height * width; +} +``` + +> Also see: [Inline method](#inline-method) + +--- + +## Extract to local variable +Creates a new variable assigned to the expression currently selected and replaces the selection with a reference to the new variable. + +### Examples +Let's extract the expression `platform.equalsIgnoreCase("MAC")` to a new variable. +#### Before + +```java +public void method() { + if (platform.equalsIgnoreCase("MAC")) { + // do something + } +} +``` +#### After +```java +public void method() { + boolean isMac = platform.equalsIgnoreCase("MAC"); + if (isMac) { + // do something + } +} +``` + +> Also see: [Inline local variable](#inline-local-variable) + +--- + +## Inline constant +Replaces a constant reference with its defined value. + +### Examples +Let's replace the constant `PI` to its defined value: `3.14`. +#### Before + +```java +private static final double PI = 3.14; + +public double getArea(double r) { + return PI * r * r; +} +``` + +#### After +```java +private static final double PI = 3.14; + +public double getArea(double r) { + return 3.14 * r * r; +} +``` + +> Also see: [Extract to constant](#extract-to-constant) + +--- + +## Inline local variable +Replaces redundant variable usage with its initializer. + +### Examples +Let's replace the variable `isMac` directly to the boolean expression. +#### Before + +```java +public void method() { + boolean isMac = platform.equalsIgnoreCase("MAC"); + if (isMac) { + // do something + } +} +``` +#### After +```java +public void method() { + if (platform.equalsIgnoreCase("MAC")) { + // do something + } +} +``` + +> Also see: [Extract to local variable](#extract-to-local-variable) + +--- + +## Inline method +Replaces calls to the method with the method’s body. + +### Example +Let's replace the method `getArea(int height, int width)` directly to the expression `height * width`. +#### Before + +```java +public void method() { + int height = 1; + int width = 2; + int area = getArea(height, width); +} + +private int getArea(int height, int width) { + return height * width; +} +``` +#### After +```java +public void method() { + int height = 1; + int width = 2; + int area = height * width; +} +``` + +> Also see: [Extract to method](#extract-to-method) + +--- + +## Introduce Parameter +Replaces an expression with a reference to a new method parameter, and updates all callers of the method to pass the expression as the value of that parameter. + +### Example +Let's introduce a new parameter for the method `public void addUser()`. + +#### Before +```java +public void buildRegistry() { + addUser(); +} + +public void addUser() { + fUsers.add("Administrator"); +} +``` +#### After +```java +public void buildRegistry() { + addUser("Administrator"); +} + +public void addUser(String name) { + fUsers.add(name); +} +``` + +--- + +## Change Method Signature +Changes the method visibility, return type, name, and updates the parameters and exceptions. The above changes can be applied through the call hierarchy of the method. + +### Example +Let's change signature for the method `public void setAddress(String address)`. + +#### Before + +```java +public void setAddress(String address) { + this.address = address; +} + +public void setAddr() { + this.setAddress("Addr"); +} +``` + +#### Refactor configuration + +![change_signature](./refactoring_change_signature.png) +#### After +```java +public void setAddress1(Object newParam, String address) { + this.address = address; +} + +public void setAddr() { + this.setAddress1(null, "Addr"); +} +``` +--- + +## Invert conditions +Inverts the boolean expression in the conditions. + +### Example +Let's invert the boolean expression in the if statement. + +#### Before +```java +public void method(int value) { + if (value > 5 && value < 15) { + // do something + } +} +``` +#### After +```java +public void method(int value) { + if (value <= 5 || value >= 15) { + // do something + } +} +``` + +--- + +## Invert local variable +Inverts the local boolean variable. + +### Example +Let's invert the variable `valid`. + +#### Before +```java +public void method(int value) { + boolean valid = value > 5 && value < 15; +} +``` +#### After +```java +public void method(int value) { + boolean notValid = value <= 5 || value >= 15; +} +``` + +--- + +## Move +Moves the selected elements and corrects all references to the elements (also in other files). Available actions are: +- Move class to another package +- Move static or instance method to another class +- Move inner class to a new file + +### Examples +Let's move the static method `print()` from class `Office` to class `Printer`. +#### Before + +```java +public class Office { + public static void main(String[] args) { + print(); + } + + public static void print() { + System.out.println("This is printer"); + } + + static class Printer { } +} +``` + +#### After +```java +public class Office { + public static void main(String[] args) { + Printer.print(); + } + + static class Printer { + public static void print() { + System.out.println("This is printer"); + } + } +} +``` + +--- + +## Rename + +**_Default shortcut:_ F2** + +Renames the selected element and corrects all references to the elements (also in other files). + +### Examples +Let's rename the class `Foo` to `Bar` +#### Before + +```java +public class Foo { + // ... +} + +public void myMethod() { + Foo myClass = new Foo(); +} +``` +#### After +```java +public class Bar { + // ... +} + +public void myMethod() { + Bar myClass = new Bar(); +} +``` + +--- + +## Change resolved type to var type +Uses `var` to declare local variables. + +### Examples +#### Before + +```java +String s = ""; +``` +#### After +```java +var s = ""; +``` + +> Also see: [Change var type to resolved type](#change-var-type-to-resolved-type) + +--- + +## Change var type to resolved type +Uses the resolved type to declare local variables. + +### Examples +#### Before + +```java +var s = ""; +``` +#### After +```java +String s = ""; +``` + +> Also see: [Change resolved type to var type](#change-resolved-type-to-var-type) \ No newline at end of file diff --git a/document/_java.metadataFilesGeneration.md b/document/_java.metadataFilesGeneration.md new file mode 100644 index 0000000000..4239b54c81 --- /dev/null +++ b/document/_java.metadataFilesGeneration.md @@ -0,0 +1,21 @@ +# Metadata Files Generation + +We use the setting `java.import.generatesMetadataFilesAtProjectRoot` to control where the project metadata files(.project, .classpath, .factorypath, .settings/) will be generated: +- `true`: Metadata files will be generated at the project's root. +- `false`: Metadata files will be generated at the workspace storage. To be specific, the path will be: `/redhat.java/jdt_ws/.metadata/.plugins/org.eclipse.core.resources/.projects//`. + +By default, the setting is set to `false`. + +> If the metadata files exist in both the project root and the workspace storage, the extension will pick the files in the project root. + +## Change the setting value + +Depending on how you change the setting, some extra steps need to be taken to make the change take effect. + +### Change from `false` to `true` +You need to restart the client. + +### Change from `true` to `false` +1. Close the client. +2. Remove the metadata files in the project by your own. +3. Open the client. diff --git a/document/_java.notCoveredExecution.md b/document/_java.notCoveredExecution.md new file mode 100644 index 0000000000..9ac8b9c1da --- /dev/null +++ b/document/_java.notCoveredExecution.md @@ -0,0 +1,111 @@ +# Not Covered Maven Plugin Execution + +## Background +Some Maven projects use 3rd party Maven plugins to generate sources or resources, and you may find that the generated code is not picked up by the project classpath, or the Maven goals are not executed by Java extension. This is a known technical issue with `m2e`, the underlying Maven integration tool for Java extension. The reason is that the Maven tooling `m2e` doesn't know if it's safe to run your Maven plugin automatically during a workspace build, so it does not run them by default and requires explicit instructions on how to handle them. Learn more about this issue from the wiki about [Execution Not Covered](https://www.eclipse.org/m2e/documentation/m2e-execution-not-covered.html). + +## Workaround +- Option 1: The best thing is still to request the Maven plugin authors to provide native integration with m2e. Here is a guideline on [how to make Maven plugins compatible with m2e](https://www.eclipse.org/m2e/documentation/m2e-making-maven-plugins-compat.html). + +- Option 2: Use [build-helper-maven-plugin](http://www.mojohaus.org/build-helper-maven-plugin/usage.html) to explicitly add the unrecognized source folder to classpath. + +```xml + + ... + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + add-source + generate-sources + + add-source + + + + some directory + ... + + + + + + + + +``` + +- Option 3: Configure a lifecycle mapping metadata in pom.xml that explicitly tells m2e what to do with your plugin. + +For example, add [a processing instruction in the pom.xml](https://www.eclipse.org/m2e/documentation/release-notes-17.html#new-syntax-for-specifying-lifecycle-mapping-metadata) like `` to execute it on every project configuration update. + +You can use quick fixes to generate the inline lifecycle mapping in pom.xml, or manually configure it in pom.xml. If it's yourself that manually configure it, you have to let VS Code update the project configuration as well. The command is `"Java: Reload Projects"`. + +```xml + + ... + + + + ro.isdc.wro4j + wro4j-maven-plugin + 1.8.0 + + + + generate-resources + + run + + + + + + + +``` + +If you have multiple Maven plugins that need to configure the lifecycle mapping metadata, you can also configure them together in a dedicated `pluginManagement` section. + +```xml + + ... + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + ro.isdc.wro4j + wro4j-maven-plugin + [1.8.0,) + + run + + + + + true + + + + + + + + + + + +``` diff --git a/document/_java.templateVariables.md b/document/_java.templateVariables.md new file mode 100644 index 0000000000..f3f78c5d0d --- /dev/null +++ b/document/_java.templateVariables.md @@ -0,0 +1,15 @@ +# Predefined Variables for Java Template Snippets + +Below are the predefined variables you could use in the template settings such as `java.templates.fileHeader` and `java.templates.typeComment`. +- `${file_name}` - name of the current Java file +- `${package_name}` - name of the enclosing package +- `${type_name}` - name of the current type +- `${user}` - current user system login name +- `${date}` - current system date +- `${time}` - current system time +- `${year}` - current year +- `${month}` - current month +- `${shortmonth}` - short form representation of current month +- `${day}` - current day of the month +- `${hour}` - current hour +- `${minute}` - current minute diff --git a/document/refactoring_change_signature.png b/document/refactoring_change_signature.png new file mode 100644 index 0000000000..6690f7471f Binary files /dev/null and b/document/refactoring_change_signature.png differ diff --git a/document/refactoring_menu.png b/document/refactoring_menu.png new file mode 100644 index 0000000000..53caef0d03 Binary files /dev/null and b/document/refactoring_menu.png differ diff --git a/formatters/eclipse-formatter.xml b/formatters/eclipse-formatter.xml index 0f7be6f295..8b078b85ac 100644 --- a/formatters/eclipse-formatter.xml +++ b/formatters/eclipse-formatter.xml @@ -1,315 +1,405 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - + + + + - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 93450e0d25..0000000000 --- a/gulpfile.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -const gulp = require('gulp'); -const cp = require('child_process'); -const decompress = require('gulp-decompress'); -const download = require('gulp-download'); -const server_dir = '../eclipse.jdt.ls'; -//... - -gulp.task('download_server', function(done) { - download("http://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz") - .pipe(decompress()) - .pipe(gulp.dest('./server')); - done(); -}); - -gulp.task('build_server', function(done) { - cp.execSync(mvnw()+ ' -Pserver-distro clean package', {cwd:server_dir, stdio:[0,1,2]} ); - gulp.src(server_dir + '/org.eclipse.jdt.ls.product/distro/*.tar.gz') - .pipe(decompress()) - .pipe(gulp.dest('./server')); - done(); -}); - -gulp.task('dev_server', function(done) { - let command = mvnw() +' -Pserver-distro,fast -o clean package '; - if(isLinux()){ - command +='-Denvironment.os=linux -Denvironment.ws=gtk -Denvironment.arch=x86_64'; - } - else if(isMac()){ - command += '-Denvironment.os=macosx -Denvironment.ws=cocoa -Denvironment.arch=x86_64'; - } - else if(isWin()){ - command += '-Denvironment.os=win32 -Denvironment.ws=win32 -Denvironment.arch=x86_64'; - } - console.log('executing '+command); - cp.execSync(command, {cwd:server_dir, stdio:[0,1,2]} ); - gulp.src(server_dir +'/org.eclipse.jdt.ls.product/distro/*.tar.gz') - .pipe(decompress()) - .pipe(gulp.dest('./server')) - done(); -}); - -gulp.task('watch_server',function(done) { - gulp.watch(server_dir+'/org.eclipse.jdt.ls.core/**/*.java',['dev_server']); - done(); -}); - -function isWin() { - return /^win/.test(process.platform); -} - -function isMac() { - return /^darwin/.test(process.platform); -} - -function isLinux() { - return /^linux/.test(process.platform); -} - -function mvnw() { - return isWin()?"mvnw.cmd":"./mvnw"; -} diff --git a/icons/icon24.png b/icons/icon24.png new file mode 100644 index 0000000000..41e133d27c Binary files /dev/null and b/icons/icon24.png differ diff --git a/icons/java-svgrepo-com.svg b/icons/java-svgrepo-com.svg new file mode 100644 index 0000000000..17ea0060c1 --- /dev/null +++ b/icons/java-svgrepo-com.svg @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/images/changelog/ChooseProduct.png b/images/changelog/ChooseProduct.png new file mode 100644 index 0000000000..0e7ecacb3d Binary files /dev/null and b/images/changelog/ChooseProduct.png differ diff --git a/images/changelog/ClientPort.png b/images/changelog/ClientPort.png new file mode 100644 index 0000000000..1512f06cbc Binary files /dev/null and b/images/changelog/ClientPort.png differ diff --git a/images/changelog/CreateNewConfiguration.png b/images/changelog/CreateNewConfiguration.png new file mode 100644 index 0000000000..b595253f2c Binary files /dev/null and b/images/changelog/CreateNewConfiguration.png differ diff --git a/images/changelog/DebugConfigurationOpen.png b/images/changelog/DebugConfigurationOpen.png new file mode 100644 index 0000000000..31efbe144b Binary files /dev/null and b/images/changelog/DebugConfigurationOpen.png differ diff --git a/images/changelog/DebugRemoteServer.png b/images/changelog/DebugRemoteServer.png new file mode 100644 index 0000000000..25c8070138 Binary files /dev/null and b/images/changelog/DebugRemoteServer.png differ diff --git a/images/changelog/RemoteServer.png b/images/changelog/RemoteServer.png new file mode 100644 index 0000000000..74e87d267a Binary files /dev/null and b/images/changelog/RemoteServer.png differ diff --git a/images/changelog/RemoteServerInVSCode.png b/images/changelog/RemoteServerInVSCode.png new file mode 100644 index 0000000000..c22813b97c Binary files /dev/null and b/images/changelog/RemoteServerInVSCode.png differ diff --git a/images/changelog/SocketSteamInVSCode.png b/images/changelog/SocketSteamInVSCode.png new file mode 100644 index 0000000000..325b87d96a Binary files /dev/null and b/images/changelog/SocketSteamInVSCode.png differ diff --git a/images/changelog/importMavenProject.png b/images/changelog/importMavenProject.png new file mode 100644 index 0000000000..c9f1c272d6 Binary files /dev/null and b/images/changelog/importMavenProject.png differ diff --git a/images/changelog/importProject.png b/images/changelog/importProject.png new file mode 100644 index 0000000000..eb81182d52 Binary files /dev/null and b/images/changelog/importProject.png differ diff --git a/images/changelog/importedMavenProject.png b/images/changelog/importedMavenProject.png new file mode 100644 index 0000000000..556d5fb77f Binary files /dev/null and b/images/changelog/importedMavenProject.png differ diff --git a/images/changelog/loadingTargetPlatform.png b/images/changelog/loadingTargetPlatform.png new file mode 100644 index 0000000000..5b87fe624a Binary files /dev/null and b/images/changelog/loadingTargetPlatform.png differ diff --git a/images/changelog/reloadTargetPlatform.png b/images/changelog/reloadTargetPlatform.png new file mode 100644 index 0000000000..d25092da61 Binary files /dev/null and b/images/changelog/reloadTargetPlatform.png differ diff --git a/images/changelog/setTargetPlatform.png b/images/changelog/setTargetPlatform.png new file mode 100644 index 0000000000..3ab2d32f93 Binary files /dev/null and b/images/changelog/setTargetPlatform.png differ diff --git a/language-configuration.json b/language-configuration.json deleted file mode 100644 index bf48f2fc81..0000000000 --- a/language-configuration.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ - "/*", - "*/" - ] - }, - "brackets": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ] - ], - "autoClosingPairs": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "\"", - "\"" - ], - [ - "'", - "'" - ], - { - "open": "/**", - "close": " */", - "notIn": [ - "string" - ] - } - ], - "surroundingPairs": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "\"", - "\"" - ], - [ - "'", - "'" - ], - [ - "<", - ">" - ] - ] -} \ No newline at end of file diff --git a/language-support/html/inline-html.json b/language-support/html/inline-html.json new file mode 100644 index 0000000000..b40dbf2a11 --- /dev/null +++ b/language-support/html/inline-html.json @@ -0,0 +1,44 @@ +{ + "injectionSelector": "L:source.java -comment -string", + "patterns": [ + { + "contentName": "meta.embedded.block.html", + "begin": "(?i)((/\\*\\s*(language=html)\\s*\\*/)|((//\\s*(language=html)\\s*)))", + "beginCaptures": { + "1": { + "name": "comment.block" + } + }, + "end": "(?<=\")", + "patterns": [ + { + "begin": "\\s*(\"\"\")$", + "beginCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "end": "\\s*(\"\"\")", + "endCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "patterns": [ + { "include": "text.html.derivative" } + ] + }, + { + "begin": "\\s*(\")", + "beginCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "end": "\\s*(\")", + "endCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "patterns": [ + { "include": "text.html.derivative" } + ] + } + ] + } + ], + "scopeName": "inline.html" +} diff --git a/language-support/java/java.tmLanguage.json b/language-support/java/java.tmLanguage.json new file mode 100644 index 0000000000..2bdf9bf0e9 --- /dev/null +++ b/language-support/java/java.tmLanguage.json @@ -0,0 +1,1888 @@ +{ + "information_for_contributors": [ + "This file has been copied from https://github.com/microsoft/vscode/blob/b37252c18238fffcebdc9fd7680f1dabea3a50a0/extensions/java/syntaxes/java.tmLanguage.json", + "The source location lists https://github.com/atom/language-java/blob/29f977dc42a7e2568b39bb6fb34c4ef108eb59b3/LICENSE.md as the original repository. It is therefore licensed under MIT." + ], + "name": "Java", + "scopeName": "source.java", + "patterns": [ + { + "begin": "\\b(package)\\b\\s*", + "beginCaptures": { + "1": { + "name": "keyword.other.package.java" + } + }, + "end": "\\s*(;)", + "endCaptures": { + "1": { + "name": "punctuation.terminator.java" + } + }, + "name": "meta.package.java", + "contentName": "storage.modifier.package.java", + "patterns": [ + { + "include": "#comments" + }, + { + "match": "(?<=\\.)\\s*\\.|\\.(?=\\s*;)", + "name": "invalid.illegal.character_not_allowed_here.java" + }, + { + "match": "(?", + "endCaptures": { + "0": { + "name": "punctuation.bracket.angle.java" + } + }, + "patterns": [ + { + "match": "\\b(extends|super)\\b", + "name": "storage.modifier.$1.java" + }, + { + "match": "(?>>?|~|\\^)", + "name": "keyword.operator.bitwise.java" + }, + { + "match": "((&|\\^|\\||<<|>>>?)=)", + "name": "keyword.operator.assignment.bitwise.java" + }, + { + "match": "(===?|!=|<=|>=|<>|<|>)", + "name": "keyword.operator.comparison.java" + }, + { + "match": "([+*/%-]=)", + "name": "keyword.operator.assignment.arithmetic.java" + }, + { + "match": "(=)", + "name": "keyword.operator.assignment.java" + }, + { + "match": "(\\-\\-|\\+\\+)", + "name": "keyword.operator.increment-decrement.java" + }, + { + "match": "(\\-|\\+|\\*|\\/|%)", + "name": "keyword.operator.arithmetic.java" + }, + { + "match": "(!|&&|\\|\\|)", + "name": "keyword.operator.logical.java" + }, + { + "match": "(\\||&)", + "name": "keyword.operator.bitwise.java" + }, + { + "match": "\\b(const|goto)\\b", + "name": "keyword.reserved.java" + } + ] + }, + "lambda-expression": { + "patterns": [ + { + "match": "->", + "name": "storage.type.function.arrow.java" + } + ] + }, + "member-variables": { + "begin": "(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)", + "end": "(?=\\=|;)", + "patterns": [ + { + "include": "#storage-modifiers" + }, + { + "include": "#variables" + }, + { + "include": "#primitive-arrays" + }, + { + "include": "#object-types" + } + ] + }, + "method-call": { + "begin": "(\\.)\\s*([A-Za-z_$][\\w$]*)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.separator.period.java" + }, + "2": { + "name": "entity.name.function.java" + }, + "3": { + "name": "punctuation.definition.parameters.begin.bracket.round.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.bracket.round.java" + } + }, + "name": "meta.method-call.java", + "patterns": [ + { + "include": "#code" + } + ] + }, + "methods": { + "begin": "(?!new)(?=[\\w<].*\\s+)(?=([^=/]|/(?!/))+\\()", + "end": "(})|(?=;)", + "endCaptures": { + "1": { + "name": "punctuation.section.method.end.bracket.curly.java" + } + }, + "name": "meta.method.java", + "patterns": [ + { + "include": "#storage-modifiers" + }, + { + "begin": "(\\w+)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.java" + }, + "2": { + "name": "punctuation.definition.parameters.begin.bracket.round.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.bracket.round.java" + } + }, + "name": "meta.method.identifier.java", + "patterns": [ + { + "include": "#parameters" + }, + { + "include": "#parens" + }, + { + "include": "#comments" + } + ] + }, + { + "include": "#generics" + }, + { + "begin": "(?=\\w.*\\s+\\w+\\s*\\()", + "end": "(?=\\s+\\w+\\s*\\()", + "name": "meta.method.return-type.java", + "patterns": [ + { + "include": "#all-types" + }, + { + "include": "#parens" + }, + { + "include": "#comments" + } + ] + }, + { + "include": "#throws" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.method.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.method.body.java", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "include": "#comments" + } + ] + }, + "module": { + "begin": "((open)\\s)?(module)\\s+(\\w+)", + "end": "}", + "beginCaptures": { + "1": { + "name": "storage.modifier.java" + }, + "3": { + "name": "storage.modifier.java" + }, + "4": { + "name": "entity.name.type.module.java" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.section.module.end.bracket.curly.java" + } + }, + "name": "meta.module.java", + "patterns": [ + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.module.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.module.body.java", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#comments-javadoc" + }, + { + "match": "\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b", + "name": "keyword.module.java" + } + ] + } + ] + }, + "numbers": { + "patterns": [ + { + "match": "(?x)\n\\b(?)?(\\()", + "beginCaptures": { + "1": { + "name": "storage.modifier.java" + }, + "2": { + "name": "entity.name.type.record.java" + }, + "3": { + "patterns": [ + { + "include": "#generics" + } + ] + }, + "4": { + "name": "punctuation.definition.parameters.begin.bracket.round.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.bracket.round.java" + } + }, + "name": "meta.record.identifier.java", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "begin": "(implements)\\s", + "beginCaptures": { + "1": { + "name": "storage.modifier.implements.java" + } + }, + "end": "(?=\\s*\\{)", + "name": "meta.definition.class.implemented.interfaces.java", + "patterns": [ + { + "include": "#object-types-inherited" + }, + { + "include": "#comments" + } + ] + }, + { + "include": "#record-body" + } + ] + }, + "record-body": { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.class.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "name": "meta.record.body.java", + "patterns": [ + { + "include": "#record-constructor" + }, + { + "include": "#class-body" + } + ] + }, + "record-constructor": { + "begin": "(?!new)(?=[\\w<].*\\s+)(?=([^\\(=/]|/(?!/))+(?={))", + "end": "(})|(?=;)", + "endCaptures": { + "1": { + "name": "punctuation.section.method.end.bracket.curly.java" + } + }, + "name": "meta.method.java", + "patterns": [ + { + "include": "#storage-modifiers" + }, + { + "begin": "(\\w+)", + "beginCaptures": { + "1": { + "name": "entity.name.function.java" + } + }, + "end": "(?=\\s*{)", + "name": "meta.method.identifier.java", + "patterns": [ + { + "include": "#comments" + } + ] + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.method.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.method.body.java", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + "static-initializer": { + "patterns": [ + { + "include": "#anonymous-block-and-instance-initializer" + }, + { + "match": "static", + "name": "storage.modifier.java" + } + ] + }, + "storage-modifiers": { + "match": "\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp|sealed|non-sealed)\\b", + "name": "storage.modifier.java" + }, + "strings": { + "patterns": [ + { + "begin": "\"\"\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.java" + } + }, + "end": "\"\"\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.java" + } + }, + "name": "string.quoted.triple.java", + "patterns": [ + { + "match": "(\\\\\"\"\")(?!\")|(\\\\.)", + "name": "constant.character.escape.java" + } + ] + }, + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.java" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.java" + } + }, + "name": "string.quoted.double.java", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.java" + } + ] + }, + { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.java" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.java" + } + }, + "name": "string.quoted.single.java", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.java" + } + ] + } + ] + }, + "throws": { + "begin": "throws", + "beginCaptures": { + "0": { + "name": "storage.modifier.java" + } + }, + "end": "(?={|;)", + "name": "meta.throwables.java", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.delimiter.java" + }, + { + "match": "[a-zA-Z$_][\\.a-zA-Z0-9$_]*", + "name": "storage.type.java" + }, + { + "include": "#comments" + } + ] + }, + "try-catch-finally": { + "patterns": [ + { + "begin": "\\btry\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.try.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.try.end.bracket.curly.java" + } + }, + "name": "meta.try.java", + "patterns": [ + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.try.resources.begin.bracket.round.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.try.resources.end.bracket.round.java" + } + }, + "name": "meta.try.resources.java", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.try.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.try.body.java", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + { + "begin": "\\b(catch)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.catch.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.catch.end.bracket.curly.java" + } + }, + "name": "meta.catch.java", + "patterns": [ + { + "include": "#comments" + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.bracket.round.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.bracket.round.java" + } + }, + "contentName": "meta.catch.parameters.java", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#storage-modifiers" + }, + { + "begin": "[a-zA-Z$_][\\.a-zA-Z0-9$_]*", + "beginCaptures": { + "0": { + "name": "storage.type.java" + } + }, + "end": "(\\|)|(?=\\))", + "endCaptures": { + "1": { + "name": "punctuation.catch.separator.java" + } + }, + "patterns": [ + { + "include": "#comments" + }, + { + "match": "\\w+", + "captures": { + "0": { + "name": "variable.parameter.java" + } + } + } + ] + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.catch.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.catch.body.java", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + { + "begin": "\\bfinally\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.finally.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.finally.end.bracket.curly.java" + } + }, + "name": "meta.finally.java", + "patterns": [ + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.finally.begin.bracket.curly.java" + } + }, + "end": "(?=})", + "contentName": "meta.finally.body.java", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + } + ] + }, + "variables": { + "begin": "(?x)\n(?=\n \\b\n (\n (void|boolean|byte|char|short|int|float|long|double)\n |\n (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String`\n )\n \\b\n \\s*\n (\n <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List`\n )?\n \\s*\n (\n (\\[\\])* # int[][]\n )?\n \\s+\n [A-Za-z_$][\\w$]* # At least one identifier after space\n ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers\n \\s*(=|:|;)\n)", + "end": "(?=\\=|:|;)", + "name": "meta.definition.variable.java", + "patterns": [ + { + "match": "([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(;|:|=|,))", + "captures": { + "1": { + "name": "variable.other.definition.java" + } + } + }, + { + "include": "#all-types" + }, + { + "include": "#code" + } + ] + }, + "variables-local": { + "begin": "(?=\\b(var)\\b\\s+[A-Za-z_$][\\w$]*\\s*(=|:|;))", + "end": "(?=\\=|:|;)", + "name": "meta.definition.variable.local.java", + "patterns": [ + { + "match": "\\bvar\\b", + "name": "storage.type.local.java" + }, + { + "match": "([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(=|:|;))", + "captures": { + "1": { + "name": "variable.other.definition.java" + } + } + }, + { + "include": "#code" + } + ] + } + } +} diff --git a/language-support/java/language-configuration.json b/language-support/java/language-configuration.json new file mode 100644 index 0000000000..90e2c5fece --- /dev/null +++ b/language-support/java/language-configuration.json @@ -0,0 +1,226 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": [ + "/*", + "*/" + ] + }, + "brackets": [ + [ + "{", + "}" + ], + [ + "[", + "]" + ], + [ + "(", + ")" + ], + [ + "\"\"\"", + "\"\"\"" + ] + ], + "autoClosingPairs": [ + [ + "{", + "}" + ], + [ + "[", + "]" + ], + [ + "(", + ")" + ], + { + "open": "\"", + "close": "\"", + "notIn": [ + "string" + ] + }, + [ + "'", + "'" + ], + { + "open": "/*", + "close": " */", + "notIn": [ + "string" + ] + }, + { + "open": "\"\"\"", + "close": "\"\"\";", + "notIn": [ + "comment" + ] + } + ], + "surroundingPairs": [ + [ + "{", + "}" + ], + [ + "[", + "]" + ], + [ + "(", + ")" + ], + [ + "\"", + "\"" + ], + [ + "'", + "'" + ], + [ + "<", + ">" + ] + ], + "autoCloseBefore": ";:.,=}])>` \n\t", + "folding": { + "markers": { + "start": "^\\s*//\\s*#?region\\b", + "end": "^\\s*//\\s*#?endregion\\b" + } + }, + "wordPattern": { + "pattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)" + }, + "indentationRules": { + "decreaseIndentPattern": { + "pattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$" + }, + "increaseIndentPattern": { + "pattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$" + }, + "unIndentedLinePattern": { + "pattern": "^(\\t|[ ])*[ ]\\*[^/]*\\*/\\s*$|^(\\t|[ ])*[ ]\\*/\\s*$|^(\\t|[ ])*[ ]\\*([ ]([^\\*]|\\*(?!/))*)?$" + }, + "indentNextLinePattern": { + "pattern": "^((.*=>\\s*)|((.*[^\\w]+|\\s*)((if|while|for)\\s*\\(.*\\)\\s*|else\\s*)))$" + } + }, + "onEnterRules": [ + { + "beforeText": { + "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$" + }, + "afterText": { + "pattern": "^\\s*\\*/$" + }, + "action": { + "indent": "indentOutdent", + "appendText": " * " + } + }, + { + "beforeText": { + "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$" + }, + "action": { + "indent": "none", + "appendText": " * " + } + }, + { + "beforeText": { + "pattern": "^(\\t|[ ])*[ ]\\*([ ]([^\\*]|\\*(?!/))*)?$" + }, + "previousLineText": { + "pattern": "(?=^(\\s*(/\\*\\*|\\*)).*)(?=(?!(\\s*\\*/)))" + }, + "action": { + "indent": "none", + "appendText": "* " + } + }, + { + "beforeText": { + "pattern": "^(\\t|[ ])*[ ]\\*/\\s*$" + }, + "action": { + "indent": "none", + "removeText": 1 + } + }, + { + "beforeText": { + "pattern": "^(\\t|[ ])*[ ]\\*[^/]*\\*/\\s*$" + }, + "action": { + "indent": "none", + "removeText": 1 + } + }, + { + "beforeText": { + "pattern": "^\\s*(\\bcase\\s.+:|\\bdefault:)$" + }, + "afterText": { + "pattern": "^(?!\\s*(\\bcase\\b|\\bdefault\\b))" + }, + "action": { + "indent": "indent" + } + }, + { + "previousLineText": "^\\s*(((else ?)?if|for|while)\\s*\\(.*\\)\\s*|else\\s*)$", + "beforeText": "^\\s+([^{i\\s]|i(?!f\\b))", + "action": { + "indent": "outdent" + } + }, + { + "beforeText": "^.*\\([^\\)]*$", + "afterText": "^\\s*\\).*$", + "action": { + "indent": "indentOutdent", + "appendText": "\t" + } + }, + { + "beforeText": "^.*\\{[^\\}]*$", + "afterText": "^\\s*\\}.*$", + "action": { + "indent": "indentOutdent", + "appendText": "\t" + } + }, + { + "beforeText": "^.*\\[[^\\]]*$", + "afterText": "^\\s*\\].*$", + "action": { + "indent": "indentOutdent", + "appendText": "\t" + } + }, + { + "beforeText": "(?<([^<>]|\\g)+>)?", + "captures": { + "1": { + "name": "storage.type.class.kotlin" + }, + "2": { + "name": "entity.name.type.class.kotlin" + }, + "3": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "object-declaration": { + "match": "\\b(object)\\s+(\\b\\w+\\b|`[^`]+`)", + "captures": { + "1": { + "name": "storage.type.object.kotlin" + }, + "2": { + "name": "entity.name.type.object.kotlin" + } + } + }, + "type-alias": { + "match": "\\b(typealias)\\s+(\\b\\w+\\b|`[^`]+`)\\s*(?<([^<>]|\\g)+>)?", + "captures": { + "1": { + "name": "storage.type.alias.kotlin" + }, + "2": { + "name": "entity.name.type.kotlin" + }, + "3": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "function-declaration": { + "begin": "\\b(fun)\\b\\s*(?<([^<>]|\\g)+>)?\\s*(?:(\\w+)\\.)?(\\b\\w+\\b|`[^`]+`)\\(", + "beginCaptures": { + "1": { + "name": "storage.type.function.kotlin" + }, + "2": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + }, + "4": { + "name": "entity.name.type.class.extension.kotlin" + }, + "5": { + "name": "entity.name.function.declaration.kotlin" + } + }, + "end": "\\)", + "endCaptures": { + "1": { + "name": "keyword.operator.assignment.type.kotlin" + } + }, + "patterns": [ + { + "include": "#parameter-declaration" + } + ] + }, + "parameter-declaration": { + "match": "\\b(\\w+)\\s*(:)\\s*(\\w+)(\\?)?(,)?", + "captures": { + "1": { + "name": "variable.parameter.kotlin" + }, + "2": { + "name": "keyword.operator.assignment.type.kotlin" + }, + "3": { + "name": "entity.name.type.kotlin" + }, + "4": { + "name": "keyword.operator.optional" + }, + "5": { + "name": "punctuation.separator.delimiter.kotlin" + } + } + }, + "variable-declaration": { + "match": "\\b(var)\\b\\s*(?<([^<>]|\\g)+>)?", + "captures": { + "1": { + "name": "storage.type.variable.kotlin" + }, + "2": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "constant-declaration": { + "match": "\\b(val)\\b\\s*(?<([^<>]|\\g)+>)?", + "captures": { + "1": { + "name": "storage.type.variable.readonly.kotlin" + }, + "2": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "variable" : { + "match": "\\b(\\w+)(?=\\s*[:=])", + "captures": { + "1": { + "name": "variable.other.definition.kotlin" + } + } + }, + "object" : { + "match": "\\b(\\w+)(?=\\.)", + "captures": { + "1": { + "name": "variable.other.object.kotlin" + } + } + }, + "type-parameter": { + "patterns": [ + { + "match": "(:)?\\s*(\\b\\w+\\b)(\\?)?", + "captures": { + "1": { + "name": "keyword.operator.assignment.kotlin" + }, + "2": { + "name": "entity.name.type.kotlin" + }, + "3": { + "name": "keyword.operator.optional" + } + } + }, + { + "match": "\\b(in|out)\\b", + "name": "storage.modifier.kotlin" + } + ] + }, + "type-annotation": { + "match": "(?|(?[<(]([^<>()\"']|\\g)+[)>]))+", + "captures": { + "0": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "function-call": { + "match": "(?:(\\?\\.)|(\\.))?(\\b\\w+\\b|`[^`]+`)\\s*(?<([^<>]|\\g)+>)?\\s*(?=[({])", + "captures": { + "1": { + "name": "punctuation.accessor.optional.kotlin" + }, + "2": { + "name": "punctuation.separator.period.kotlin" + }, + "3": { + "name": "entity.name.function.call.kotlin" + }, + "4": { + "patterns": [ + { + "include": "#type-parameter" + } + ] + } + } + }, + "property.reference": { + "match": "(?:(\\?\\.)|(\\.))(\\w+)\\b", + "captures": { + "1": { + "name": "punctuation.accessor.optional.kotlin" + }, + "2": { + "name": "punctuation.separator.period.kotlin" + }, + "3": { + "name": "variable.other.property.kotlin" + } + } + }, + "method-reference": { + "match": "\\??::(\\b\\w+\\b|`[^`]+`)", + "captures": { + "1": { + "name": "entity.name.function.reference.kotlin" + } + } + }, + "key": { + "match": "\\b(\\w=)\\s*(=)", + "captures": { + "1": { + "name": "variable.parameter.kotlin" + }, + "2": { + "name": "keyword.operator.assignment.kotlin" + } + } + }, + "string-empty": { + "match": "(?", + "name": "storage.type.function.arrow.kotlin" + }, + "operators": { + "patterns": [ + { + "match": "(===?|\\!==?|<=|>=|<|>)", + "name": "keyword.operator.comparison.kotlin" + }, + { + "match": "(\\?:)", + "name": "keyword.operator.elvis.kotlin" + }, + { + "match": "([+*/%-]=)", + "name": "keyword.operator.assignment.arithmetic.kotlin" + }, + { + "match": "(=)", + "name": "keyword.operator.assignment.kotlin" + }, + { + "match": "([+*/%-])", + "name": "keyword.operator.arithmetic.kotlin" + }, + { + "match": "(!|&&|\\|\\|)", + "name": "keyword.operator.logical.kotlin" + }, + { + "match": "(--|\\+\\+)", + "name": "keyword.operator.increment-decrement.kotlin" + }, + { + "match": "(\\.\\.)", + "name": "keyword.operator.range.kotlin" + } + ] + }, + "self-reference": { + "match": "\\b(this|super)(@\\w+)?\\b", + "name": "variable.language.this.kotlin" + } + } +} diff --git a/language-support/kotlin/language-configuration.json b/language-support/kotlin/language-configuration.json new file mode 100644 index 0000000000..56225afa7e --- /dev/null +++ b/language-support/kotlin/language-configuration.json @@ -0,0 +1,27 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": [ "/*", "*/" ] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] }, + { "open": "\"", "close": "\"", "notIn": ["string"] }, + { "open": "/*", "close": " */", "notIn": ["string"] } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["<", ">"], + ["'", "'"], + ["\"", "\""] + ] +} \ No newline at end of file diff --git a/language-support/properties/JavaProperties.tmLanguage.json b/language-support/properties/JavaProperties.tmLanguage.json new file mode 100644 index 0000000000..60b4ee34c4 --- /dev/null +++ b/language-support/properties/JavaProperties.tmLanguage.json @@ -0,0 +1,103 @@ +{ + "information_for_contributors": [ + "This file has been converted from https://github.com/textmate/java.tmbundle/blob/master/Syntaxes/JavaProperties.plist", + "If you want to provide a fix or improvement, please create a pull request against the original repository.", + "Once accepted there, we are happy to receive an update request." + ], + "version": "https://github.com/textmate/java.tmbundle/blob/79b8b61865e40de0ff04bb16fe1076b154b9894c/Syntaxes/JavaProperties.plist", + "fileTypes": [ + "properties" + ], + "foldingStartMarker": "^[a-zA-Z0-9.-_]+=.*\\\r\n", + "foldingStopMarker": "^(.*(?" + ] + ] +} \ No newline at end of file diff --git a/language-support/sql/inline-sql.json b/language-support/sql/inline-sql.json new file mode 100644 index 0000000000..9d13e384f0 --- /dev/null +++ b/language-support/sql/inline-sql.json @@ -0,0 +1,46 @@ +{ + "injectionSelector": "L:source.java -comment -string", + "patterns": [ + { + "contentName": "meta.embedded.block.sql", + "begin": "(?i)((/\\*\\s*(language=sql)\\s*\\*/)|((//\\s*(language=sql)\\s*)))", + "beginCaptures": { + "1": { + "name": "comment.block" + } + }, + "end": "(?<=\")", + "patterns": [ + { + "begin": "\\s*(\"\"\")$", + "beginCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "end": "\\s*(\"\"\")", + "endCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "patterns": [ + { "include": "source.sql" }, + { "include": "source.plpgsql.postgres" } + ] + }, + { + "begin": "\\s*(\")", + "beginCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "end": "\\s*(\")", + "endCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "patterns": [ + { "include": "source.sql" }, + { "include": "source.plpgsql.postgres" } + ] + } + ] + } + ], + "scopeName": "inline.sql" +} diff --git a/language-support/xml/inline-xml.json b/language-support/xml/inline-xml.json new file mode 100644 index 0000000000..69ec0a491b --- /dev/null +++ b/language-support/xml/inline-xml.json @@ -0,0 +1,44 @@ +{ + "injectionSelector": "L:source.java -comment -string", + "patterns": [ + { + "contentName": "meta.embedded.block.xml", + "begin": "(?i)((/\\*\\s*(language=xml)\\s*\\*/)|((//\\s*(language=xml)\\s*)))", + "beginCaptures": { + "1": { + "name": "comment.block" + } + }, + "end": "(?<=\")", + "patterns": [ + { + "begin": "\\s*(\"\"\")$", + "beginCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "end": "\\s*(\"\"\")", + "endCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "patterns": [ + { "include": "text.xml" } + ] + }, + { + "begin": "\\s*(\")", + "beginCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "end": "\\s*(\")", + "endCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "patterns": [ + { "include": "text.xml" } + ] + } + ] + } + ], + "scopeName": "inline.xml" +} diff --git a/language-support/yaml/inline-yaml.json b/language-support/yaml/inline-yaml.json new file mode 100644 index 0000000000..e0051e5185 --- /dev/null +++ b/language-support/yaml/inline-yaml.json @@ -0,0 +1,44 @@ +{ + "injectionSelector": "L:source.java -comment -string", + "patterns": [ + { + "contentName": "meta.embedded.block.yaml", + "begin": "(?i)((/\\*\\s*(language=yaml)\\s*\\*/)|((//\\s*(language=yaml)\\s*)))", + "beginCaptures": { + "1": { + "name": "comment.block" + } + }, + "end": "(?<=\")", + "patterns": [ + { + "begin": "\\s*(\"\"\")$", + "beginCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "end": "\\s*(\"\"\")", + "endCaptures": { + "0": { "name": "string.quoted.triple.java" } + }, + "patterns": [ + { "include": "source.yaml" } + ] + }, + { + "begin": "\\s*(\")", + "beginCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "end": "\\s*(\")", + "endCaptures": { + "0": { "name": "string.quoted.double.java" } + }, + "patterns": [ + { "include": "source.yaml" } + ] + } + ] + } + ], + "scopeName": "inline.yaml" +} diff --git a/lombok/lombok-1.18.39-4050.jar b/lombok/lombok-1.18.39-4050.jar new file mode 100644 index 0000000000..d624c2078a Binary files /dev/null and b/lombok/lombok-1.18.39-4050.jar differ diff --git a/package-lock.json b/package-lock.json index a5f87e500f..d6eddb1fde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5039 +1,4640 @@ { "name": "java", - "version": "0.47.0", - "lockfileVersion": 1, + "version": "1.55.0", + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@types/glob": { - "version": "5.0.30", - "resolved": "http://registry.npmjs.org/@types/glob/-/glob-5.0.30.tgz", - "integrity": "sha1-ECZAnFYlqGiQdGAoCNCCsoZ7ilE=", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" + "packages": { + "": { + "name": "java", + "version": "1.55.0", + "license": "EPL-2.0", + "dependencies": { + "@redhat-developer/vscode-extension-proposals": "0.0.23", + "@redhat-developer/vscode-redhat-telemetry": "0.10.2", + "@vscode/codicons": "^0.0.32", + "@vscode/webview-ui-toolkit": "1.2.2", + "chokidar": "^3.5.3", + "expand-home-dir": "^0.0.3", + "fmtr": "^1.1.2", + "fs-extra": "^8.1.0", + "glob": "^11.1.0", + "htmlparser2": "6.0.1", + "jdk-utils": "^0.6.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "semver": "^7.5.2", + "vscode-languageclient": "8.2.0-next.3", + "vscode-variables": "^1.0.1", + "winreg-utf8": "^0.1.1", + "winston": "^3.2.1", + "winston-daily-rotate-file": "^4.7.1" + }, + "devDependencies": { + "@types/fs-extra": "^8.0.0", + "@types/glob": "5.0.30", + "@types/lodash.findindex": "^4.6.6", + "@types/mocha": "^5.2.5", + "@types/node": "^18.17.1", + "@types/react": "^17.0.37", + "@types/react-dom": "^17.0.11", + "@types/semver": "^7.3.8", + "@types/sinon": "^10.0.12", + "@types/vscode": "^1.77.0", + "@types/vscode-webview": "^1.57.0", + "@types/winreg": "^1.2.30", + "@types/winston": "^2.4.4", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "@vscode/test-electron": "^2.5.2", + "css-loader": "^6.7.3", + "eslint": "^8.13.0", + "eslint-webpack-plugin": "^3.2.0", + "lodash.findindex": "^4.6.0", + "mini-css-extract-plugin": "^2.9.4", + "minimist": ">=1.2.6", + "mocha": "^11.1.0", + "sinon": "^14.0.0", + "tar": "^7.5.11", + "ts-loader": "^9.4.2", + "typescript": "^4.6.4", + "webpack": "^5.105.0", + "webpack-cli": "^4.6.0" + }, + "engines": { + "vscode": "^1.77.0" } }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", - "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", - "dev": true + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "engines": { + "node": ">=0.1.90" + } }, - "@types/node": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.2.tgz", - "integrity": "sha512-JWB3xaVfsfnFY8Ofc9rTB/op0fqqTSqy4vBcVk1LuRJvta7KTX+D//fCkiTMeLGhdr2EbFZzQjC97gvmPilk9Q==", - "dev": true + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } }, - "@webassemblyjs/ast": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", - "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "node_modules/@eslint/eslintrc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11" + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.1", + "globals": "^13.9.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", - "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", - "dev": true + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } }, - "@webassemblyjs/helper-api-error": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", - "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "@webassemblyjs/helper-buffer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", - "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", - "dev": true + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "@webassemblyjs/helper-code-frame": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", - "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.7.11" + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@webassemblyjs/helper-fsm": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", - "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", - "dev": true + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, - "@webassemblyjs/helper-module-context": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", - "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", - "dev": true + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", - "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", - "dev": true + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", - "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11" + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" } }, - "@webassemblyjs/ieee754": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", - "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "@webassemblyjs/leb128": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", - "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "requires": { - "@xtuc/long": "4.2.1" + "license": "MIT", + "engines": { + "node": ">=6.0.0" } }, - "@webassemblyjs/utf8": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", - "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", - "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/helper-wasm-section": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-opt": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "@webassemblyjs/wast-printer": "1.7.11" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", - "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", - "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", - "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", - "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/floating-point-hex-parser": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-code-frame": "1.7.11", - "@webassemblyjs/helper-fsm": "1.7.11", - "@xtuc/long": "4.2.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", - "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11", - "@xtuc/long": "4.2.1" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", - "dev": true - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, - "requires": { - "acorn": "^5.0.0" + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } + "license": "MIT" }, - "ajv": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", - "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "ansi-colors": { + "node_modules/@lukeed/csprng": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" + "node_modules/@lukeed/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@lukeed/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==", + "license": "MIT", + "dependencies": { + "@lukeed/csprng": "^1.1.0" + }, + "engines": { + "node": ">=8" } }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "node_modules/@microsoft/fast-element": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.11.0.tgz", + "integrity": "sha512-VKJYMkS5zgzHHb66sY7AFpYv6IfFhXrjQcAyNgi2ivD65My1XOhtjfKez5ELcLFRJfgZNAxvI8kE69apXERTkw==" }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "node_modules/@microsoft/fast-foundation": { + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.47.0.tgz", + "integrity": "sha512-EyFuioaZQ9ngjUNRQi8R3dIPPsaNQdUOS+tP0G7b1MJRhXmQWIitBM6IeveQA6ZvXG6H21dqgrfEWlsYrUZ2sw==", + "dependencies": { + "@microsoft/fast-element": "^1.11.0", + "@microsoft/fast-web-utilities": "^5.4.1", + "tabbable": "^5.2.0", + "tslib": "^1.13.0" + } }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true + "node_modules/@microsoft/fast-foundation/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "node_modules/@microsoft/fast-react-wrapper": { + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", + "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", + "dependencies": { + "@microsoft/fast-element": "^1.9.0", + "@microsoft/fast-foundation": "^2.41.1" + }, + "peerDependencies": { + "react": ">=16.9.0" } }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" + "node_modules/@microsoft/fast-web-utilities": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", + "dependencies": { + "exenv-es6": "^1.1.1" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "archive-type": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", - "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "requires": { - "file-type": "^3.1.0" + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "requires": { - "sprintf-js": "~1.0.2" + "engines": { + "node": ">= 8" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "requires": { - "make-iterator": "^1.0.0" + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "requires": { - "make-iterator": "^1.0.0" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" } }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "node_modules/@redhat-developer/vscode-extension-proposals": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/@redhat-developer/vscode-extension-proposals/-/vscode-extension-proposals-0.0.23.tgz", + "integrity": "sha512-ecJcUShveU2qFPvp/h/YaICRATQQAZarCQ+MApZmqWD1OC9ultnDHsSgqX2ircBX3d2Ni5mqRbKf+LlHQEFhKA==" }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true + "node_modules/@redhat-developer/vscode-redhat-telemetry": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@redhat-developer/vscode-redhat-telemetry/-/vscode-redhat-telemetry-0.10.2.tgz", + "integrity": "sha512-bkrwQN3J+VXbyk5fd173ezUq/uQxJuO2Sp1CXUwGmxf8KExFbCMUaTdXeJPdoFVMtY4sA5wyJ5EZNTtltSMiDQ==", + "license": "Apache-2.0", + "dependencies": { + "@segment/analytics-node": "2.3.0", + "countries-and-timezones": "^3.4.1", + "getos": "^3.2.1", + "object-hash": "^3.0.0", + "os-locale": "^5.0.0", + "picomatch": "^4.0.2", + "ua-parser-js": "1.0.39", + "uuid": "^11.0.3" + } }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true + "node_modules/@redhat-developer/vscode-redhat-telemetry/node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" + "node_modules/@redhat-developer/vscode-redhat-telemetry/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@redhat-developer/vscode-redhat-telemetry/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@segment/analytics-core": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.8.2.tgz", + "integrity": "sha512-5FDy6l8chpzUfJcNlIcyqYQq4+JTUynlVoCeCUuVz+l+6W0PXg+ljKp34R4yLVCcY5VVZohuW+HH0VLWdwYVAg==", + "license": "MIT", "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-generic-utils": "1.2.0", + "dset": "^3.1.4", + "tslib": "^2.4.1" } }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, + "node_modules/@segment/analytics-core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@segment/analytics-generic-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@segment/analytics-generic-utils/-/analytics-generic-utils-1.2.0.tgz", + "integrity": "sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==", + "license": "MIT", "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } + "tslib": "^2.4.1" } }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true + "node_modules/@segment/analytics-generic-utils/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, + "node_modules/@segment/analytics-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-2.3.0.tgz", + "integrity": "sha512-fOXLL8uY0uAWw/sTLmezze80hj8YGgXXlAfvSS6TUmivk4D/SP0C0sxnbpFdkUzWg2zT64qWIZj26afEtSnxUA==", + "license": "MIT", "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-core": "1.8.2", + "@segment/analytics-generic-utils": "1.2.0", + "buffer": "^6.0.3", + "jose": "^5.1.0", + "node-fetch": "^2.6.7", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@segment/analytics-node/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "node_modules/@segment/analytics-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "node_modules/@sinonjs/fake-timers": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, - "requires": { - "safer-buffer": "~2.1.0" + "dependencies": { + "@sinonjs/commons": "^1.7.0" } }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "dependencies": { + "type-detect": "4.0.8" } }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "node_modules/@sinonjs/samsam": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-7.0.1.tgz", + "integrity": "sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==", "dev": true, - "requires": { - "util": "0.10.3" - }, "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } }, - "async-done": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", - "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^1.0.7", - "stream-exhaust": "^1.0.1" + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" } }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "node_modules/@types/fs-extra": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", + "integrity": "sha512-bCtL5v9zdbQW86yexOlXWTEGvLNqWxMFyi7gQA7Gcthbezr2cPSOb8SkESVKA937QD5cIwOFLDFt0MQoXOEr9Q==", "dev": true, - "requires": { - "async-done": "^1.2.2" + "dependencies": { + "@types/node": "*" } }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "node_modules/@types/glob": { + "version": "5.0.30", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.30.tgz", + "integrity": "sha1-ECZAnFYlqGiQdGAoCNCCsoZ7ilE=", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "node_modules/@types/lodash": { + "version": "4.14.146", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.146.tgz", + "integrity": "sha512-JzJcmQ/ikHSv7pbvrVNKJU5j9jL9VLf3/gqs048CEnBVVVEv4kve3vLxoPHGvclutS+Il4SBIuQQ087m1eHffw==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "node_modules/@types/lodash.findindex": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.findindex/-/lodash.findindex-4.6.6.tgz", + "integrity": "sha512-quPh7tw70yhryaubH6wBvgIQgeU1PFjdoT4eaW6WCKzjIlxgImLKIv4bvJhMTUlRkMgf5VAfECKKXKuB8cexgw==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "node_modules/@types/mocha": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", + "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", "dev": true }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "node_modules/@types/node": { + "version": "18.18.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.8.tgz", + "integrity": "sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==", "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "dependencies": { + "undici-types": "~5.26.4" } }, - "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "node_modules/@types/react": { + "version": "17.0.53", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.53.tgz", + "integrity": "sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw==", "dev": true, - "requires": { - "tweetnacl": "^0.14.3" + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true + "node_modules/@types/react-dom": { + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", + "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", + "dev": true, + "dependencies": { + "@types/react": "^17" + } }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "dev": true }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "node_modules/@types/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-D/2EJvAlCEtYFEYmmlGwbGXuK886HzyCc3nZX/tkFTQdEU8jZDAgiv08P162yB17y4ZXZoq7yFAnW4GDBb9Now==", "dev": true }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "node_modules/@types/sinon": { + "version": "10.0.13", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", + "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "dependencies": { + "@types/sinonjs__fake-timers": "*" } }, - "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", "dev": true }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } + "node_modules/@types/vscode": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.77.0.tgz", + "integrity": "sha512-MWFN5R7a33n8eJZJmdVlifjig3LWUNRrPeO1xemIcZ0ae0TEQuRc7G2xV0LUX78RZFECY1plYBn+dP/Acc3L0Q==", + "dev": true }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "node_modules/@types/vscode-webview": { + "version": "1.57.1", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.1.tgz", + "integrity": "sha512-ghW5SfuDmsGDS2A4xkvGsLwDRNc3Vj5rS6rPOyPm/IryZuf3wceZKxgYaUoW+k9f0f/CB7y2c1rRsdOWZWn0PQ==", "dev": true }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "node_modules/@types/winreg": { + "version": "1.2.30", + "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", + "integrity": "sha1-kdZxDlNtNFucmwF8V0z2qNpkxRg=", "dev": true }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "node_modules/@types/winston": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/winston/-/winston-2.4.4.tgz", + "integrity": "sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw==", + "deprecated": "This is a stub types definition. winston provides its own type definitions, so you do not need this installed.", "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "dependencies": { + "winston": "*" } }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz", + "integrity": "sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==", "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "dependencies": { + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/type-utils": "5.18.0", + "@typescript-eslint/utils": "5.18.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "node_modules/@typescript-eslint/parser": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.18.0.tgz", + "integrity": "sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==", "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" + "dependencies": { + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", + "debug": "^4.3.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz", + "integrity": "sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==", "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "dependencies": { + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz", + "integrity": "sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==", "dev": true, - "requires": { - "pako": "~1.0.5" + "dependencies": { + "@typescript-eslint/utils": "5.18.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "buffer": { - "version": "3.6.0", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "requires": { - "base64-js": "0.0.8", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "node_modules/@typescript-eslint/types": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.18.0.tgz", + "integrity": "sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==", "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - }, - "dependencies": { - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz", + "integrity": "sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true } } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "node_modules/@typescript-eslint/utils": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.18.0.tgz", + "integrity": "sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==", "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz", + "integrity": "sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.18.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true + "node_modules/@vscode/codicons": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.32.tgz", + "integrity": "sha512-3lgSTWhAzzWN/EPURoY4ZDBEA80OPmnaknNujA3qnI4Iu7AONWd9xF3iE4L+4prIe8E3TUnLQ4pxoaFTEEZNwg==" }, - "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "node_modules/@vscode/test-electron": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", + "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", "dev": true, - "requires": { - "tslib": "^1.9.0" + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^8.1.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" } }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "node_modules/@vscode/webview-ui-toolkit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz", + "integrity": "sha512-xIQoF4FC3Xh6d7KNKIoIezSiFWYFuf6gQMdDyKueKBFGeKwaHWEn+dY2g3makvvEsNMEDji/woEwvg9QSbuUsw==", + "dependencies": { + "@microsoft/fast-element": "^1.6.2", + "@microsoft/fast-foundation": "^2.38.0", + "@microsoft/fast-react-wrapper": "^0.1.18" + }, + "peerDependencies": { + "react": ">=16.9.0" } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, + "license": "MIT", "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - } + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "license": "MIT" }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, - "requires": { - "color-name": "1.1.3" + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, - "requires": { - "delayed-stream": "~1.0.0" + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" } }, - "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true + "license": "MIT" }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, - "requires": { - "date-now": "^0.1.4" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, - "requires": { - "safe-buffer": "~5.1.1" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" } }, - "core-util-is": { + "node_modules/@webpack-cli/configtest": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", + "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" } }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "node_modules/@webpack-cli/info": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", + "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "node_modules/@webpack-cli/serve": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", + "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } } }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" }, - "d": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } + "license": "Apache-2.0" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "requires": { - "assert-plus": "^1.0.0" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, - "requires": { - "ms": "2.0.0" + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "decompress": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", - "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "requires": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "requires": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - }, - "dependencies": { - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true - } + "license": "MIT", + "engines": { + "node": ">= 14" } }, - "decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, "dependencies": { - "file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true - } + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, - "requires": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - }, "dependencies": { - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true } } }, - "decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, - "requires": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "default-compare": { + "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "requires": { - "object-keys": "^1.0.12" + "engines": { + "node": ">=8" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "lodash": "^4.17.14" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } + "license": "MIT" }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" + "engines": { + "node": ">=6" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "node_modules/caniuse-lite": { + "version": "1.0.30001769", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" }, - "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, - "requires": { - "prr": "~1.0.1" + "engines": { + "node": ">=6.0" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, - "requires": { - "is-arrayish": "^0.2.1" + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "dependencies": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" } }, - "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" + "node_modules/colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "node_modules/colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "engines": { + "node": ">=0.1.90" } }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "node_modules/colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "dependencies": { + "color": "3.0.x", + "text-hex": "1.0.x" } }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "license": "MIT" }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/countries-and-timezones": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.8.0.tgz", + "integrity": "sha512-+Ze9h5f4dQpUwbzTm0DEkiPiZyim9VHV4/mSnT4zNYJnrnfwsKjAZPtnp7J5VzejCDgySs+2SSc6MDdCnD43GA==", + "license": "MIT", + "engines": { + "node": ">=8.x", + "npm": ">=5.x" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "requires": { - "estraverse": "^4.1.0" + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" } }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "events": { + "node_modules/diagnostics": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "expand-home-dir": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/expand-home-dir/-/expand-home-dir-0.0.3.tgz", - "integrity": "sha1-ct6KBIbMKKO71wRjU5iCW1tign0=" - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" } - } + ] }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, - "requires": { - "pend": "~1.2.0" - } + "license": "ISC" }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "file-type": { - "version": "3.9.0", - "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true + "node_modules/enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "dependencies": { + "env-variable": "0.0.x" + } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" } }, - "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "node_modules/enhanced-resolve": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" } }, - "find-java-home": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/find-java-home/-/find-java-home-0.2.0.tgz", - "integrity": "sha512-nq5PFOHxE1VSEbdDVkLoA2bAcRnG4ETqJO8ipFq3glIWA52hdWCXYX3emuUyMAQfaqFU4Ea85gqcgaPmOApEPA==", - "requires": { - "which": "~1.0.5", - "winreg": "~1.2.2" + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } + "node_modules/enquirer/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" } }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "node_modules/env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" } }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "node_modules/eslint": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.13.0.tgz", + "integrity": "sha512-D+Xei61eInqauAyTJ6C0q6x9mx7kTUC1KZ0m0LSEexR0V+e94K12LmWX076ZIsldwfQ2RONdaJe0re0TRGQbRQ==", "dev": true, - "requires": { - "for-in": "^1.0.1" + "dependencies": { + "@eslint/eslintrc": "^1.2.1", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, - "requires": { - "map-cache": "^0.2.2" + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "engines": { + "node": ">=10" } }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "node_modules/eslint-webpack-plugin/node_modules/@types/eslint": { + "version": "8.4.5", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", + "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } }, - "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/exenv-es6": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==" + }, + "node_modules/expand-home-dir": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/expand-home-dir/-/expand-home-dir-0.0.3.tgz", + "integrity": "sha1-ct6KBIbMKKO71wRjU5iCW1tign0=" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "get-value": { + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "node_modules/fast-safe-stringify": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "requires": { - "assert-plus": "^1.0.0" + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-stream-rotator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", + "dependencies": { + "moment": "^2.29.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/fmtr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fmtr/-/fmtr-1.1.2.tgz", + "integrity": "sha512-GYZV5D+SI/2AZBWF2HHKTxdQ7fty+2C/Jq2lyTseyZ1VBkkznSE2wzlbUPAutesC0hmJFpe+KXt6mzPE7qUXiw==", + "dependencies": { + "lodash": "^4.17.14" } }, - "glob-watcher": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", - "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "object.defaults": "^1.1.0" + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "global-modules": { + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } + "license": "ISC" }, - "global-modules-path": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz", - "integrity": "sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==", - "dev": true + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "glogg": { + "node_modules/functional-red-black-tree": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "requires": { - "sparkles": "^1.0.0" + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "license": "MIT", + "dependencies": { + "async": "^3.2.0" + } }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true + "node_modules/getos/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, - "gulp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", - "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", - "dev": true, - "requires": { - "glob-watcher": "^5.0.0", - "gulp-cli": "^2.0.0", - "undertaker": "^1.0.0", - "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "gulp-cli": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", - "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.1.0", - "isobject": "^3.0.1", - "liftoff": "^2.5.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.0.1", - "yargs": "^7.1.0" - } - } + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "gulp-decompress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-2.0.1.tgz", - "integrity": "sha1-EAKYk66NzSkrO2Ojb8+GFOPSe90=", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "requires": { - "archive-type": "^3.0.0", - "decompress": "^4.0.0", - "gulp-util": "^3.0.1", - "readable-stream": "^2.0.2" + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "gulp-download": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/gulp-download/-/gulp-download-0.0.1.tgz", - "integrity": "sha1-VKMBj8YZs0HM9kkWBvet8L08c5c=", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "requires": { - "gulp-util": "^3.0.8", - "request": "^2.88.0", - "request-progress": "^3.0.0", - "through": "^2.3.8" + "license": "BSD-2-Clause" + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "license": "BlueOak-1.0.0", "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - } - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } + "node_modules/glob/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "license": "ISC", + "engines": { + "node": "20 || >=22" } }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "har-schema": { + "node_modules/glob/node_modules/path-scurry": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "node_modules/globals": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "requires": { - "ansi-regex": "^2.0.0" + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "requires": { - "sparkles": "^1.0.0" + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "bin": { + "he": "bin/he" } }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "node_modules/htmlparser2": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.1.tgz", + "integrity": "sha512-GDKPd+vk4jvSuvCbyuzx/unmXkk090Azec7LovXP8as1Hn8q9p3hbjmDGbUqqhknw0ajwit6LiiWqfiTUPMK7w==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.4.4", + "entities": "^2.0.0" } }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" } }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "engines": { + "node": ">=10.17.0" } }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, - "requires": { - "parse-passwd": "^1.0.0" + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } + ] }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "engines": { + "node": ">= 4" } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "dev": true }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "node_modules/import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" } }, - "imurmurhash": { + "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.19" + } }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" + "node_modules/invert-kv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", + "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==", + "license": "MIT", + "engines": { + "node": ">=8" }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" + "funding": { + "url": "https://github.com/sindresorhus/invert-kv?sponsor=1" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { + "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "engines": { + "node": ">=0.10.0" + } }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" } }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "engines": { + "node": ">=8" } }, - "is-plain-object": { + "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-stream": { + "node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "engines": { + "node": ">=0.10.0" + } }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { + "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "isexe": { + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isobject": { + "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "node_modules/jdk-utils": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/jdk-utils/-/jdk-utils-0.6.0.tgz", + "integrity": "sha512-/CHgo6Q5xyfW/+vWXLz7cAb+iwIye3mNo7SV8UTHsbLhRykk+N7LzKXRlCvdeoblyuTrA8pb00iZX8De3txvWQ==", + "license": "MIT", + "bin": { + "jdk-utils": "bin/cli.js" + } }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stable-stringify": { + "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "requires": { - "readable-stream": "^2.0.5" + "engines": { + "node": ">=0.10.0" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" + "node_modules/kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "dependencies": { + "colornames": "^1.1.1" } }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" + "node_modules/lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "license": "MIT", + "dependencies": { + "invert-kv": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "dependencies": { + "immediate": "~3.0.5" } }, - "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "node_modules/lodash.findindex": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz", + "integrity": "sha1-oyRd7mH7m24GJLU1ElYku2nBEQY=", "dev": true }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "requires": { - "lodash._root": "^3.0.0" + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "requires": { - "pify": "^3.0.0" + "dependencies": { + "has-flag": "^4.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" } }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "map-age-cleaner": { + "node_modules/map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "node_modules/mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "license": "MIT", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + }, + "engines": { + "node": ">=8" + } }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "requires": { - "object-visit": "^1.0.0" + "engines": { + "node": ">= 8" } }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "engines": { + "node": ">= 0.6" } }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" } }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true + "node_modules/mini-css-extract-plugin": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", + "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } }, - "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "requires": { - "mime-db": "~1.37.0" + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" + "node_modules/mocha": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", + "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "node_modules/mocha/node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } + "license": "MIT", + "engines": { + "node": ">=8" } }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "node_modules/mocha/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "requires": { - "minimist": "0.0.8" + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "node_modules/mocha/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "mock-require": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", - "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "requires": { - "get-caller-file": "^1.0.2", - "normalize-path": "^2.1.1" + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "node_modules/mocha/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "requires": { - "duplexer2": "0.0.2" + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true + "node_modules/mocha/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } }, - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" } }, - "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, - "next-tick": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } + "node_modules/nise": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "dependencies": { + "type-detect": "4.0.8" } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" + "dependencies": { + "@sinonjs/commons": "^3.0.1" } }, - "now-and-later": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", - "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true, - "requires": { - "once": "^1.3.2" + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, - "requires": { - "path-key": "^2.0.0" - } + "license": "MIT" }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } }, - "object-assign": { + "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "engines": { + "node": ">=0.10.0" + } }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" } }, - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "node_modules/one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, - "requires": { - "isobject": "^3.0.0" + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "node_modules/optionator/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "object.pick": { + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, - "requires": { - "isobject": "^3.0.1" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" + "node_modules/os-locale": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", + "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "license": "MIT", + "dependencies": { + "execa": "^4.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" + "node_modules/os-locale/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true + "node_modules/os-locale/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" + "node_modules/os-locale/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "node_modules/os-locale/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "p-defer": { + "node_modules/p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "node_modules/p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "requires": { - "p-try": "^2.0.0" + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "requires": { - "p-limit": "^2.0.0" + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-try": { + "node_modules/p-try": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "pako": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", - "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "engines": { + "node": ">=8" } }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" } }, - "parse-node-version": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", - "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "requires": { - "path-root-regex": "^0.1.0" + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { + "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "requires": { - "pinkie": "^2.0.0" + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "requires": { - "find-up": "^3.0.0" - }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - } + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "engines": { + "node": ">= 0.8.0" } }, - "pump": { + "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { + "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", - "dev": true - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, - "requires": { - "safe-buffer": "^5.1.0" + "engines": { + "node": ">=6" } }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "requires": { - "randombytes": "^2.0.5", + "dependencies": { "safe-buffer": "^5.1.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" } }, - "readable-stream": { + "node_modules/readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -5041,1948 +4642,1520 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - } } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, - "requires": { - "resolve": "^1.1.6" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "engines": { + "node": ">=0.10.0" } }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" + "engines": { + "node": ">=0.10.0" } }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-progress": { + "node_modules/resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "requires": { - "path-parse": "^1.0.5" + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "requires": { - "resolve-from": "^3.0.0" + "engines": { + "node": ">=8" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, - "requires": { - "value-or-function": "^3.0.0" + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "requires": { - "glob": "^7.0.5" + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "requires": { - "aproba": "^1.1.1" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "safe-buffer": { + "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safe-regex": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } }, - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, - "requires": { - "commander": "~2.8.1" + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, - "requires": { - "sver-compat": "^1.5.0" + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "setimmediate": { + "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "dev": true }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" } }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "node_modules/sinon": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.2.tgz", + "integrity": "sha512-PDpV0ZI3ZCS3pEqx0vpNp6kzPhHrLx72wA0G+ZLaaJjLIYeE0n8INlgaohKuGy7hP0as5tbUd23QWu5U233t+w==", + "deprecated": "16.1.1", "dev": true, - "requires": { - "kind-of": "^3.2.0" + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^9.1.2", + "@sinonjs/samsam": "^7.0.1", + "diff": "^5.0.0", + "nise": "^5.1.2", + "supports-color": "^7.2.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "engines": { + "node": ">=0.10.0" } }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } }, - "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "spdx-license-ids": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", - "dev": true + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, - "ssri": { + "node_modules/string-width/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "requires": { - "safe-buffer": "~5.1.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, - "requires": { - "ansi-regex": "^2.0.0" + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "node_modules/tar": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", "dev": true, - "requires": { - "is-utf8": "^0.2.0" + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, - "strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "requires": { - "is-natural-number": "^4.0.1" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "node_modules/terser": { + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "tapable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", - "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", - "dev": true - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } - }, - "terser": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.11.0.tgz", - "integrity": "sha512-5iLMdhEPIq3zFWskpmbzmKwMQixKmTYwY3Ox9pjtSklBLnHiuQ0GKJLhL1HSYtyffHM3/lDIFBnb82m9D7ewwQ==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1", - "source-map-support": "~0.5.6" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true + "node_modules/terser-webpack-plugin": { + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz", - "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.8.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } + "esbuild": { + "optional": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "uglify-js": { + "optional": true } } }, - "throttleit": { + "node_modules/text-hex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true + "node_modules/triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "node_modules/ts-loader": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz", + "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==", "dev": true, - "requires": { - "setimmediate": "^1.0.4" + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" } }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, - "requires": { - "through2": "^2.0.3" + "engines": { + "node": ">=4" } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "engines": { + "node": ">=10" }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ts-loader": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.1.tgz", - "integrity": "sha512-fDDgpBH3SR8xlt2MasLdz3Yy611PQ/UY/KGyo7TgXhTRU/6sS8uGG0nJYnU1OdFBNKcoYbId1UTNaAOUn+i41g==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "node_modules/typescript": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", + "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz", + "integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" } }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "tslint": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", - "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.27.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, - "requires": { - "tslib": "^1.8.1" + "dependencies": { + "punycode": "^2.1.0" } }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" + "node_modules/vscode-jsonrpc": { + "version": "8.2.1-next.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1-next.1.tgz", + "integrity": "sha512-L+DYtdUtqUXGpyMgHqer6IBKvFFhl/1ToiMmCmG85LYHuuX0jllHMz77MYt0RicakoYY+Lq1yLK6Qj3YBqgzDQ==", + "engines": { + "node": ">=14.0.0" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "node_modules/vscode-languageclient": { + "version": "8.2.0-next.3", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.2.0-next.3.tgz", + "integrity": "sha512-Ojo6L2cb7GSiyD864k8vGb9fHxBdZeciHQQOF595C3IDHWg0w4KQ7iN7qGWVdl4wDNwlGTX3wWZawGfPTxnrPQ==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.4-next.3" + }, + "engines": { + "vscode": "^1.79.0" + } }, - "typescript": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.1.tgz", - "integrity": "sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q==", - "dev": true + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "typescript-tslint-plugin": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/typescript-tslint-plugin/-/typescript-tslint-plugin-0.3.1.tgz", - "integrity": "sha512-h8HEPBm36UEs901ld1x6m5eY/UFb4mF+A0nvERr4BWMww5wnV5nfcm9ZFt18foYL0GQ5NVMt1Tb3466WUU8dRQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.4", - "mock-require": "^3.0.2", - "vscode-languageserver": "^5.1.0" + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "unbzip2-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz", - "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", - "dev": true, - "requires": { - "buffer": "^3.0.1", - "through": "^2.3.6" + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.6-next.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.6-next.1.tgz", + "integrity": "sha512-2npXUc8oe/fb9Bjcwm2HTWYZXyCbW4NTo7jkOrEciGO+/LfWbSMgqZ6PwKWgqUkgCbkPxQHNjoMqr9ol/Ehjgg==", + "dependencies": { + "vscode-jsonrpc": "8.2.1-next.1", + "vscode-languageserver-types": "3.17.6-next.1" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true + "node_modules/vscode-languageserver-types": { + "version": "3.17.6-next.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.6-next.1.tgz", + "integrity": "sha512-7xVc/xLtNhKuCKX0mINT6mFUrUuRz0EinhwPGT8Gtsv2hlo+xJb5NKbiGailcWa1/T5e4dr5Pb2MfGchHreHAA==" }, - "undertaker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", - "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { + "node_modules/vscode-variables": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } + "resolved": "https://registry.npmjs.org/vscode-variables/-/vscode-variables-1.0.1.tgz", + "integrity": "sha512-iZ1d08I30ktqv4mMszGz2Y2o53r+PBpF5tEnwf8NNzKoxeuo0thoaFRG98uJkNVhOtiDmH4HJ3KlqfjM6XIxbA==" }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, - "requires": { - "unique-slug": "^2.0.0" + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" } }, - "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "node_modules/webpack": { + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "dev": true, - "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } + "node_modules/webpack-cli": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", + "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.2", + "@webpack-cli/info": "^1.2.3", + "@webpack-cli/serve": "^1.3.1", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "webpack-dev-server": { + "optional": true } } }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, - "requires": { - "punycode": "^2.1.0" + "engines": { + "node": ">= 10" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "node_modules/webpack-cli/node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "node_modules/webpack-cli/node_modules/rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "dependencies": { + "resolve": "^1.9.0" }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" } }, - "url-parse": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.6.tgz", - "integrity": "sha512-/B8AD9iQ01seoXmXf9z/MjLZQIdOoYl/+gvsQF6+mpnxaTfG9P7srYaiqaDMyKkR36XMXfhqSHss5MyFAO8lew==", + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" + "license": "MIT", + "engines": { + "node": ">=10.13.0" } }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", "dev": true }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "node_modules/winreg-utf8": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/winreg-utf8/-/winreg-utf8-0.1.1.tgz", + "integrity": "sha512-A4tBCO0bx3FCA/s8RowK40h3BQhKOWRFmsn6gYrXj6WjRAbOGnNJkTOpVmtA82UeGNMtpn3Wr0TWb742C1AS+g==" }, - "v8-compile-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", - "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", - "dev": true + "node_modules/winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "dependencies": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + }, + "engines": { + "node": ">= 6.4.0" + } }, - "v8flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", - "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" + "node_modules/winston-daily-rotate-file": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", + "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "winston": "^3" } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "node_modules/winston-daily-rotate-file/node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "node_modules/winston-daily-rotate-file/node_modules/logform": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", + "dependencies": { + "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" } }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true + "node_modules/winston-daily-rotate-file/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "node_modules/winston-daily-rotate-file/node_modules/winston-transport": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 6.4.0" } }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "node_modules/winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "dependencies": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + }, + "engines": { + "node": ">= 6.4.0" } }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" + "node_modules/winston/node_modules/readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "node_modules/word-wrap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, - "requires": { - "indexof": "0.0.1" + "engines": { + "node": ">=0.10.0" } }, - "vscode": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.33.tgz", - "integrity": "sha512-sXedp2oF6y4ZvqrrFiZpeMzaCLSWV+PpYkIxjG/iYquNZ9KrLL2LujltGxPLvzn49xu2sZkyC+avVNFgcJD1Iw==", + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { - "glob": "^7.1.2", - "mocha": "^4.0.1", - "request": "^2.88.0", - "semver": "^5.4.1", - "source-map-support": "^0.5.0", - "url-parse": "^1.4.4", - "vscode-test": "^0.1.4" - }, "dependencies": { - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "vscode-jsonrpc": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz", - "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==" + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } }, - "vscode-languageclient": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.1.1.tgz", - "integrity": "sha512-jMxshi+BPRQFNG8GB00dJv7ldqMda0be26laYYll/udtJuHbog6RqK10GSxHWDN0PgY0b0m5fePyTk3bq8a0TA==", - "requires": { - "semver": "^5.5.0", - "vscode-languageserver-protocol": "3.13.0" - } - }, - "vscode-languageserver": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz", - "integrity": "sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==", - "dev": true, - "requires": { - "vscode-languageserver-protocol": "3.14.1", - "vscode-uri": "^1.0.6" - }, - "dependencies": { - "vscode-languageserver-protocol": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz", - "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==", - "dev": true, - "requires": { - "vscode-jsonrpc": "^4.0.0", - "vscode-languageserver-types": "3.14.0" - } - }, - "vscode-languageserver-types": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz", - "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==", - "dev": true - } + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "vscode-languageserver-protocol": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz", - "integrity": "sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg==", - "requires": { - "vscode-jsonrpc": "^4.0.0", - "vscode-languageserver-types": "3.13.0" + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "vscode-languageserver-types": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz", - "integrity": "sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA==" + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, - "vscode-test": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.1.5.tgz", - "integrity": "sha512-s+lbF1Dtasc0yXVB9iQTexBe2JK6HJAUJe3fWezHKIjq+xRw5ZwCMEMBaonFIPy7s95qg2HPTRDR5W4h4kbxGw==", - "dev": true, - "requires": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1" + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "vscode-uri": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", - "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==", - "dev": true - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } - }, - "webpack": { - "version": "4.27.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.27.1.tgz", - "integrity": "sha512-WArHiLvHrlfyRM8i7f+2SFbr/XbQ0bXqTkPF8JpHOzub5482Y3wx7rEO8stuLGOKOgZJcqcisLhD7LrM/+fVMw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/wasm-edit": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" - } - }, - "webpack-cli": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz", - "integrity": "sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.0", - "global-modules-path": "^2.3.0", - "import-local": "^2.0.0", - "interpret": "^1.1.0", - "loader-utils": "^1.1.0", - "supports-color": "^5.5.0", - "v8-compile-cache": "^2.0.2", - "yargs": "^12.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "which": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", - "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=" - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "winreg": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", - "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" - }, - "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "requires": { - "errno": "~0.1.7" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "requires": { - "camelcase": "^3.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } } diff --git a/package.json b/package.json index 8ce3587cd2..9fe83f02d0 100644 --- a/package.json +++ b/package.json @@ -4,14 +4,27 @@ "description": "Java Linting, Intellisense, formatting, refactoring, Maven/Gradle support and more...", "author": "Red Hat", "icon": "icons/icon128.png", - "license": "EPL-1.0", - "version": "0.47.0", + "license": "EPL-2.0", + "version": "1.55.0", "publisher": "redhat", "bugs": "https://github.com/redhat-developer/vscode-java/issues", - "preview": true, - "enableProposedApi": false, + "preview": false, + "capabilities": { + "untrustedWorkspaces": { + "supported": "limited", + "restrictedConfigurations": [ + "java.jdt.ls.java.home", + "java.home", + "java.jdt.ls.vmargs", + "java.configuration.runtimes", + "java.import.gradle.java.home", + "java.import.gradle.home" + ] + }, + "virtualWorkspaces": false + }, "engines": { - "vscode": "^1.31.0" + "vscode": "^1.77.0" }, "repository": { "type": "git", @@ -27,400 +40,1837 @@ "multi-root ready" ], "activationEvents": [ - "onLanguage:java", "workspaceContains:pom.xml", + "workspaceContains:*/pom.xml", "workspaceContains:build.gradle", - "workspaceContains:.classpath" + "workspaceContains:*/build.gradle", + "workspaceContains:settings.gradle", + "workspaceContains:*/settings.gradle", + "workspaceContains:build.gradle.kts", + "workspaceContains:*/build.gradle.kts", + "workspaceContains:settings.gradle.kts", + "workspaceContains:*/settings.gradle.kts", + "workspaceContains:.classpath", + "workspaceContains:*/.classpath", + "onCommand:_java.templateVariables", + "onCommand:_java.metadataFilesGeneration" ], "main": "./dist/extension", "contributes": { + "customEditors": [ + { + "viewType": "decompiled.javaClass", + "displayName": "Decompiled Java Class File", + "selector": [ + { + "filenamePattern": "file:/**/*.class" + }, + { + "filenamePattern": "vscode-remote:/**/*.class" + } + ] + } + ], + "javaBuildFilePatterns": [ + "^pom\\.xml$", + ".*\\.gradle(\\.kts)?$" + ], + "javaBuildTools": [ + { + "displayName": "Maven", + "buildFileNames": [ + "pom.xml" + ] + }, + { + "displayName": "Gradle", + "buildFileNames": [ + "build.gradle", + "settings.gradle", + "build.gradle.kts", + "settings.gradle.kts" + ] + } + ], + "javaShortcuts": [ + { + "title": "$(settings-gear) Open Java Settings", + "command": "workbench.action.openSettings", + "arguments": [ + "java" + ] + }, + { + "title": "$(output) Open Logs", + "command": "java.open.logs" + }, + { + "title": "$(trash) Clean Workspace Cache...", + "command": "java.clean.workspace" + }, + { + "command": "java.change.searchScope", + "title": "$(search) Search Scope", + "category": "Java" + } + ], + "semanticTokenTypes": [ + { + "id": "annotation", + "superType": "type", + "description": "Style for annotations." + }, + { + "id": "annotationMember", + "superType": "method", + "description": "Style for annotation members." + }, + { + "id": "modifier", + "superType": "keyword", + "description": "Style for modifier keywords." + }, + { + "id": "record", + "superType": "class", + "description": "Style for records." + }, + { + "id": "recordComponent", + "superType": "parameter", + "description": "Style for record components." + } + ], + "semanticTokenModifiers": [ + { + "id": "public", + "description": "Style for symbols with the public access modifier." + }, + { + "id": "private", + "description": "Style for symbols with the private access modifier." + }, + { + "id": "protected", + "description": "Style for symbols with the protected access modifier." + }, + { + "id": "native", + "description": "Style for symbols with the native modifier." + }, + { + "id": "generic", + "description": "Style for symbols that are generic (have type parameters)." + }, + { + "id": "typeArgument", + "description": "Style for symbols that are type arguments for a generic symbol." + }, + { + "id": "importDeclaration", + "description": "Style for symbols that are part of an import declaration." + }, + { + "id": "constructor", + "description": "Style for symbols that are constructors." + } + ], + "semanticTokenScopes": [ + { + "language": "java", + "scopes": { + "annotation": [ + "storage.type.annotation.java" + ], + "decorator": [ + "storage.type.annotation.java" + ], + "annotationMember": [ + "entity.name.annotationMember.java", + "constant.other.key.java" + ], + "modifier": [ + "storage.modifier.java" + ], + "keyword.documentation": [ + "keyword.other.documentation.javadoc.java" + ], + "*.constructor": [ + "entity.name.function.java" + ] + } + } + ], "languages": [ { "id": "java", "extensions": [ + ".java", ".class" ], - "configuration": "./language-configuration.json" + "configuration": "./language-support/java/language-configuration.json" + }, + { + "id": "java-properties", + "aliases": [ + "Java Properties" + ], + "extensions": [ + ".properties" + ], + "configuration": "./language-support/properties/java-properties-configuration.json" + }, + { + "id": "gradle-kotlin-dsl", + "aliases": [ + "Gradle Kotlin DSL" + ], + "extensions": [ + ".gradle.kts" + ], + "configuration": "./language-support/kotlin/language-configuration.json" } ], - "snippets": [ + "grammars": [ { "language": "java", - "path": "./snippets/java.json" + "scopeName": "source.java", + "path": "./language-support/java/java.tmLanguage.json" + }, + { + "language": "java-properties", + "scopeName": "source.java-properties", + "path": "./language-support/properties/JavaProperties.tmLanguage.json" + }, + { + "language": "gradle-kotlin-dsl", + "scopeName": "source.gradle-kotlin-dsl", + "path": "./language-support/kotlin/kotlin.tmLanguage.json" + }, + { + "injectTo": [ + "source.java" + ], + "scopeName": "inline.sql", + "path": "./language-support/sql/inline-sql.json", + "embeddedLanguages": { + "meta.embedded.block.sql": "sql" + } + }, + { + "injectTo": [ + "source.java" + ], + "scopeName": "inline.json", + "path": "./language-support/json/inline-json.json", + "embeddedLanguages": { + "meta.embedded.block.json": "json" + } + }, + { + "injectTo": [ + "source.java" + ], + "scopeName": "inline.xml", + "path": "./language-support/xml/inline-xml.json", + "embeddedLanguages": { + "meta.embedded.block.xml": "xml" + } + }, + { + "injectTo": [ + "source.java" + ], + "scopeName": "inline.yaml", + "path": "./language-support/yaml/inline-yaml.json", + "embeddedLanguages": { + "meta.embedded.block.yaml": "yaml" + } + }, + { + "injectTo": [ + "source.java" + ], + "scopeName": "inline.html", + "path": "./language-support/html/inline-html.json", + "embeddedLanguages": { + "meta.embedded.block.html": "html" + } } ], - "configuration": { - "type": "object", - "title": "Java configuration", - "properties": { - "java.home": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "Specifies the folder path to the JDK (8 or more recent) used to launch the Java Language Server.\nOn Windows, backslashes must be escaped, i.e.\n\"java.home\":\"C:\\\\Program Files\\\\Java\\\\jdk1.8.0_161\"", - "scope": "window" - }, - "java.jdt.ls.vmargs": { - "type": [ - "string", - "null" - ], - "default": "-noverify -Xmx1G -XX:+UseG1GC -XX:+UseStringDeduplication", - "description": "Specifies extra VM arguments used to launch the Java Language Server. Eg. use `-noverify -Xmx1G -XX:+UseG1GC -XX:+UseStringDeduplication` to bypass class verification, increase the heap size to 1GB and enable String deduplication with the G1 Garbage collector", - "scope": "window" - }, - "java.errors.incompleteClasspath.severity": { - "type": [ - "string" - ], - "enum": [ - "ignore", - "info", - "warning", - "error" - ], - "default": "warning", - "description": "Specifies the severity of the message when the classpath is incomplete for a Java file", - "scope": "window" - }, - "java.configuration.checkProjectSettingsExclusions": { - "type": "boolean", - "default": true, - "description": "Checks if the extension-generated project settings files (.project, .classpath, .factorypath, .settings/) should be excluded from the file explorer.", - "scope": "window" - }, - "java.configuration.updateBuildConfiguration": { - "type": [ - "string" - ], - "enum": [ - "disabled", - "interactive", - "automatic" - ], - "default": "interactive", - "description": "Specifies how modifications on build files update the Java classpath/configuration", - "scope": "window" - }, - "java.trace.server": { - "type": "string", - "enum": [ - "off", - "messages", - "verbose" - ], - "default": "off", - "description": "Traces the communication between VS Code and the Java language server.", - "scope": "window" - }, - "java.import.maven.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable the Maven importer.", - "scope": "window" - }, - "java.import.gradle.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable the Gradle importer.", - "scope": "window" - }, - "java.import.gradle.wrapper.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable the Gradle wrapper.", - "scope": "window" - }, - "java.import.gradle.version": { - "type": "string", - "default": null, - "description": "Gradle version, used if the gradle wrapper is missing or disabled.", - "scope": "window" - }, - "java.import.gradle.arguments": { - "type": "string", - "default": null, - "description": "Arguments to pass to Gradle.", - "scope": "window" - }, - "java.import.gradle.jvmArguments": { - "type": "string", - "default": null, - "description": "JVM arguments to pass to Gradle.", - "scope": "window" - }, - "java.import.gradle.home": { - "type": "string", - "default": null, - "description": "Setting for GRADLE_HOME.", - "scope": "window" - }, - "java.maven.downloadSources": { - "type": "boolean", - "default": false, - "description": "Enable/disable eager download of Maven source artifacts.", - "scope": "window" - }, - "java.referencesCodeLens.enabled": { - "type": "boolean", - "default": false, - "description": "Enable/disable the references code lens.", - "scope": "window" - }, - "java.signatureHelp.enabled": { - "type": "boolean", - "default": false, - "description": "Enable/disable the signature help.", - "scope": "window" - }, - "java.implementationsCodeLens.enabled": { - "type": "boolean", - "default": false, - "description": "Enable/disable the implementations code lens.", - "scope": "window" - }, - "java.configuration.maven.userSettings": { - "type": "string", - "default": null, - "description": "Path to Maven's settings.xml", - "scope": "window" - }, - "java.format.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable default Java formatter", - "scope": "window" - }, - "java.saveActions.organizeImports": { - "type": "boolean", - "default": false, - "description": "Enable/disable auto organize imports on save action", - "scope": "window" - }, - "java.import.exclusions": { - "type": "array", - "description": "Configure glob patterns for excluding folders", - "default": [ - "**/node_modules/**", - "**/.metadata/**", - "**/archetype-resources/**", - "**/META-INF/maven/**" - ], - "scope": "window" - }, - "java.contentProvider.preferred": { - "type": "string", - "description": "Preferred content provider (a 3rd party decompiler id, usually)", - "default": null, - "scope": "window" - }, - "java.autobuild.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable the 'auto build'", - "scope": "window" - }, - "java.maxConcurrentBuilds": { - "type": "integer", - "default": 1, - "description": "Max simultaneous project builds", - "scope": "window", - "minimum": 1 - }, - "java.completion.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable code completion support", - "scope": "window" - }, - "java.completion.overwrite": { - "type": "boolean", - "default": true, - "description": "When set to true, code completion overwrites the current text. When set to false, code is simply added instead.", - "scope": "window" - }, - "java.completion.guessMethodArguments": { - "type": "boolean", - "default": false, - "description": "When set to true, method arguments are guessed when a method is selected from as list of code assist proposals.", - "scope": "window" - }, - "java.completion.favoriteStaticMembers": { - "type": "array", - "description": "Defines a list of static members or types with static members. Content assist will propose those static members even if the import is missing.", - "default": [ - "org.junit.Assert.*", - "org.junit.Assume.*", - "org.junit.jupiter.api.Assertions.*", - "org.junit.jupiter.api.Assumptions.*", - "org.junit.jupiter.api.DynamicContainer.*", - "org.junit.jupiter.api.DynamicTest.*", - "org.mockito.Mockito.*", - "org.mockito.ArgumentMatchers.*", - "org.mockito.Answers.*" - ], - "scope": "window" - }, - "java.completion.importOrder": { - "type": "array", - "description": "Defines the sorting order of import statements. A package or type name prefix (e.g. 'org.eclipse') is a valid entry. An import is always added to the most specific group.", - "default": [ - "java", - "javax", - "com", - "org" - ], - "scope": "window" - }, - "java.foldingRange.enabled": { - "type": "boolean", - "default": true, - "description": "Enable/disable smart folding range support. If disabled, it will use the default indentation-based folding range provided by VS Code.", - "scope": "window" - }, - "java.progressReports.enabled": { - "type": "boolean", - "description": "[Experimental] Enable/disable progress reports from background processes on the server.", - "default": true, - "scope": "window" - }, - "java.format.settings.url": { - "type": "string", - "description": "Specifies the url or file path to the [Eclipse formatter xml settings](https://github.com/redhat-developer/vscode-java/wiki/Formatter-settings).", - "default": null, - "scope": "window" - }, - "java.format.settings.profile": { - "type": "string", - "description": "Optional formatter profile name from the Eclipse formatter settings.", - "default": null, - "scope": "window" - }, - "java.format.comments.enabled": { - "type": "boolean", - "description": "Includes the comments during code formatting.", - "default": true, - "scope": "window" - }, - "java.format.onType.enabled": { - "type": "boolean", - "description": "Enable/disable automatic block formatting when typing `;`, `` or `}`", - "default": true, - "scope": "window" - }, - "java.codeGeneration.hashCodeEquals.useJava7Objects": { - "type": "boolean", - "description": "Use Objects.hash and Objects.equals when generating the hashCode and equals methods. This setting only applies to Java 7 and higher.", - "default": false, - "scope": "window" - }, - "java.codeGeneration.hashCodeEquals.useInstanceof": { - "type": "boolean", - "description": "Use 'instanceof' to compare types when generating the hashCode and equals methods.", - "default": false, - "scope": "window" - }, - "java.codeGeneration.useBlocks": { - "type": "boolean", - "description": "Use blocks in 'if' statements when generating the methods.", - "default": false, - "scope": "window" - }, - "java.codeGeneration.generateComments": { - "type": "boolean", - "description": "Generate method comments when generating the methods.", - "default": false, - "scope": "window" - }, - "java.codeGeneration.toString.template": { - "type": "string", - "description": "The template for generating the toString method.", - "default": "${object.className} [${member.name()}=${member.value}, ${otherMembers}]" - }, - "java.codeGeneration.toString.codeStyle": { - "type": "string", - "enum": [ - "STRING_CONCATENATION", - "STRING_BUILDER", - "STRING_BUILDER_CHAINED", - "STRING_FORMAT" - ], - "enumDescriptions": [ - "String concatenation", - "StringBuilder/StringBuffer", - "StringBuilder/StringBuffer - chained call", - "String.format/MessageFormat" - ], - "description": "The code style for generating the toString method.", - "default": "STRING_CONCATENATION" - }, - "java.codeGeneration.toString.skipNullValues": { - "type": "boolean", - "description": "Skip null values when generating the toString method.", - "default": false, - "scope": "window" - }, - "java.codeGeneration.toString.listArrayContents": { - "type": "boolean", - "description": "List contents of arrays instead of using native toString().", - "default": true, - "scope": "window" - }, - "java.codeGeneration.toString.limitElements": { - "type": "integer", - "description": "Limit number of items in arrays/collections/maps to list, if 0 then list all.", - "default": 0, - "scope": "window" + "jsonValidation": [ + { + "fileMatch": "package.json", + "url": "./schemas/package.schema.json" + } + ], + "configuration": [ + { + "id": "java-startup", + "title": "Startup", + "order": 10, + "properties": { + "java.home": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Specifies the folder path to the JDK (21 or more recent) used to launch the Java Language Server.\nOn Windows, backslashes must be escaped, i.e.\n\"java.home\":\"C:\\\\Program Files\\\\Java\\\\jdk-21.0_5\"", + "scope": "machine-overridable", + "deprecationMessage": "This setting is deprecated, please use 'java.jdt.ls.java.home' instead.", + "order": 0 + }, + "java.jdt.ls.java.home": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Specifies the folder path to the JDK (21 or more recent) used to launch the Java Language Server. This setting will replace the Java extension's embedded JRE to start the Java Language Server. \n\nOn Windows, backslashes must be escaped, i.e.\n\"java.jdt.ls.java.home\":\"C:\\\\Program Files\\\\Java\\\\jdk-21.0_5\"", + "scope": "machine-overridable", + "order": 10 + }, + "java.jdt.ls.vmargs": { + "type": [ + "string", + "null" + ], + "default": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable", + "description": "Specifies extra VM arguments used to launch the Java Language Server. Eg. use `-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable` to optimize memory usage with the parallel garbage collector", + "scope": "machine-overridable", + "order": 20 + }, + "java.server.launchMode": { + "type": "string", + "enum": [ + "Standard", + "LightWeight", + "Hybrid" + ], + "enumDescriptions": [ + "Provides full features such as intellisense, refactoring, building, Maven/Gradle support etc.", + "Starts a syntax server with lower start-up cost. Only provides syntax features such as outline, navigation, javadoc, syntax errors.", + "Provides full features with better responsiveness. It starts a standard language server and a secondary syntax server. The syntax server provides syntax features until the standard server is ready." + ], + "description": "The launch mode for the Java extension", + "default": "Hybrid", + "scope": "window", + "order": 30 + }, + "java.configuration.workspaceCacheLimit": { + "type": [ + "null", + "integer" + ], + "default": 90, + "minimum": 1, + "description": "The number of days (if enabled) to keep unused workspace cache data. Beyond this limit, cached workspace data may be removed.", + "scope": "application", + "order": 40 + }, + "java.sharedIndexes.enabled": { + "type": "string", + "enum": [ + "auto", + "on", + "off" + ], + "default": "auto", + "markdownDescription": "[Experimental] Specify whether to share indexes between different workspaces. When set to `auto`, shared indexes will be enabled in Visual Studio Code - Insiders.", + "scope": "window", + "order": 50 + }, + "java.sharedIndexes.location": { + "type": "string", + "markdownDescription": "Specifies a common index location for all workspaces. See default values as follows:\n \nWindows: First use `\"$APPDATA\\\\.jdt\\\\index\"`, or `\"~\\\\.jdt\\\\index\"` if it does not exist\n \nmacOS: `\"~/Library/Caches/.jdt/index\"`\n \nLinux: First use `\"$XDG_CACHE_HOME/.jdt/index\"`, or `\"~/.cache/.jdt/index\"` if it does not exist", + "default": "", + "scope": "window", + "order": 60 + }, + "java.jdt.ls.lombokSupport.enabled": { + "type": "boolean", + "default": true, + "description": "Whether to load lombok processors from project classpath", + "scope": "window", + "order": 70 + }, + "java.jdt.ls.protobufSupport.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "Specify whether to automatically add Protobuf output source directories to the classpath.\n\n**Note:** Only works for Gradle `com.google.protobuf` plugin `0.8.4` or higher.", + "scope": "window", + "order": 80 + }, + "java.jdt.ls.aspectjSupport.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Specify whether to enable `io.freefair.aspectj` plugin in Gradle projects. Defaults to `false`.", + "scope": "window", + "order": 80 + }, + "java.jdt.ls.kotlinSupport.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "[Experimental] Specify whether to enable `org.jetbrains.kotlin.jvm` plugin in Gradle projects. Defaults to `true`.", + "scope": "window", + "order": 80 + }, + "java.jdt.ls.scalaSupport.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "[Experimental] Specify whether to enable `scala` plugin in Gradle projects. Defaults to `true`.", + "scope": "window", + "order": 80 + }, + "java.jdt.ls.groovySupport.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "[Experimental] Specify whether to enable `groovy` plugin in Gradle projects. Defaults to `true`.", + "scope": "window", + "order": 80 + }, + "java.jdt.ls.androidSupport.enabled": { + "type": "string", + "enum": [ + "auto", + "on", + "off" + ], + "default": "auto", + "markdownDescription": "[Experimental] Specify whether to enable Android project importing. When set to `auto`, the Android support will be enabled in Visual Studio Code - Insiders.\n\n**Note:** Only works for Android Gradle Plugin `3.2.0` or higher.", + "scope": "window", + "order": 90 + }, + "java.jdt.ls.javac.enabled": { + "type": "string", + "enum": [ + "on", + "off" + ], + "default": "off", + "markdownDescription": "[Experimental] Specify whether to enable Javac-based compilation in the language server. Requires running this extension with Java 25", + "scope": "window", + "order": 95 + }, + "java.jdt.ls.appcds.enabled": { + "type": "string", + "enum": [ + "auto", + "on", + "off" + ], + "default": "auto", + "markdownDescription": "[Experimental] Enable Java AppCDS (Application Class Data Sharing) for improvements to extension activation. When set to `auto`, AppCDS will be enabled in Visual Studio Code - Insiders, and for pre-release versions.", + "scope": "machine-overridable", + "order": 100 + }, + "java.trace.server": { + "type": "string", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "Traces the communication between VS Code and the Java language server.", + "scope": "window" + }, + "redhat.telemetry.enabled": { + "type": "boolean", + "default": null, + "markdownDescription": "Enable usage data and errors to be sent to Red Hat servers. Read our [privacy statement](https://developers.redhat.com/article/tool-data-collection).", + "scope": "window", + "tags": [ + "usesOnlineServices", + "telemetry" + ] + } + } + }, + { + "id": "java-projectimport", + "title": "Project Import/Update", + "order": 20, + "properties": { + "java.import.projectSelection": { + "type": "string", + "enum": [ + "manual", + "automatic" + ], + "enumDescriptions": [ + "Manually select the build configuration files.", + "Let extension automatically scan and select the build configuration files." + ], + "default": "automatic", + "markdownDescription": "[Experimental] Specifies how to select build configuration files to import. \nNote: Currently, `Gradle` projects cannot be partially imported.", + "scope": "window", + "order": 10 + }, + "java.configuration.updateBuildConfiguration": { + "type": [ + "string" + ], + "enum": [ + "disabled", + "interactive", + "automatic" + ], + "default": "interactive", + "description": "Specifies how modifications on build files update the Java classpath/configuration", + "scope": "window", + "order": 20 + }, + "java.import.exclusions": { + "type": "array", + "description": "Configure glob patterns for excluding folders. Use `!` to negate patterns to allow subfolders imports. You have to include a parent directory. The order is important.", + "default": [ + "**/node_modules/**", + "**/.metadata/**", + "**/archetype-resources/**", + "**/META-INF/maven/**" + ], + "scope": "window" + }, + "java.project.resourceFilters": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?!\\*).*" + }, + "default": [ + "node_modules", + "\\.git" + ], + "markdownDescription": "Excludes files and folders from being refreshed by the Java Language Server, which can improve the overall performance. For example, [\"node_modules\",\"\\.git\"] will exclude all files and folders named `node_modules` or `.git`. Pattern expressions must be compatible with `java.util.regex.Pattern`. Defaults to [\"node_modules\",\"\\.git\"].", + "scope": "window" + }, + "java.configuration.checkProjectSettingsExclusions": { + "deprecationMessage": "Please use 'java.import.generatesMetadataFilesAtProjectRoot' to control whether to generate the project metadata files at the project root. And use 'files.exclude' to control whether to hide the project metadata files from the file explorer.", + "type": "boolean", + "default": false, + "description": "Controls whether to exclude extension-generated project settings files (.project, .classpath, .factorypath, .settings/) from the file explorer.", + "scope": "window" + }, + "java.import.generatesMetadataFilesAtProjectRoot": { + "type": "boolean", + "markdownDescription": "Specify whether the project metadata files(.project, .classpath, .factorypath, .settings/) will be generated at the project root. Click [HERE](command:_java.metadataFilesGeneration) to learn how to change the setting to make it take effect.", + "default": false, + "scope": "window" + }, + "java.project.importOnFirstTimeStartup": { + "type": "string", + "enum": [ + "disabled", + "interactive", + "automatic" + ], + "default": "automatic", + "description": "Specifies whether to import the Java projects, when opening the folder in Hybrid mode for the first time.", + "scope": "application" + }, + "java.project.importHint": { + "type": "boolean", + "description": "Enable/disable the server-mode switch information, when Java projects import is skipped on startup.", + "default": true, + "scope": "application" + }, + "java.showBuildStatusOnStart.enabled": { + "anyOf": [ + { + "enum": [ + "notification", + "terminal", + "off" + ], + "enumDescriptions": [ + "Show the build status via progress notification on start", + "Show the build status via terminal on start", + "Do not show any build status on start" + ] + }, + "boolean" + ], + "description": "Automatically show build status on startup.", + "default": "notification", + "scope": "window" + }, + "java.project.encoding": { + "enum": [ + "ignore", + "warning", + "setDefault" + ], + "enumDescriptions": [ + "Ignore project encoding settings", + "Show warning if a project has no explicit encoding set", + "Set the default workspace encoding settings" + ], + "default": "ignore", + "markdownDescription": "Project encoding settings", + "scope": "window" + } + } + }, + { + "id": "java-unmanagedfolder", + "title": "Unmanaged Folder", + "order": 30, + "properties": { + "java.project.sourcePaths": { + "type": "array", + "items": { + "type": "string" + }, + "markdownDescription": "Relative paths to the workspace where stores the source files. `Only` effective in the `WORKSPACE` scope. The setting will `NOT` affect Maven or Gradle project.", + "default": [], + "scope": "window", + "order": 10 + }, + "java.project.outputPath": { + "type": [ + "string", + "null" + ], + "markdownDescription": "A relative path to the workspace where stores the compiled output. `Only` effective in the `WORKSPACE` scope. The setting will `NOT` affect Maven or Gradle project.", + "default": "", + "scope": "window", + "order": 20 + }, + "java.project.referencedLibraries": { + "type": [ + "array", + "object" + ], + "description": "Configure glob patterns for referencing local libraries to a Java project.", + "default": [ + "lib/**/*.jar" + ], + "properties": { + "include": { + "type": "array" + }, + "exclude": { + "type": "array" + }, + "sources": { + "type": "object" + } + }, + "required": [ + "include" + ], + "additionalProperties": false, + "scope": "window", + "order": 30 + } + } + }, + { + "id": "java-maven", + "title": "Maven", + "order": 40, + "properties": { + "java.import.maven.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable the Maven importer.", + "scope": "window", + "order": 10 + }, + "java.import.maven.offline.enabled": { + "type": "boolean", + "default": false, + "description": "Enable/disable the Maven offline mode.", + "scope": "window", + "order": 20 + }, + "java.import.maven.disableTestClasspathFlag": { + "type": "boolean", + "default": false, + "description": "Enable/disable test classpath segregation. When enabled, this permits the usage of test resources within a Maven project as dependencies within the compile scope of other projects.", + "scope": "window", + "order": 30 + }, + "java.maven.downloadSources": { + "type": "boolean", + "default": false, + "description": "Enable/disable download of Maven source artifacts as part of importing Maven projects.", + "scope": "window", + "order": 40 + }, + "java.maven.updateSnapshots": { + "type": "boolean", + "default": false, + "description": "Force update of Snapshots/Releases.", + "scope": "window", + "order": 50 + }, + "java.configuration.maven.userSettings": { + "type": "string", + "default": null, + "description": "Path to Maven's user settings.xml", + "scope": "window", + "order": 60 + }, + "java.configuration.maven.globalSettings": { + "type": "string", + "default": null, + "description": "Path to Maven's global settings.xml", + "scope": "window", + "order": 70 + }, + "java.configuration.maven.notCoveredPluginExecutionSeverity": { + "type": "string", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "Specifies severity if the plugin execution is not covered by Maven build lifecycle.", + "scope": "window", + "order": 80 + }, + "java.configuration.maven.defaultMojoExecutionAction": { + "type": "string", + "enum": [ + "ignore", + "warn", + "error", + "execute" + ], + "default": "ignore", + "description": "Specifies default mojo execution action when no associated metadata can be detected.", + "scope": "window", + "order": 90 + }, + "java.configuration.maven.lifecycleMappings": { + "type": "string", + "default": null, + "description": "Path to Maven's lifecycle mappings xml", + "scope": "window", + "order": 100 + } + } + }, + { + "id": "java-gradle", + "title": "Gradle", + "order": 50, + "properties": { + "java.import.gradle.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable the Gradle importer.", + "scope": "window", + "order": 10 + }, + "java.import.gradle.wrapper.enabled": { + "type": "boolean", + "default": true, + "description": "Use Gradle from the 'gradle-wrapper.properties' file.", + "scope": "window", + "order": 20 + }, + "java.import.gradle.version": { + "type": "string", + "default": null, + "description": "Use Gradle from the specific version if the Gradle wrapper is missing or disabled.", + "scope": "window", + "order": 30 + }, + "java.import.gradle.home": { + "type": "string", + "default": null, + "description": "Use Gradle from the specified local installation directory or GRADLE_HOME if the Gradle wrapper is missing or disabled and no 'java.import.gradle.version' is specified.", + "scope": "machine-overridable", + "order": 40 + }, + "java.import.gradle.java.home": { + "type": "string", + "default": null, + "description": "The location to the JVM used to run the Gradle daemon.", + "scope": "machine-overridable", + "order": 50 + }, + "java.import.gradle.user.home": { + "type": "string", + "default": null, + "description": "Setting for GRADLE_USER_HOME.", + "scope": "machine-overridable", + "order": 55 + }, + "java.import.gradle.offline.enabled": { + "type": "boolean", + "default": false, + "description": "Enable/disable the Gradle offline mode.", + "scope": "window", + "order": 60 + }, + "java.import.gradle.arguments": { + "type": "string", + "default": null, + "description": "Arguments to pass to Gradle.", + "scope": "machine", + "order": 70 + }, + "java.import.gradle.jvmArguments": { + "type": "string", + "default": null, + "description": "JVM arguments to pass to Gradle.", + "scope": "machine", + "order": 80 + }, + "java.import.gradle.annotationProcessing.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable the annotation processing on Gradle projects and delegate Annotation Processing to JDT APT. Only works for Gradle 5.2 or higher.", + "scope": "window", + "order": 90 + }, + "java.imports.gradle.wrapper.checksums": { + "type": "array", + "items": { + "type": "object", + "default": {}, + "required": [ + "sha256" + ], + "properties": { + "sha256": { + "type": "string", + "label": "SHA-256 checksum." + }, + "allowed": { + "type": "boolean", + "default": true, + "label": "Is allowed?" + } + }, + "additionalProperties": false, + "uniqueItems": true + }, + "description": "Defines allowed/disallowed SHA-256 checksums of Gradle Wrappers", + "default": [], + "scope": "application" + } + } + }, + { + "id": "java-build", + "title": "Build", + "order": 60, + "properties": { + "java.autobuild.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable the 'auto build'", + "scope": "window", + "order": 10 + }, + "java.maxConcurrentBuilds": { + "type": "integer", + "default": 1, + "description": "Max simultaneous project builds", + "scope": "window", + "minimum": 1, + "order": 20 + }, + "java.settings.url": { + "type": "string", + "markdownDescription": "Specifies the url or file path to the workspace Java settings. See [Setting Global Preferences](https://github.com/redhat-developer/vscode-java/wiki/Settings-Global-Preferences)", + "default": null, + "scope": "window", + "order": 30 + }, + "java.compile.nullAnalysis.nonnull": { + "type": "array", + "default": [ + "javax.annotation.Nonnull", + "org.eclipse.jdt.annotation.NonNull", + "org.springframework.lang.NonNull", + "org.jspecify.annotations.NonNull" + ], + "markdownDescription": "Specify the Nonnull annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`", + "scope": "window" + }, + "java.compile.nullAnalysis.nullable": { + "type": "array", + "default": [ + "javax.annotation.Nullable", + "org.eclipse.jdt.annotation.Nullable", + "org.springframework.lang.Nullable", + "org.jspecify.annotations.Nullable" + ], + "markdownDescription": "Specify the Nullable annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`", + "scope": "window" + }, + "java.compile.nullAnalysis.nonnullbydefault": { + "type": "array", + "default": [ + "javax.annotation.ParametersAreNonnullByDefault", + "org.eclipse.jdt.annotation.NonNullByDefault", + "org.springframework.lang.NonNullApi", + "org.jspecify.annotations.NullMarked" + ], + "markdownDescription": "Specify the NonNullByDefault annotation types to be used for null analysis. If more than one annotation is specified, then the topmost annotation will be used first if it exists in project dependencies. This setting will be ignored if `java.compile.nullAnalysis.mode` is set to `disabled`", + "scope": "window" + }, + "java.compile.nullAnalysis.mode": { + "type": "string", + "enum": [ + "disabled", + "interactive", + "automatic" + ], + "default": "interactive", + "markdownDescription": "Specify how to enable the annotation-based null analysis.", + "scope": "window" + }, + "java.errors.incompleteClasspath.severity": { + "type": [ + "string" + ], + "enum": [ + "ignore", + "info", + "warning", + "error" + ], + "default": "warning", + "description": "Specifies the severity of the message when the classpath is incomplete for a Java file", + "scope": "window" + } + } + }, + { + "id": "java-jdks", + "title": "Installed JDKs", + "order": 70, + "properties": { + "java.configuration.runtimes": { + "type": "array", + "description": "Map Java Execution Environments to local JDKs.", + "items": { + "type": "object", + "default": {}, + "required": [ + "path", + "name" + ], + "properties": { + "name": { + "type": "string", + "enum": [ + "JavaSE-1.8", + "JavaSE-9", + "JavaSE-10", + "JavaSE-11", + "JavaSE-12", + "JavaSE-13", + "JavaSE-14", + "JavaSE-15", + "JavaSE-16", + "JavaSE-17", + "JavaSE-18", + "JavaSE-19", + "JavaSE-20", + "JavaSE-21", + "JavaSE-22", + "JavaSE-23", + "JavaSE-24", + "JavaSE-25", + "JavaSE-26" + ], + "description": "Java Execution Environment name. Must be unique." + }, + "path": { + "type": "string", + "pattern": ".*(?` or `}`", + "default": true, + "scope": "window" + } + } + }, + { + "id": "java-codecompletion", + "title": "Code Completion", + "order": 90, + "properties": { + "java.completion.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable code completion support", + "scope": "window", + "order": 10 + }, + "java.completion.engine": { + "type": "string", + "default": "ecj", + "description": "[Experimental] Select code completion engine", + "scope": "window", + "enum": [ + "ecj", + "dom" + ], + "markdownEnumDescriptions": [ + "Use ECJ-based code completion engine (default)", + "Use (highly experimental) JDT DOM-based code completion engine (requires `java.jdt.ls.javac.enabled` to be `on`)" + ], + "order": 1000 + }, + "java.completion.postfix.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "Enable/disable postfix completion support. `#editor.snippetSuggestions#` can be used to customize how postfix snippets are sorted.", + "scope": "window", + "order": 20 + }, + "java.completion.chain.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Enable/disable chain completion support. Chain completions are only available when completions are invoked by the completions shortcut", + "scope": "window", + "order": 30 + }, + "java.completion.favoriteStaticMembers": { + "type": "array", + "description": "Defines a list of static members or types with static members. Content assist will propose those static members even if the import is missing.", + "default": [ + "org.junit.Assert.*", + "org.junit.Assume.*", + "org.junit.jupiter.api.Assertions.*", + "org.junit.jupiter.api.Assumptions.*", + "org.junit.jupiter.api.DynamicContainer.*", + "org.junit.jupiter.api.DynamicTest.*", + "org.mockito.Mockito.*", + "org.mockito.ArgumentMatchers.*", + "org.mockito.Answers.*" + ], + "scope": "window", + "order": 40 + }, + "java.completion.filteredTypes": { + "type": "array", + "description": "Defines the type filters. All types whose fully qualified name matches the selected filter strings will be ignored in content assist or quick fix proposals and when organizing imports. For example 'java.awt.*' will hide all types from the awt packages.", + "default": [ + "java.awt.*", + "com.sun.*", + "sun.*", + "jdk.*", + "org.graalvm.*", + "io.micrometer.shaded.*" + ], + "scope": "window", + "order": 50 + }, + "java.completion.guessMethodArguments": { + "type": [ + "boolean", + "string" + ], + "enum": [ + "auto", + "off", + "insertParameterNames", + "insertBestGuessedArguments" + ], + "enumDescriptions": [ + "Use 'off' only when using Visual Studio Code - Insiders, other platform will defaults to 'insertBestGuessedArguments'.", + "Method arguments will not be inserted during completion.", + "The parameter names will be inserted during completion.", + "The best guessed arguments will be inserted during completion according to the code context." + ], + "default": "auto", + "description": "Specify how the arguments will be filled during completion.", + "scope": "window", + "order": 60 + }, + "java.completion.matchCase": { + "type": "string", + "enum": [ + "firstLetter", + "off" + ], + "enumDescriptions": [ + "Match case for the first letter when doing completion.", + "Do not match case when doing completion." + ], + "default": "firstLetter", + "markdownDescription": "Specify whether to match case for code completion.", + "scope": "window", + "order": 70 + }, + "java.completion.importOrder": { + "type": "array", + "description": "Defines the sorting order of import statements. A package or type name prefix (e.g. 'org.eclipse') is a valid entry. An import is always added to the most specific group. As a result, the empty string (e.g. '') can be used to group all other imports. Static imports are prefixed with a '#'", + "default": [ + "#", + "java", + "javax", + "org", + "com", + "" + ], + "scope": "window", + "order": 80 + }, + "java.completion.lazyResolveTextEdit.enabled": { + "type": "boolean", + "default": true, + "description": "[Experimental] Enable/disable lazily resolving text edits for code completion.", + "scope": "window" + }, + "java.completion.maxResults": { + "type": "integer", + "default": 0, + "markdownDescription": "Maximum number of completion results (not including snippets).\n`0` (the default value) disables the limit, all results are returned. In case of performance problems, consider setting a sensible limit.", + "scope": "window" + }, + "java.signatureHelp.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable the signature help.", + "scope": "window" + }, + "java.signatureHelp.description.enabled": { + "type": "boolean", + "default": false, + "description": "Enable/disable to show the description in signature help.", + "scope": "window" + }, + "java.completion.collapseCompletionItems": { + "type": "boolean", + "default": false, + "markdownDescription": "Enable/disable the collapse of overloaded methods in completion items. Overrides `#java.completion.guessMethodArguments#`.", + "scope": "window" + } + } + }, + { + "id": "java-codegeneration", + "title": "Code Generation", + "order": 100, + "properties": { + "java.templates.newFile.enabled": { + "type": "boolean", + "default": true, + "markdownDescription": "Enable/disable automatic generation of class body and package declaration when creating a new Java file. Set to `false` to create empty Java files. Defaults to `true`.", + "scope": "window", + "order": 5 + }, + "java.templates.fileHeader": { + "type": "array", + "markdownDescription": "Specifies the file header comment for new Java file. Supports configuring multi-line comments with an array of strings, and using ${variable} to reference the [predefined variables](command:_java.templateVariables).", + "scope": "window", + "default": [], + "order": 10 + }, + "java.templates.typeComment": { + "type": "array", + "markdownDescription": "Specifies the type comment for new Java type. Supports configuring multi-line comments with an array of strings, and using ${variable} to reference the [predefined variables](command:_java.templateVariables).", + "scope": "window", + "default": [], + "order": 20 + }, + "java.codeGeneration.insertionLocation": { + "type": "string", + "enum": [ + "afterCursor", + "beforeCursor", + "lastMember" + ], + "enumDescriptions": [ + "Insert the generated code after the member where the cursor is located.", + "Insert the generated code before the member where the cursor is located.", + "Insert the generated code as the last member of the target type." + ], + "description": "Specifies the insertion location of the code generated by source actions.", + "default": "afterCursor", + "scope": "window", + "order": 30 + }, + "java.codeGeneration.addFinalForNewDeclaration": { + "type": "string", + "enum": [ + "none", + "fields", + "variables", + "all" + ], + "enumDescriptions": [ + "Do not generate final modifier.", + "Generate 'final' modifier only for new field declarations.", + "Generate 'final' modifier only for new variable declarations.", + "Generate 'final' modifier for all new declarations." + ], + "description": "Whether to generate the 'final' modifer for code actions that create new declarations.", + "default": "none", + "scope": "window" + }, + "java.codeGeneration.hashCodeEquals.useJava7Objects": { + "type": "boolean", + "description": "Use Objects.hash and Objects.equals when generating the hashCode and equals methods. This setting only applies to Java 7 and higher.", + "default": false, + "scope": "window" + }, + "java.codeGeneration.hashCodeEquals.useInstanceof": { + "type": "boolean", + "description": "Use 'instanceof' to compare types when generating the hashCode and equals methods.", + "default": false, + "scope": "window" + }, + "java.codeGeneration.useBlocks": { + "type": "boolean", + "description": "Use blocks in 'if' statements when generating the methods.", + "default": false, + "scope": "window" + }, + "java.codeGeneration.generateComments": { + "type": "boolean", + "description": "Generate method comments when generating the methods.", + "default": false, + "scope": "window" + }, + "java.codeGeneration.toString.template": { + "type": "string", + "description": "The template for generating the toString method.", + "default": "${object.className} [${member.name()}=${member.value}, ${otherMembers}]" + }, + "java.codeGeneration.toString.codeStyle": { + "type": "string", + "enum": [ + "STRING_CONCATENATION", + "STRING_BUILDER", + "STRING_BUILDER_CHAINED", + "STRING_FORMAT" + ], + "enumDescriptions": [ + "String concatenation", + "StringBuilder/StringBuffer", + "StringBuilder/StringBuffer - chained call", + "String.format/MessageFormat" + ], + "description": "The code style for generating the toString method.", + "default": "STRING_CONCATENATION" + }, + "java.codeGeneration.toString.skipNullValues": { + "type": "boolean", + "description": "Skip null values when generating the toString method.", + "default": false, + "scope": "window" + }, + "java.codeGeneration.toString.listArrayContents": { + "type": "boolean", + "description": "List contents of arrays instead of using native toString().", + "default": true, + "scope": "window" + }, + "java.codeGeneration.toString.limitElements": { + "type": "integer", + "description": "Limit number of items in arrays/collections/maps to list, if 0 then list all.", + "default": 0, + "scope": "window" + }, + "java.edit.smartSemicolonDetection.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Defines the `smart semicolon` detection. Defaults to `false`.", + "scope": "window" + } } + }, + { + "id": "java-codeaction", + "title": "Code Action", + "order": 110, + "properties": { + "java.cleanup.actions": { + "type": "array", + "markdownDescription": "The list of clean ups to be run on the current document when it's saved or when the cleanup command is issued. Clean ups can automatically fix code style or programming mistakes. Click [HERE](command:_java.learnMoreAboutCleanUps) to learn more about what each clean up does.", + "items": { + "type": "string", + "enum": [ + "qualifyMembers", + "qualifyStaticMembers", + "addOverride", + "addDeprecated", + "stringConcatToTextBlock", + "invertEquals", + "addFinalModifier", + "instanceofPatternMatch", + "lambdaExpressionFromAnonymousClass", + "lambdaExpression", + "switchExpression", + "tryWithResource", + "renameFileToType", + "organizeImports", + "renameUnusedLocalVariables", + "useSwitchForInstanceofPattern", + "redundantComparisonStatement", + "redundantFallingThroughBlockEnd", + "redundantIfCondition", + "redundantModifiers", + "redundantSuperCall" + ] + }, + "default": [ + "renameFileToType" + ], + "scope": "window", + "order": 10 + }, + "java.cleanup.actionsOnSave": { + "type": "array", + "deprecationMessage": "Deprecated, please use 'java.cleanup.actions' instead.", + "items": { + "type": "string", + "enum": [ + "qualifyMembers", + "qualifyStaticMembers", + "addOverride", + "addDeprecated", + "stringConcatToTextBlock", + "invertEquals", + "addFinalModifier", + "instanceofPatternMatch", + "lambdaExpressionFromAnonymousClass", + "lambdaExpression", + "switchExpression", + "tryWithResource" + ] + }, + "default": [], + "scope": "window" + }, + "java.saveActions.cleanup": { + "type": "boolean", + "default": true, + "description": "Enable/disable cleanup actions on save." + }, + "java.saveActions.organizeImports": { + "type": "boolean", + "default": false, + "description": "Enable/disable auto organize imports on save action", + "deprecationMessage": "This setting is deprecated, please configure 'editor.codeActionsOnSave' instead.", + "scope": "window", + "order": 20 + }, + "java.updateImportsOnPaste.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable auto organize imports when pasting code", + "scope": "window", + "order": 25 + }, + "java.sources.organizeImports.starThreshold": { + "type": "integer", + "description": "Specifies the number of imports added before a star-import declaration is used.", + "default": 99, + "scope": "window", + "minimum": 1, + "order": 30 + }, + "java.sources.organizeImports.staticStarThreshold": { + "type": "integer", + "description": "Specifies the number of static imports added before a star-import declaration is used.", + "default": 99, + "scope": "window", + "minimum": 1, + "order": 40 + }, + "java.quickfix.showAt": { + "type": "string", + "enum": [ + "line", + "problem" + ], + "default": "line", + "description": "Show quickfixes at the problem or line level.", + "scope": "window" + }, + "java.codeAction.sortMembers.avoidVolatileChanges": { + "type": "boolean", + "default": true, + "description": "Reordering of fields, enum constants, and initializers can result in semantic and runtime changes due to different initialization and persistence order. This setting prevents this from occurring.", + "scope": "window" + }, + "java.refactoring.extract.interface.replace": { + "type": "boolean", + "markdownDescription": "Specify whether to replace all the occurrences of the subtype with the new extracted interface.", + "default": true + } + } + }, + { + "id": "java-codenagivation", + "title": "Code Navigation", + "order": 120, + "properties": { + "java.hover.javadoc.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable displaying Javadoc on hover.", + "scope": "window", + "order": 5 + }, + "java.referencesCodeLens.enabled": { + "type": "boolean", + "default": false, + "description": "Enable/disable the references code lens.", + "scope": "window", + "order": 10 + }, + "java.implementationCodeLens": { + "type": "string", + "enum": [ + "none", + "types", + "methods", + "all" + ], + "enumDescriptions": [ + "Disable the implementations code lens", + "Enable the implementations code lens only for types", + "Enable the implementations code lens only for methods", + "Enable the implementations code lens for types and methods" + ], + "default": "none", + "description": "Enable/disable the implementations code lens for the provided categories.", + "scope": "window", + "order": 20 + }, + "java.references.includeAccessors": { + "type": "boolean", + "default": true, + "description": "Include getter, setter and builder/constructor when finding references.", + "scope": "window", + "order": 30 + }, + "java.references.includeDeclarations": { + "type": "boolean", + "default": true, + "description": "Include declarations when finding references.", + "scope": "window", + "order": 40 + }, + "java.references.includeDecompiledSources": { + "type": "boolean", + "default": true, + "description": "Include the decompiled sources when finding references.", + "scope": "window", + "order": 50 + }, + "java.symbols.includeSourceMethodDeclarations": { + "type": "boolean", + "markdownDescription": "Include method declarations from source files in symbol search.", + "default": false, + "scope": "window", + "order": 60 + }, + "java.symbols.includeGeneratedCode": { + "type": "boolean", + "markdownDescription": "Include generated code (e.g. Lombok getters, setters, constructors) in document outline/symbols.", + "default": false, + "scope": "window", + "order": 65 + }, + "java.typeHierarchy.lazyLoad": { + "type": "boolean", + "default": false, + "description": "Enable/disable lazy loading the content in type hierarchy. Lazy loading could save a lot of loading time but every type should be expanded manually to load its content.", + "scope": "window", + "order": 70 + }, + "java.inlayHints.parameterNames.enabled": { + "type": "string", + "enum": [ + "none", + "literals", + "all" + ], + "enumDescriptions": [ + "Disable parameter name hints", + "Enable parameter name hints only for literal arguments", + "Enable parameter name hints for literal and non-literal arguments" + ], + "default": "literals", + "markdownDescription": "Enable/disable inlay hints for parameter names:\n```java\n\nInteger.valueOf(/* s: */ '123', /* radix: */ 10)\n \n```\n `#java.inlayHints.parameterNames.exclusions#` can be used to disable the inlay hints for methods.", + "scope": "window", + "order": 80 + }, + "java.inlayHints.parameterNames.suppressWhenSameNameNumbered": { + "type": "boolean", + "default": true, + "markdownDescription": "Suppress parameter name hints on arguments following the same-name numbered pattern.", + "scope": "window", + "order": 81 + }, + "java.inlayHints.parameterNames.exclusions": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "markdownDescription": "The patterns for the methods that will be disabled to show the inlay hints. Supported pattern examples:\n - `java.lang.Math.*` - All the methods from java.lang.Math.\n - `*.Arrays.asList` - Methods named as 'asList' in the types named as 'Arrays'.\n - `*.println(*)` - Methods named as 'println'.\n - `(from, to)` - Methods with two parameters named as 'from' and 'to'.\n - `(arg*)` - Methods with one parameter whose name starts with 'arg'.", + "scope": "window", + "order": 90 + }, + "java.inlayHints.variableTypes.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Enable/disable inlay hints for implicit variable types:\n```java\n\nvar foo /* :Path */ = Path.of(\"foo\");\n \n```", + "scope": "window" + }, + "java.inlayHints.parameterTypes.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Enable/disable inlay hints for (lambda) parameter types:\n```java\n\nList.of(1, 2, 3, 4).filter(/*Integer */ n -> n % 2 == 0).toList();\n \n```", + "scope": "window" + }, + "java.inlayHints.formatParameters.enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Enable/disable inlay hints for format specifiers in format strings (e.g. `String.format()`, `String.formatted()`, `PrintStream.printf()`). Shows which argument corresponds to each format specifier.", + "scope": "window" + }, + "java.search.scope": { + "type": "string", + "enum": [ + "all", + "main" + ], + "enumDescriptions": [ + "Search on all classpath entries including reference libraries and projects.", + "All classpath entries excluding test classpath entries." + ], + "default": "all", + "markdownDescription": "Specifies the scope which must be used for search operation like \n - Find Reference\n - Call Hierarchy\n - Workspace Symbols", + "scope": "window", + "order": 100 + } + } + }, + { + "id": "java-others", + "title": "Others", + "order": 130, + "properties": { + "java.eclipse.downloadSources": { + "type": "boolean", + "default": false, + "description": "Enable/disable download of Maven source artifacts for Eclipse projects.", + "scope": "window" + }, + "java.contentProvider.preferred": { + "type": "string", + "description": "Preferred content provider (a 3rd party decompiler id, usually)", + "default": null, + "scope": "window" + }, + "java.foldingRange.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable smart folding range support. If disabled, it will use the default indentation-based folding range provided by VS Code.", + "scope": "window" + }, + "java.selectionRange.enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection.", + "scope": "window" + }, + "java.edit.validateAllOpenBuffersOnChanges": { + "type": "boolean", + "default": false, + "markdownDescription": "Specifies whether to recheck all open Java files for diagnostics when editing a Java file.", + "scope": "window" + }, + "java.diagnostic.filter": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Specifies a list of file patterns for which matching documents should not have their diagnostics reported (eg. '**/Foo.java').", + "scope": "window" + }, + "java.editor.reloadChangedSources": { + "type": "string", + "enum": [ + "ask", + "auto", + "manual" + ], + "enumDescriptions": [ + "Ask to reload the sources of the open class files", + "Automatically reload the sources of the open class files", + "Manually reload the sources of the open class files" + ], + "default": "ask", + "markdownDescription": "Specifies whether to reload the sources of the open class files when their source jar files are changed.", + "scope": "window" + } + } + } + ], + "configurationDefaults": { + "[java]": { + "editor.suggest.snippetsPreventQuickSuggestions": false } }, "commands": [ + { + "command": "java.server.mode.switch", + "title": "%java.server.mode.switch%", + "category": "Java" + }, { "command": "java.projectConfiguration.update", - "title": "Update project configuration", + "title": "%java.projectConfiguration.update%", + "category": "Java" + }, + { + "command": "java.project.import.command", + "title": "%java.project.import%", "category": "Java" }, { "command": "java.open.serverLog", - "title": "Open Java Language Server log file", + "title": "%java.open.serverLog%", + "category": "Java" + }, + { + "command": "java.open.serverStdoutLog", + "title": "%java.open.serverStdoutLog%" + }, + { + "command": "java.open.serverStderrLog", + "title": "%java.open.serverStderrLog%" + }, + { + "command": "java.open.clientLog", + "title": "%java.open.clientLog%", + "category": "Java" + }, + { + "command": "java.open.logs", + "title": "%java.open.logs%", "category": "Java" }, { "command": "java.workspace.compile", - "title": "Force Java compilation", + "title": "%java.workspace.compile%", + "category": "Java" + }, + { + "command": "java.project.build", + "title": "%java.project.build%", "category": "Java" }, { "command": "java.open.formatter.settings", - "title": "Open Java formatter settings", + "title": "%java.open.formatter.settings%", "category": "Java" }, { "command": "java.clean.workspace", - "title": "Clean the Java language server workspace", + "title": "%java.clean.workspace%", "category": "Java" }, { - "command": "java.project.updateSourceAttachment", - "title": "Attach Source", + "command": "java.project.updateSourceAttachment.command", + "title": "%java.project.updateSourceAttachment%", "category": "Java" }, { - "command": "java.project.addToSourcePath", - "title": "Add Folder to Java Source Path", + "command": "java.project.addToSourcePath.command", + "title": "%java.project.addToSourcePath%", "category": "Java" }, { - "command": "java.project.removeFromSourcePath", - "title": "Remove Folder from Java Source Path", + "command": "java.project.removeFromSourcePath.command", + "title": "%java.project.removeFromSourcePath%", "category": "Java" }, { - "command": "java.project.listSourcePaths", - "title": "List all Java source paths", + "command": "java.project.listSourcePaths.command", + "title": "%java.project.listSourcePaths%", + "category": "Java" + }, + { + "command": "java.show.server.task.status", + "title": "%java.show.server.task.status%", + "category": "Java" + }, + { + "command": "java.action.navigateToSuperImplementation", + "title": "%java.action.navigateToSuperImplementation%", + "category": "Java" + }, + { + "command": "java.action.showTypeHierarchy", + "title": "%java.action.showTypeHierarchy%", + "category": "Java" + }, + { + "command": "java.action.showClassHierarchy", + "title": "%java.action.showClassHierarchy%", + "icon": "$(type-hierarchy)", + "enablement": "typeHierarchyDirection != both && typeHierarchySymbolKind != 10", + "category": "Java" + }, + { + "command": "java.action.showSupertypeHierarchy", + "title": "%java.action.showSupertypeHierarchy%", + "icon": "$(type-hierarchy-super)", + "enablement": "typeHierarchyDirection != parents", + "category": "Java" + }, + { + "command": "java.action.showSubtypeHierarchy", + "title": "%java.action.showSubtypeHierarchy%", + "icon": "$(type-hierarchy-sub)", + "enablement": "typeHierarchyDirection != children", + "category": "Java" + }, + { + "command": "java.action.changeBaseType", + "title": "%java.action.changeBaseType%", + "category": "Java" + }, + { + "command": "java.project.createModuleInfo.command", + "title": "%java.project.createModuleInfo.command%", + "category": "Java" + }, + { + "command": "_java.learnMoreAboutCleanUps", + "title": "Learn more about Java Clean Ups", + "category": "Java" + }, + { + "command": "java.clean.sharedIndexes", + "title": "%java.clean.sharedIndexes%", + "category": "Java" + }, + { + "command": "java.server.restart", + "title": "%java.server.restart%", + "category": "Java" + }, + { + "command": "java.action.filesExplorerPasteAction", + "title": "%java.action.filesExplorerPasteAction%", + "category": "Java" + }, + { + "command": "java.action.doCleanup", + "title": "%java.action.doCleanup%", + "category": "Java" + }, + { + "command": "java.change.searchScope", + "title": "%java.change.searchScope%" + }, + { + "command": "java.action.showExtendedOutline", + "title": "%java.action.showExtendedOutline%", "category": "Java" + }, + { + "command": "java.dashboard.refresh", + "category": "Java", + "title": "Refresh", + "icon": "$(refresh)", + "when": "java:dashboard == true" + }, + { + "command": "java.dashboard.dumpState", + "category": "Java", + "title": "Dump State", + "icon": "$(json)", + "when": "java:dashboard == true" + }, + { + "command": "java.dashboard.open", + "category": "Java", + "title": "Open Java Dashboard", + "icon": "$(dashboard)" + }, + { + "command": "java.runtimes.add", + "title": "%java.runtimes.add%", + "category": "Java" + }, + { + "command": "java.action.copyFullyQualifiedName", + "title": "%java.action.copyFullyQualifiedName%", + "category": "Java" } ], "keybindings": [ @@ -432,35 +1882,84 @@ { "command": "java.workspace.compile", "key": "shift+alt+b" + }, + { + "command": "java.action.clipboardPasteAction", + "key": "ctrl+shift+v", + "mac": "cmd+shift+v", + "when": "javaLSReady && editorLangId == java" + }, + { + "command": "java.action.filesExplorerPasteAction", + "key": "ctrl+shift+v", + "mac": "cmd+shift+v", + "when": "explorerViewletFocus && config.editor.pasteAs.enabled" + }, + { + "command": "java.action.doCleanup", + "key": "ctrl+shift+alt+s", + "when": "javaLSReady && editorLangId == java" + }, + { + "command": "java.action.showExtendedOutline", + "key": "ctrl+o", + "when": "javaLSReady && inQuickOpen" } ], "menus": { "explorer/context": [ { "command": "java.projectConfiguration.update", - "when": "resourceFilename =~ /(.*\\.gradle)|(pom.xml)$/", + "when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/", "group": "1_javaactions" }, { "when": "explorerResourceIsFolder&&javaLSReady", - "command": "java.project.addToSourcePath", + "command": "java.project.addToSourcePath.command", "group": "1_javaactions@1" }, { "when": "explorerResourceIsFolder&&javaLSReady", - "command": "java.project.removeFromSourcePath", + "command": "java.project.removeFromSourcePath.command", "group": "1_javaactions@2" } ], + "editor/title": [ + { + "command": "java.dashboard.refresh", + "group": "navigation", + "when": "webviewId == java.dashboard" + }, + { + "command": "java.dashboard.dumpState", + "group": "navigation", + "when": "webviewId == java.dashboard" + } + ], "editor/context": [ { - "command": "java.project.updateSourceAttachment", + "command": "java.project.updateSourceAttachment.command", "when": "editorReadonly && editorLangId == java", "group": "1_javaactions" }, { "command": "java.projectConfiguration.update", - "when": "resourceFilename =~ /(.*\\.gradle)|(pom.xml)$/", + "when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/", + "group": "1_javaactions" + }, + { + "command": "java.action.navigateToSuperImplementation", + "when": "javaLSReady && editorTextFocus && editorLangId == java", + "group": "navigation@90" + }, + { + "command": "java.action.showTypeHierarchy", + "when": "javaLSReady && editorTextFocus && editorLangId == java", + "group": "0_navigation@3" + }, + { + "command": "java.action.copyFullyQualifiedName", + "when": "javaLSReady && editorTextFocus && editorLangId == java", "group": "1_javaactions" } ], @@ -469,61 +1968,190 @@ "command": "java.projectConfiguration.update", "when": "javaLSReady" }, + { + "command": "java.project.import.command", + "when": "javaLSReady" + }, + { + "command": "java.open.serverStdoutLog", + "when": "false" + }, + { + "command": "java.open.serverStderrLog", + "when": "false" + }, + { + "command": "java.action.navigateToSuperImplementation", + "when": "javaLSReady && editorLangId == java" + }, { "command": "java.workspace.compile", "when": "javaLSReady" }, { - "command": "java.project.listSourcePaths", + "command": "java.project.build", "when": "javaLSReady" }, { - "command": "java.project.updateSourceAttachment", + "command": "java.project.listSourcePaths.command", + "when": "javaLSReady" + }, + { + "command": "java.action.showTypeHierarchy", + "when": "javaLSReady && editorIsOpen" + }, + { + "command": "java.action.showClassHierarchy", + "when": "false" + }, + { + "command": "java.action.showSubtypeHierarchy", + "when": "false" + }, + { + "command": "java.action.showSupertypeHierarchy", + "when": "false" + }, + { + "command": "java.action.changeBaseType", + "when": "false" + }, + { + "command": "java.project.updateSourceAttachment.command", + "when": "false" + }, + { + "command": "java.project.addToSourcePath.command", + "when": "false" + }, + { + "command": "java.project.removeFromSourcePath.command", "when": "false" }, { - "command": "java.project.addToSourcePath", + "command": "java.show.server.task.status", + "when": "java:serverMode != LightWeight" + }, + { + "command": "java.server.mode.switch", + "when": "java:serverMode == LightWeight" + }, + { + "command": "java.server.restart", + "when": "javaLSReady" + }, + { + "command": "java.action.filesExplorerPasteAction", "when": "false" }, { - "command": "java.project.removeFromSourcePath", + "command": "java.action.doCleanup", "when": "false" } + ], + "view/title": [ + { + "command": "java.action.showClassHierarchy", + "group": "navigation@-1", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy && typeHierarchySymbolKind != 10" + }, + { + "command": "java.action.showSupertypeHierarchy", + "group": "navigation@0", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy" + }, + { + "command": "java.action.showSubtypeHierarchy", + "group": "navigation@1", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy" + } + ], + "view/item/context": [ + { + "command": "java.action.changeBaseType", + "group": "1", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy && viewItem != 'false'" + } ] } }, "scripts": { - "vscode:prepublish": "webpack --mode production", - "compile": "tsc -p ./", - "watch": "webpack --mode development --watch --info-verbosity verbose", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "node ./node_modules/vscode/bin/test", - "build-server": "./node_modules/.bin/gulp build_server", - "watch-server": "./node_modules/.bin/gulp watch_server", - "webpack": "webpack --mode development" + "vscode:prepublish": "node scripts/prepublish.mjs", + "compile": "tsc -p ./&webpack --mode development", + "watch": "webpack --mode development --watch", + "pretest": "npm run compile", + "test": "node ./out/test/runtest.js", + "build-server": "node scripts/index.mjs build-server", + "build": "node scripts/index.mjs build-or-download", + "fast-build-server": "node scripts/index.mjs dev-server", + "watch-server": "node scripts/index.mjs watch-server", + "eslint": "eslint --ignore-path .eslintignore --ext .js,.ts,.tsx .", + "repo:check": "node scripts/index.mjs repo-check", + "repo:fix": "node scripts/index.mjs repo-fix", + "clean-jre": "node scripts/index.mjs clean-jre", + "download-jre": "node scripts/index.mjs download-jre", + "download-lombok": "node scripts/index.mjs download-lombok", + "download-server": "node scripts/index.mjs download-server", + "generate-standard-test-folder": "node scripts/index.mjs generate-standard-test-folder", + "generate-lightweight-test-folder": "node scripts/index.mjs generate-lightweight-test-folder", + "clean-test-folder": "node scripts/index.mjs clean-test-folder", + "prepare-pre-release": "node scripts/index.mjs prepare-pre-release" }, "devDependencies": { + "@types/fs-extra": "^8.0.0", "@types/glob": "5.0.30", + "@types/lodash.findindex": "^4.6.6", "@types/mocha": "^5.2.5", - "@types/node": "^6.0.40", - "gulp": "^4.0.0", - "gulp-decompress": "2.0.1", - "gulp-download": "0.0.1", - "mocha": "^5.2.0", - "ts-loader": "^5.3.1", - "tslint": "^5.11.0", - "typescript": "^3.4.1", - "typescript-tslint-plugin": "^0.3.1", - "vscode": "^1.1.33", - "webpack": "^4.27.1", - "webpack-cli": "^3.1.2" + "@types/node": "^18.17.1", + "@types/react": "^17.0.37", + "@types/react-dom": "^17.0.11", + "@types/semver": "^7.3.8", + "@types/sinon": "^10.0.12", + "@types/vscode": "^1.77.0", + "@types/vscode-webview": "^1.57.0", + "@types/winreg": "^1.2.30", + "@types/winston": "^2.4.4", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "@vscode/test-electron": "^2.5.2", + "css-loader": "^6.7.3", + "eslint": "^8.13.0", + "eslint-webpack-plugin": "^3.2.0", + "lodash.findindex": "^4.6.0", + "mini-css-extract-plugin": "^2.9.4", + "minimist": ">=1.2.6", + "mocha": "^11.1.0", + "sinon": "^14.0.0", + "tar": "^7.5.11", + "ts-loader": "^9.4.2", + "typescript": "^4.6.4", + "webpack": "^5.105.0", + "webpack-cli": "^4.6.0" }, "dependencies": { - "vscode-languageclient": "~5.1.1", - "find-java-home": "0.2.0", - "tmp": "^0.0.33", - "path-exists": "^3.0.0", + "@redhat-developer/vscode-extension-proposals": "0.0.23", + "@redhat-developer/vscode-redhat-telemetry": "0.10.2", + "@vscode/codicons": "^0.0.32", + "@vscode/webview-ui-toolkit": "1.2.2", + "chokidar": "^3.5.3", "expand-home-dir": "^0.0.3", - "glob": "^7.1.3" - } + "fmtr": "^1.1.2", + "fs-extra": "^8.1.0", + "glob": "^11.1.0", + "htmlparser2": "6.0.1", + "jdk-utils": "^0.6.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "semver": "^7.5.2", + "vscode-languageclient": "8.2.0-next.3", + "vscode-variables": "^1.0.1", + "winreg-utf8": "^0.1.1", + "winston": "^3.2.1", + "winston-daily-rotate-file": "^4.7.1" + }, + "overrides": { + "vscode-languageserver-protocol": "3.17.6-next.1" + }, + "segmentWriteKey": "Y7Y5Xk8dKEhVZHTmAkFZkqgdN4d7c4lt", + "segmentWriteKeyDebug": "BflPll7uuKOCm3y0g7JpfXLVBVFBivDE" } diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 0000000000..c695cfe3e6 --- /dev/null +++ b/package.nls.json @@ -0,0 +1,35 @@ +{ + "java.server.mode.switch": "Switch to Standard Mode", + "java.projectConfiguration.update": "Reload Projects", + "java.project.import": "Import Java Projects into Workspace", + "java.open.serverLog": "Open Java Language Server Log File", + "java.open.serverStdoutLog": "Open Java Language Server Output Log File", + "java.open.serverStderrLog": "Open Java Language Server Error Log File", + "java.open.clientLog": "Open Java Extension Log File", + "java.open.logs": "Open All Log Files", + "java.workspace.compile": "Force Java Compilation", + "java.project.build": "Rebuild Projects", + "java.open.formatter.settings": "Open Java Formatter Settings", + "java.clean.workspace": "Clean Java Language Server Workspace", + "java.project.updateSourceAttachment": "Attach Source...", + "java.project.addToSourcePath": "Add Folder to Java Source Path", + "java.project.removeFromSourcePath": "Remove Folder from Java Source Path", + "java.project.listSourcePaths": "List All Java Source Paths", + "java.show.server.task.status": "Show Build Job Status", + "java.action.navigateToSuperImplementation": "Go to Super Implementation", + "java.action.showTypeHierarchy": "Show Type Hierarchy", + "java.action.showClassHierarchy": "Show Class Hierarchy", + "java.action.showSupertypeHierarchy": "Show Supertype Hierarchy", + "java.action.showSubtypeHierarchy": "Show Subtype Hierarchy", + "java.action.changeBaseType": "Base on this Type", + "java.project.createModuleInfo.command": "Create module-info.java", + "java.clean.sharedIndexes": "Clean Shared Indexes", + "java.server.restart": "Restart Java Language Server", + "java.edit.smartSemicolonDetection": "Java Smart Semicolon Detection", + "java.action.filesExplorerPasteAction": "Paste Clipboard Text Into a File", + "java.action.doCleanup": "Performs Cleanup Actions", + "java.change.searchScope": "Change Search Scope", + "java.action.showExtendedOutline": "Open Extended Outline", + "java.runtimes.add": "Add Java Runtime", + "java.action.copyFullyQualifiedName": "Copy Fully Qualified Name" +} diff --git a/package.nls.ko.json b/package.nls.ko.json new file mode 100644 index 0000000000..0b185fa056 --- /dev/null +++ b/package.nls.ko.json @@ -0,0 +1,33 @@ +{ + "java.server.mode.switch": "Standard 모드로 전환", + "java.projectConfiguration.update": "프로젝트 다시 로드", + "java.project.import": "작업 영역으로 Java 프로젝트 가져오기", + "java.open.serverLog": "Java Language Server 로그 파일 열기", + "java.open.serverStdoutLog": "Java Language Server 출력 로그 파일 열기", + "java.open.serverStderrLog": "Java Language Server 오류 로그 파일 열기", + "java.open.clientLog": "Java Extension 로그 파일 열기", + "java.open.logs": "모든 로그 파일 열기", + "java.workspace.compile": "Java 컴파일 강제 실행", + "java.project.build": "프로젝트 다시 빌드", + "java.open.formatter.settings": "Java Formatter 설정 열기", + "java.clean.workspace": "Java Language Server 작업 영역 정리", + "java.project.updateSourceAttachment": "소스 첨부...", + "java.project.addToSourcePath": "Java 소스 경로에 폴더 추가", + "java.project.removeFromSourcePath": "Java 소스 경로에서 폴더 제거", + "java.project.listSourcePaths": "모든 Java 소스 경로 표시", + "java.show.server.task.status": "빌드 작업 상태 표시", + "java.action.navigateToSuperImplementation": "상위 구현으로 이동", + "java.action.showTypeHierarchy": "Type 계층 구조 표시", + "java.action.showClassHierarchy": "Class 계층 구조 표시", + "java.action.showSupertypeHierarchy": "Supertype 계층 구조 표시", + "java.action.showSubtypeHierarchy": "Subtype 계층 구조 표시", + "java.action.changeBaseType": "이 타입을 기준으로", + "java.project.createModuleInfo.command": "module-info.java 생성", + "java.clean.sharedIndexes": "공유 인덱스 정리", + "java.server.restart": "Java Language Server 다시 시작", + "java.edit.smartSemicolonDetection": "Java 스마트 세미콜론 감지", + "java.action.filesExplorerPasteAction": "클립보드 텍스트를 파일에 붙여넣기", + "java.action.doCleanup": "정리 작업을 수행", + "java.change.searchScope": "검색 범위 변경", + "java.action.showExtendedOutline": "확장 개요 열기" +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json new file mode 100644 index 0000000000..2526d4c36a --- /dev/null +++ b/package.nls.zh-cn.json @@ -0,0 +1,29 @@ +{ + "java.server.mode.switch": "切换到标准模式", + "java.projectConfiguration.update": "重新加载项目", + "java.project.import": "将 Java 项目导入工作区", + "java.open.serverLog": "打开 Java 语言服务器日志文件", + "java.open.serverStdoutLog": "打开 Java 语言服务器输出日志文件", + "java.open.serverStderrLog": "打开 Java 语言服务器错误日志文件", + "java.open.clientLog": "打开 Java 插件日志文件", + "java.open.logs": "打开所有日志文件", + "java.workspace.compile": "强制编译", + "java.project.build": "重新构建项目", + "java.open.formatter.settings": "打开 Java 格式设置", + "java.clean.workspace": "清理 Java 语言服务器工作区", + "java.project.updateSourceAttachment": "附加源代码...", + "java.project.addToSourcePath": "将文件夹加入 Java 源代码路径", + "java.project.removeFromSourcePath": "将文件夹从 Java 源代码路径中删除", + "java.project.listSourcePaths": "列出所有 Java 源代码路径", + "java.show.server.task.status": "显示工作状态", + "java.action.navigateToSuperImplementation": "转到父类实现", + "java.action.showTypeHierarchy": "显示类型层次结构", + "java.action.showClassHierarchy": "显示类的继承关系", + "java.action.showSupertypeHierarchy": "显示父类层次结构", + "java.action.showSubtypeHierarchy": "显示子类层次结构", + "java.action.changeBaseType": "基于此类型", + "java.project.createModuleInfo.command": "创建 module-info.java", + "java.clean.sharedIndexes": "清理共享的索引文件", + "java.action.filesExplorerPasteAction": "将剪贴板文本粘贴到文件中", + "java.action.doCleanup": "执行清理操作" +} diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json new file mode 100644 index 0000000000..808fc1d97e --- /dev/null +++ b/package.nls.zh-tw.json @@ -0,0 +1,28 @@ +{ + "java.server.mode.switch": "切換到標準模式", + "java.projectConfiguration.update": "重新載入專案", + "java.project.import": "匯入 Java 專案到工作區", + "java.open.serverLog": "開啟 Java 語言伺服器日誌檔", + "java.open.serverStdoutLog": "開啟 Java 語言伺服器輸出日誌檔", + "java.open.serverStderrLog": "開啟 Java 語言伺服器錯誤日誌檔", + "java.open.clientLog": "開啟 Java 延伸模組日誌檔", + "java.open.logs": "開啟所有日誌檔", + "java.workspace.compile": "強制編譯 Java", + "java.project.build": "重新建置專案", + "java.open.formatter.settings": "開啟 Java 格式設定", + "java.clean.workspace": "清理 Java 語言伺服器工作區", + "java.project.updateSourceAttachment": "附加原始碼...", + "java.project.addToSourcePath": "將資料夾加入 Java 原始碼路徑", + "java.project.removeFromSourcePath": "從 Java 始碼路徑中移除資料夾", + "java.project.listSourcePaths": "列出所有 Java 始碼路徑", + "java.show.server.task.status": "顯示建置工作狀態", + "java.action.navigateToSuperImplementation": "移到父類別中的實作", + "java.action.showTypeHierarchy": "顯示型別階層結構", + "java.action.showClassHierarchy": "顯示類別階層結構", + "java.action.showSupertypeHierarchy": "顯示父類別階層結構", + "java.action.showSubtypeHierarchy": "顯示子類別階層結構", + "java.action.changeBaseType": "以此型別為基礎", + "java.project.createModuleInfo.command": "創建 module-info.java", + "java.action.filesExplorerPasteAction": "將剪貼簿文字貼到文件中", + "java.action.doCleanup": "執行清理操作" +} \ No newline at end of file diff --git a/schemas/package.schema.json b/schemas/package.schema.json new file mode 100644 index 0000000000..53d17634ce --- /dev/null +++ b/schemas/package.schema.json @@ -0,0 +1,68 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "contributes": { + "type": "object", + "properties": { + "javaExtensions": { + "type": "array", + "markdownDescription": "Java language server extensions", + "items": { + "type": "string", + "description": "Relative path to a Java language server extension JAR file" + } + }, + "javaBuildFilePatterns": { + "type": "array", + "markdownDescription": "Java build file patterns", + "items": { + "type": "string", + "description": "Regular expressions for specifying build file" + } + }, + "javaBuildTools": { + "type": "array", + "description": "Information about the cared build files. Will be used when 'java.import.projectSelection' is 'manual'.", + "items": { + "type": "object", + "properties": { + "displayName": { + "description": "The display name of the build file type.", + "type": "string" + }, + "buildFileNames": { + "description": "The build file names that supported by the build tool.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "javaShortcuts": { + "type": "array", + "description": "Shortcuts to be listed when clicking server status bar item.", + "items": { + "type": "object", + "properties": { + "title": { + "description": "The title of the quick pick item.", + "type": "string" + }, + "command": { + "description": "The command to be executed when the quick pick is selected.", + "type": "string" + }, + "arguments": { + "description": "The arguments to be passed to the command.", + "type": "array" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/scripts/index.mjs b/scripts/index.mjs new file mode 100644 index 0000000000..ceb5f9c862 --- /dev/null +++ b/scripts/index.mjs @@ -0,0 +1,143 @@ +#!/usr/bin/env node + +import { cleanJre, downloadJre } from './jre.mjs'; +import { downloadLombok } from './lombok.mjs'; +import { downloadServer, buildServer, buildOrDownload, devServer, watchServer } from './server.mjs'; +import { generateStandardTestFolder, generateLightweightTestFolder, cleanTestFolder } from './test.mjs'; +import { preparePreRelease } from './release.mjs'; +import { repoCheck, repoFix } from './repo.mjs'; +import { pathToFileURL } from 'url'; + +async function main() { + const command = process.argv[2]; + const args = process.argv.slice(3); + + switch (command) { + // JRE commands + case 'clean-jre': + await cleanJre(); + break; + case 'download-jre': + const targetIndex = args.indexOf('--target'); + const versionIndex = args.indexOf('--javaVersion'); + const targetPlatform = targetIndex !== -1 ? args[targetIndex + 1] : undefined; + const javaVersion = versionIndex !== -1 ? args[versionIndex + 1] : undefined; + await downloadJre(targetPlatform, javaVersion); + break; + + // Lombok commands + case 'download-lombok': + await downloadLombok(); + break; + + // Server commands + case 'download-server': + await downloadServer(); + break; + case 'build-server': + try { + await buildServer(); + } catch (error) { + console.error('Build failed:', error.message); + process.exit(1); + } + break; + case 'build-or-download': + await buildOrDownload(); + break; + case 'dev-server': + await devServer(); + break; + case 'watch-server': + try { + await watchServer(); + } catch (error) { + console.error('Error:', error.message); + process.exit(1); + } + break; + + // Test commands + case 'generate-standard-test-folder': + await generateStandardTestFolder(); + break; + case 'generate-lightweight-test-folder': + await generateLightweightTestFolder(); + break; + case 'clean-test-folder': + await cleanTestFolder(); + break; + + // Release commands + case 'prepare-pre-release': + await preparePreRelease(); + break; + + // Repository commands + case 'repo-check': + await repoCheck(); + break; + case 'repo-fix': + await repoFix(); + break; + + default: + console.log(` +Usage: node scripts/index.js [options] + +Commands: + JRE Management: + clean-jre Clean JRE directory + download-jre [--target ] [--javaVersion ] Download JRE + + Lombok Management: + download-lombok Download Lombok + + Server Management: + download-server Download JDT Language Server + build-server Build JDT Language Server + build-or-download Build or download JDT Language Server + dev-server Build development server + watch-server Watch server files for changes + + Test Environment: + generate-standard-test-folder Generate standard test folder + generate-lightweight-test-folder Generate lightweight test folder + clean-test-folder Clean test folder + + Release Management: + prepare-pre-release Prepare pre-release version + + Repository Management: + repo-check Check package-lock.json for internal registry references + repo-fix Fix package-lock.json registry references + +Examples: + node scripts/index.js download-jre --target darwin-x64 --javaVersion 21 + node scripts/index.js build-or-download + node scripts/index.js watch-server + `); + process.exit(1); + } +} + +if (import.meta.url === pathToFileURL(process.argv[1]).toString()) { + main().catch(console.error); +} + +export { + cleanJre, + downloadJre, + downloadLombok, + downloadServer, + buildServer, + buildOrDownload, + devServer, + watchServer, + generateStandardTestFolder, + generateLightweightTestFolder, + cleanTestFolder, + preparePreRelease, + repoCheck, + repoFix +}; diff --git a/scripts/jre.mjs b/scripts/jre.mjs new file mode 100644 index 0000000000..0485afda75 --- /dev/null +++ b/scripts/jre.mjs @@ -0,0 +1,127 @@ +#!/usr/bin/env node +/* eslint-disable @typescript-eslint/naming-convention */ + +import fs from 'fs-extra'; +import path from 'path'; +import https from 'https'; +import { downloadFile, getScriptDir, extractTarGz, handleError, setupMainExecution } from './utils.mjs'; + +const dirname = getScriptDir(); + +const LATEST_JRE = 21; + +const platformMapping = { + "linux-arm64": "linux-aarch64", + "linux-x64": "linux-x86_64", + "darwin-arm64": "macosx-aarch64", + "darwin-x64": "macosx-x86_64", + "win32-x64": "win32-x86_64", + "win32-arm64": "win32-aarch64" +}; + + +async function downloadManifest(manifestUrl) { + return new Promise((resolve, reject) => { + https.get(manifestUrl, (response) => { + if (response.statusCode >= 400) { + reject(new Error(`${response.statusCode} returned from ${manifestUrl}`)); + return; + } + let body = ''; + response.on('data', (chunk) => body += chunk); + response.on('end', () => resolve(body)); + }).on('error', reject); + }); +} + + +async function cleanJre() { + if (fs.existsSync('./jre')) { + fs.removeSync('./jre'); + console.log('Cleaned JRE directory'); + } +} + +async function downloadJre(targetPlatform, javaVersion) { + if (fs.existsSync('./jre')) { + fs.removeSync('./jre'); + } + + if (!targetPlatform || !Object.keys(platformMapping).includes(targetPlatform)) { + console.log("[Error] download_jre failed, please specify a valid target platform via --target argument. Here are the supported platform list:"); + for (const platform of Object.keys(platformMapping)) { + console.log(platform); + } + return; + } + + const version = (!javaVersion || javaVersion === "latest") ? LATEST_JRE : javaVersion; + console.log(`Downloading justj JRE ${version} for the platform ${targetPlatform}...`); + + const manifestUrl = `https://download.eclipse.org/justj/jres/${version}/downloads/latest/justj.manifest`; + + try { + const manifest = await downloadManifest(manifestUrl); + + if (!manifest) { + throw new Error(`Failed to download justj.manifest, please check if the link ${manifestUrl} is valid.`); + } + + const javaPlatform = platformMapping[targetPlatform]; + const list = manifest.split(/\r?\n/); + const jreIdentifier = list.find((value) => { + return value.indexOf("org.eclipse.justj.openjdk.hotspot.jre.full.stripped") >= 0 && value.indexOf(javaPlatform) >= 0; + }); + + if (!jreIdentifier) { + throw new Error(`justj doesn't support the jre ${version} for the platform ${javaPlatform} (${targetPlatform}), please refer to the link ${manifestUrl} for the supported platforms.`); + } + + const jreDownloadUrl = `https://download.eclipse.org/justj/jres/${version}/downloads/latest/${jreIdentifier}`; + const parsedDownloadUrl = new URL(jreDownloadUrl); + const jreFileName = path.basename(parsedDownloadUrl.pathname) + .replace(/[\.7z|\.bz2|\.gz|\.rar|\.tar|\.zip|\.xz]*$/, ""); + const idx = jreFileName.indexOf('-'); + const jreVersionLabel = idx >= 0 ? jreFileName.substring(idx + 1) : jreFileName; + + const tempFile = path.join(dirname, 'temp-jre.tar.gz'); + const destDir = path.join('./jre', jreVersionLabel); + + // Ensure the jre directory exists + fs.ensureDirSync('./jre'); + fs.ensureDirSync(destDir); + + console.log(`Downloading JRE from ${jreDownloadUrl}...`); + await downloadFile(jreDownloadUrl, tempFile); + + console.log(`Extracting JRE to ${destDir}...`); + await extractTarGz(tempFile, destDir); + + // Clean up temp file + fs.removeSync(tempFile); + + console.log(`Successfully downloaded and extracted JRE ${jreVersionLabel}`); + } catch (error) { + handleError(error, 'downloading JRE'); + } +} + +// Main execution +async function main() { + const args = process.argv.slice(2); + const targetIndex = args.indexOf('--target'); + const versionIndex = args.indexOf('--javaVersion'); + + const targetPlatform = targetIndex !== -1 ? args[targetIndex + 1] : `${process.platform}-${process.arch}`; + const javaVersion = versionIndex !== -1 ? args[versionIndex + 1] : LATEST_JRE; + + if (args.includes('clean')) { + await cleanJre(); + } else { + await downloadJre(targetPlatform, javaVersion); + } +} + +setupMainExecution(main); + +export { cleanJre, downloadJre }; diff --git a/scripts/lombok.mjs b/scripts/lombok.mjs new file mode 100644 index 0000000000..fe372e2b2b --- /dev/null +++ b/scripts/lombok.mjs @@ -0,0 +1,36 @@ +#!/usr/bin/env node + +import fs from 'fs-extra'; +import path from 'path'; +import { downloadFile, handleError, setupMainExecution } from './utils.mjs'; + +async function downloadLombok() { + if (fs.existsSync('./lombok')) { + fs.removeSync('./lombok'); + } + + try { + const lombokVersion = '1.18.38'; + // The latest lombok version can be found on the website https://projectlombok.org/downloads + const lombokUrl = `https://projectlombok.org/downloads/lombok-${lombokVersion}.jar`; + + // Ensure the lombok directory exists + fs.ensureDirSync('./lombok'); + + console.log(`Downloading Lombok ${lombokVersion}...`); + await downloadFile(lombokUrl, path.join('./lombok', `lombok-${lombokVersion}.jar`)); + + console.log(`Successfully downloaded Lombok ${lombokVersion}`); + } catch (error) { + handleError(error, 'downloading Lombok'); + } +} + +// Main execution +async function main() { + await downloadLombok(); +} + +setupMainExecution(main); + +export { downloadLombok }; diff --git a/scripts/prepublish.mjs b/scripts/prepublish.mjs new file mode 100644 index 0000000000..4159eef9fa --- /dev/null +++ b/scripts/prepublish.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env node + +// Skip webpack if SKIP_WEBPACK environment variable is set to 'true' +if (process.env.SKIP_WEBPACK === 'true') { + console.log('Skipping webpack compilation (SKIP_WEBPACK=true)'); + process.exit(0); +} + +// Otherwise, run webpack using the local webpack-cli installation +const { spawn } = await import('child_process'); +const { fileURLToPath } = await import('url'); +const { dirname, resolve, join } = await import('path'); + +const scriptFilename = fileURLToPath(import.meta.url); +const scriptDirname = dirname(scriptFilename); +const projectRoot = resolve(scriptDirname, '..'); + +// Use webpack-cli from local node_modules (cross-platform) +const webpackCliPath = join(projectRoot, 'node_modules', '.bin', 'webpack'); +const isWindows = process.platform === 'win32'; +const webpackCommand = isWindows ? `${webpackCliPath}.cmd` : webpackCliPath; + +const webpack = spawn(webpackCommand, ['--mode', 'production'], { + stdio: 'inherit', + cwd: projectRoot +}); + +webpack.on('close', (code) => { + process.exit(code || 0); +}); + +webpack.on('error', (error) => { + console.error('Error running webpack:', error); + process.exit(1); +}); diff --git a/scripts/release.mjs b/scripts/release.mjs new file mode 100644 index 0000000000..d9433b8ea9 --- /dev/null +++ b/scripts/release.mjs @@ -0,0 +1,60 @@ +#!/usr/bin/env node + +import fs from 'fs-extra'; +import { getProjectPath, handleError, setupMainExecution } from './utils.mjs'; + +function prependZero(num) { + if (num > 99) { + throw "Unexpected value to prepend with zero"; + } + return `${num < 10 ? "0" : ""}${num}`; +} + +async function preparePreRelease() { + console.log('Preparing pre-release version...'); + + try { + const packageJsonPath = getProjectPath('package.json'); + const json = JSON.parse(fs.readFileSync(packageJsonPath).toString()); + const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/); + + if (!stableVersion) { + throw new Error('Invalid version format in package.json'); + } + + const major = stableVersion[1]; + const minor = stableVersion[2]; + const date = new Date(); + const month = date.getMonth() + 1; + const day = date.getDate(); + const hours = date.getHours(); + const patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`; + + const insiderPackageJson = Object.assign(json, { + version: `${major}.${minor}.${patch}`, + }); + + fs.writeFileSync(packageJsonPath, JSON.stringify(insiderPackageJson, null, 2)); + console.log(`Successfully updated version to ${insiderPackageJson.version}`); + } catch (error) { + handleError(error, 'preparing pre-release'); + } +} + +// Main execution +async function main() { + const command = process.argv[2]; + + switch (command) { + case 'prepare': + await preparePreRelease(); + break; + default: + console.log('Usage: node release.js [prepare]'); + process.exit(1); + } +} + +setupMainExecution(main); + +export { preparePreRelease }; diff --git a/scripts/repo.mjs b/scripts/repo.mjs new file mode 100644 index 0000000000..1f51e2452f --- /dev/null +++ b/scripts/repo.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +import fs from 'fs-extra'; +import { getProjectPath, handleError, setupMainExecution } from './utils.mjs'; + +const NON_NPM_REPOSITORY_RE = new RegExp( + String.raw`"resolved":\s*"https://.+/registry.npmjs.org/`, + "g" +); + +async function repoCheck() { + console.log('Checking package-lock.json for internal registry references...'); + + try { + const packageLockPath = getProjectPath('package-lock.json'); + const data = fs.readFileSync(packageLockPath, { encoding: "utf-8" }); + + if (NON_NPM_REPOSITORY_RE.test(data)) { + console.error("Found references to the internal registry in the file package-lock.json. Please fix it with 'npm run repo:fix'"); + process.exit(1); + } else { + console.log('No internal registry references found'); + } + } catch (error) { + handleError(error, 'checking repository'); + } +} + +async function repoFix() { + console.log('Fixing package-lock.json registry references...'); + + try { + const packageLockPath = getProjectPath('package-lock.json'); + const data = fs.readFileSync(packageLockPath, { encoding: "utf-8" }); + const newData = data.replace(NON_NPM_REPOSITORY_RE, `"resolved": "https://registry.npmjs.org/`); + + if (data !== newData) { + fs.writeFileSync(packageLockPath, newData, { + encoding: "utf-8", + }); + console.log('Successfully fixed package-lock.json'); + } else { + console.log('Nothing to fix'); + } + } catch (error) { + handleError(error, 'fixing repository'); + } +} + +// Main execution +async function main() { + const command = process.argv[2]; + + switch (command) { + case 'check': + await repoCheck(); + break; + case 'fix': + await repoFix(); + break; + default: + console.log('Usage: node repo.js [check|fix]'); + process.exit(1); + } +} + +setupMainExecution(main); + +export { repoCheck, repoFix }; diff --git a/scripts/server.mjs b/scripts/server.mjs new file mode 100644 index 0000000000..2037d99c9b --- /dev/null +++ b/scripts/server.mjs @@ -0,0 +1,167 @@ +#!/usr/bin/env node + +/* eslint-disable no-underscore-dangle */ + +import fs from 'fs-extra'; +import path from 'path'; +import { execSync } from 'child_process'; +import chokidar from 'chokidar'; +import { glob } from 'glob'; +import { downloadFile, getScriptDir, extractTarGz, handleError, setupMainExecution } from './utils.mjs'; + +const dirname = getScriptDir(); + +const serverDir = path.join(dirname, '..', '..', 'eclipse.jdt.ls'); +const JDT_LS_SNAPSHOT_URL = "https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz"; + +function isWin() { + return /^win/.test(process.platform); +} + +function mvnw() { + return isWin() ? "mvnw.cmd" : "./mvnw"; +} + + +async function downloadServer() { + console.log('Downloading Eclipse JDT Language Server snapshot...'); + + fs.removeSync('./server'); + fs.ensureDirSync('./server'); + + const tempFile = path.join(dirname, 'temp-server.tar.gz'); + + try { + await downloadFile(JDT_LS_SNAPSHOT_URL, tempFile); + await extractTarGz(tempFile, './server'); + fs.removeSync(tempFile); + + console.log('Successfully downloaded and extracted JDT Language Server'); + } catch (error) { + handleError(error, 'downloading server'); + } +} + +async function buildServer() { + console.log('Building Eclipse JDT Language Server...'); + + fs.removeSync('./server'); + fs.ensureDirSync('./server'); + + try { + const command = `${mvnw() } -Pserver-distro clean package -U -Declipse.jdt.ls.skipGradleChecksums`; + console.log(`Executing: ${command}`); + execSync(command, { cwd: serverDir, stdio: [0, 1, 2] }); + + const sources = await glob(`${serverDir }/org.eclipse.jdt.ls.product/distro/*.tar.gz`); + + if (sources.length > 0) { + await extractTarGz(sources[0], './server'); + console.log('Successfully built and extracted JDT Language Server'); + } else { + throw new Error('No server distribution found after build'); + } + } catch (error) { + handleError(error, 'building server', false); + throw error; + } +} + +async function buildOrDownload() { + if (!fs.existsSync(serverDir)) { + console.log('NOTE: eclipse.jdt.ls is not found as a sibling directory, downloading the latest snapshot of the Eclipse JDT Language Server...'); + await downloadServer(); + } else { + await buildServer(); + } +} + +async function devServer() { + console.log('Building development server...'); + + try { + const command = `${mvnw() } -o -pl org.eclipse.jdt.ls.core,org.eclipse.jdt.ls.target clean package -Declipse.jdt.ls.skipGradleChecksums`; + console.log(`Executing: ${command}`); + execSync(command, { cwd: serverDir, stdio: [0, 1, 2] }); + + const sources = await glob(`${serverDir }/org.eclipse.jdt.ls.core/target/org.eclipse.jdt.ls.core-*-SNAPSHOT.jar`); + const targets = await glob('./server/plugins/org.eclipse.jdt.ls.core_*.jar'); + + if (sources.length > 0 && targets.length > 0) { + console.log(`Copying ${sources[0]} to ${targets[0]}`); + fs.copySync(sources[0], targets[0]); + console.log('Successfully built development server'); + } else { + throw new Error('Source or target JAR files not found'); + } + } catch (error) { + handleError(error, 'building development server'); + } +} + +async function watchServer() { + console.log('Watching server files for changes...'); + // if server_dir is not a directory, throw an error + if (!fs.existsSync(serverDir)) { + throw new Error(`Server directory '${serverDir}' does not exist. This command is for JDT Language Server development. You need to have the eclipse.jdt.ls repository as a sibling directory to use this feature.`); + } + const watcher = chokidar.watch(`${serverDir }/org.eclipse.jdt.ls.core/**/*.java`, { + ignored: /(^|[\/\\])\../, // ignore dotfiles + persistent: true + }); + + watcher.on('change', async (path) => { + console.log(`File ${path} has been changed, rebuilding...`); + try { + await devServer(); + } catch (error) { + handleError(error, 'rebuilding server', false); + } + }); + + console.log('Watching for changes. Press Ctrl+C to stop.'); + + // Handle graceful shutdown + process.on('SIGINT', () => { + console.log('\nStopping watcher...'); + watcher.close(); + process.exit(0); + }); + + // Keep the process alive by waiting indefinitely + return new Promise((resolve, reject) => { + console.log('Watcher is now active and waiting for file changes...'); + // This promise never resolves, keeping the process alive + // The process will only exit when SIGINT is received + }); +} + +// Main execution +async function main() { + const command = process.argv[2]; + + switch (command) { + case 'download': + await downloadServer(); + break; + case 'build': + await buildServer(); + break; + case 'build-or-download': + await buildOrDownload(); + break; + case 'dev': + await devServer(); + break; + case 'watch': + await watchServer(); + break; + default: + console.log('Usage: node server.js [download|build|build-or-download|dev|watch]'); + process.exit(1); + } +} + +setupMainExecution(main); + +export { downloadServer, buildServer, buildOrDownload, devServer, watchServer }; diff --git a/scripts/test.mjs b/scripts/test.mjs new file mode 100644 index 0000000000..3886c5c197 --- /dev/null +++ b/scripts/test.mjs @@ -0,0 +1,82 @@ +#!/usr/bin/env node +/* eslint-disable @typescript-eslint/naming-convention */ + +import fs from 'fs-extra'; +import path from 'path'; +import { getProjectPath, handleError, setupMainExecution } from './utils.mjs'; + +const originalTestFolder = getProjectPath('test', 'resources', 'projects', 'maven', 'salut'); +const tempTestFolder = getProjectPath('test-temp'); +const testSettings = path.join(tempTestFolder, '.vscode', 'settings.json'); + +async function generateStandardTestFolder() { + console.log('Generating standard test folder...'); + + try { + fs.copySync(originalTestFolder, tempTestFolder); + fs.ensureDirSync(path.join(tempTestFolder, '.vscode')); + fs.writeJSONSync(testSettings, { + "java.server.launchMode": "Standard", + "java.configuration.updateBuildConfiguration": "automatic" + }); + + console.log('Successfully generated standard test folder'); + } catch (error) { + handleError(error, 'generating standard test folder'); + } +} + +async function generateLightweightTestFolder() { + console.log('Generating lightweight test folder...'); + + try { + fs.copySync(originalTestFolder, tempTestFolder); + fs.ensureDirSync(path.join(tempTestFolder, '.vscode')); + fs.writeJSONSync(testSettings, { + "java.server.launchMode": "LightWeight", + }); + + console.log('Successfully generated lightweight test folder'); + } catch (error) { + handleError(error, 'generating lightweight test folder'); + } +} + +async function cleanTestFolder() { + console.log('Cleaning test folder...'); + + try { + if (fs.existsSync(tempTestFolder)) { + fs.removeSync(tempTestFolder); + console.log('Successfully cleaned test folder'); + } else { + console.log('Test folder does not exist'); + } + } catch (error) { + handleError(error, 'cleaning test folder'); + } +} + +// Main execution +async function main() { + const command = process.argv[2]; + + switch (command) { + case 'standard': + await generateStandardTestFolder(); + break; + case 'lightweight': + await generateLightweightTestFolder(); + break; + case 'clean': + await cleanTestFolder(); + break; + default: + console.log('Usage: node test.js [standard|lightweight|clean]'); + process.exit(1); + } +} + +setupMainExecution(main); + +export { generateStandardTestFolder, generateLightweightTestFolder, cleanTestFolder }; diff --git a/scripts/utils.mjs b/scripts/utils.mjs new file mode 100644 index 0000000000..49a2d1ad7a --- /dev/null +++ b/scripts/utils.mjs @@ -0,0 +1,102 @@ +#!/usr/bin/env node + +import https from 'https'; +import { createWriteStream } from 'fs'; +import { pipeline } from 'stream'; +import { promisify } from 'util'; +import { fileURLToPath } from 'url'; +import path from 'path'; +import fs from 'fs-extra'; +import * as tar from 'tar'; +import zlib from 'zlib'; + +const pipelineAsync = promisify(pipeline); + +/** + * Downloads a file from a URL to a destination path + * @param {string} url - The URL to download from + * @param {string} destPath - The destination path to save the file + * @returns {Promise} A promise that resolves when the download is complete + */ +async function downloadFile(url, destPath) { + return new Promise((resolve, reject) => { + const file = createWriteStream(destPath); + https.get(url, (response) => { + if (response.statusCode >= 400) { + reject(new Error(`${response.statusCode} returned from ${url}`)); + return; + } + pipelineAsync(response, file) + .then(() => resolve()) + .catch(reject); + }).on('error', reject); + }); +} + +/** + * Gets the directory name of the current script (ESM equivalent of __dirname) + * @returns {string} The directory path of the current script + */ +function getScriptDir() { + const filename = fileURLToPath(import.meta.url); + return path.dirname(filename); +} + +/** + * Extracts a tar.gz file to a destination directory + * @param {string} tarGzPath - Path to the tar.gz file + * @param {string} destDir - Destination directory for extraction + * @returns {Promise} A promise that resolves when extraction is complete + */ +async function extractTarGz(tarGzPath, destDir) { + return new Promise((resolve, reject) => { + fs.createReadStream(tarGzPath) + .pipe(zlib.createGunzip()) + .pipe(tar.extract({ cwd: destDir, strip: 0 })) + .on('end', resolve) + .on('error', reject); + }); +} + +/** + * Creates a path relative to the project root (parent of scripts directory) + * @param {...string} pathSegments - Path segments to join + * @returns {string} The constructed path + */ +function getProjectPath(...pathSegments) { + const scriptDir = getScriptDir(); + const projectRoot = path.join(scriptDir, '..'); + return path.join(projectRoot, ...pathSegments); +} + +/** + * Handles errors with consistent logging and exit behavior + * @param {Error} error - The error to handle + * @param {string} context - Context description for the error + * @param {boolean} shouldExit - Whether to exit the process (default: true) + */ +function handleError(error, context, shouldExit = true) { + console.error(`Error ${context}:`, error.message); + if (shouldExit) { + process.exit(1); + } +} + +/** + * Sets up the main execution pattern for scripts + * @param {Function} mainFunction - The main function to execute + */ +function setupMainExecution(mainFunction) { + if (import.meta.url === `file://${process.argv[1]}`) { + mainFunction().catch(console.error); + } +} + +export { + downloadFile, + getScriptDir, + extractTarGz, + getProjectPath, + handleError, + setupMainExecution +}; diff --git a/snippets/java.json b/snippets/server.json similarity index 58% rename from snippets/java.json rename to snippets/server.json index 2890ef175d..57e7c4f68d 100644 --- a/snippets/java.json +++ b/snippets/server.json @@ -1,38 +1,29 @@ { - "main": { - "prefix": "main", - "body": [ - "public static void main(String[] args) {", - "\t$0", - "}" - ], - "description": "Public static main method" - }, "sysout": { - "prefix": "sysout", + "prefix": ["sysout", "sout", "System.out.println()"], "body": [ "System.out.println($0);" ], "description": "Print to standard out" }, "syserr": { - "prefix": "syserr", + "prefix": ["syserr", "serr", "System.err.println()"], "body": [ "System.err.println($0);" ], "description": "Print to standard err" }, "fori": { - "prefix": "fori", + "prefix": ["fori"], "body": [ - "for (${1:int} ${2:i} = ${3:0}; $2 < ${4:max}; $2++) {", + "for (${1:int} ${2:i} = ${3:0}; ${2:i} < ${4:max}; ${2:i}++) {", "\t$0", "}" ], "description": "Indexed for loop" }, "foreach": { - "prefix": "foreach", + "prefix": ["foreach", "iter"], "body": [ "for (${1:type} ${2:var} : ${3:iterable}) {", "\t$0", @@ -40,17 +31,8 @@ ], "description": "Enhanced for loop" }, - "Public constructor": { - "prefix": "ctor", - "body": [ - "public ${1:${TM_FILENAME_BASE}}($2) {", - "\t${0:super();}", - "}" - ], - "description": "Public constructor" - }, "if": { - "prefix": "if", + "prefix": ["if"], "body": [ "if (${1:condition}) {", "\t$0", @@ -59,7 +41,7 @@ "description": "if statement" }, "ifelse": { - "prefix": "ifelse", + "prefix": ["ifelse"], "body": [ "if (${1:condition}) {", "\t$2", @@ -70,7 +52,7 @@ "description": "if/else statement" }, "ifnull": { - "prefix": "ifnull", + "prefix": ["ifnull"], "body": [ "if (${1:condition} == null) {", "\t$0", @@ -79,7 +61,7 @@ "description": "if statement checking for null" }, "ifnotnull": { - "prefix": "ifnotnull", + "prefix": ["ifnotnull"], "body": [ "if (${1:condition} != null) {", "\t$0", @@ -87,116 +69,99 @@ ], "description": "if statement checking for not null" }, - "trycatch": { - "prefix": "try_catch", + "While Statement": { + "prefix": ["while"], "body": [ - "try {", - "\t$1", - "} catch (${2:Exception} ${3:e}) {", - "\t$4//${0:TODO}: handle exception", + "while (${1:condition}) {", + "\t$0", "}" ], - "description": "try/catch block" - }, - "tryresources": { - "prefix": "try_resources", - "body": [ - "try ($1) {", - "\t$2", - "} catch (${3:Exception} ${4:e}) {", - "\t$5//${0:TODO}: handle exception", - "}" - ] + "description": "While Statement" }, - "private_method": { - "prefix": "private_method", + "Do-While Statement": { + "prefix": ["dowhile"], "body": [ - "private ${1:void} ${2:name}($3) {", + "do {", "\t$0", - "}" + "} while (${1:condition});" ], - "description": "private method" + "description": "Do-While Statement" }, - "Public method": { - "prefix": "public_method", + "Switch Statement": { + "prefix": "switch", "body": [ - "public ${1:void} ${2:name}(${3}) {", - "\t$0", + "switch (${1:key}) {", + "\tcase ${2:value}:", + "\t\t$0", + "\t\tbreak;", + "", + "\tdefault:", + "\t\tbreak;", "}" ], - "description": "public method" + "description": "Switch Statement" }, - "Private static method": { - "prefix": "private_static_method", + "trycatch": { + "prefix": "try_catch", "body": [ - "private static ${1:Type} ${2:name}(${3}) {", - "\t$0", + "try {", + "\t${TM_SELECTED_TEXT:$1}", + "} catch (${2:Exception} ${3:e}) {", + "\t$0// TODO: handle exception", "}" ], - "description": "private static method" + "description": "try/catch block" }, - "Public static method": { - "prefix": "public_static_method", + "tryresources": { + "prefix": "try_resources", "body": [ - "public static ${1:void} ${2:name}(${3}) {", - "\t$0", + "try ($1) {", + "\t$2", + "} catch (${3:Exception} ${4:e}) {", + "\t$0// TODO: handle exception", "}" - ], - "description": "public static method" + ] }, - "Protected Method": { - "prefix": "protected_method", + "main": { + "prefix": ["main", "psvm", "public static void main(String[] args)"], "body": [ - "protected ${1:void} ${2:name}(${3}) {", + "public static void main(String[] args) {", "\t$0", "}" ], - "description": "Protected method" + "description": "Public static main method" }, - "Switch Statement": { - "prefix": "switch", + "Constructor": { + "prefix": "ctor", "body": [ - "switch (${1:key}) {", - "\tcase ${2:value}:", - "\t\t$0", - "\t\tbreak;", - "", - "\tdefault:", - "\t\tbreak;", + "${1|public,protected,private|} ${2:${TM_FILENAME_BASE}}($3) {", + "\t${4:super();}$0", "}" ], - "description": "Switch Statement" + "description": "Constructor" }, - "While Statement": { - "prefix": "while", + "method": { + "prefix": "method", "body": [ - "while (${1:condition}) {", + "${1|public,protected,private|}${2| , static |}${3:void} ${4:name}($5) {", "\t$0", "}" ], - "description": "While Statement" - }, - "Do-While Statement": { - "prefix": "dowhile", - "body": [ - "do {", - "\t$0", - "} while (${1:condition});" - ], - "description": "Do-While Statement" + "description": "Method" }, "newObject": { "prefix": "new", "body": [ - "${0:Object} ${1:foo} = new ${0:Object}();" + "${1:Object} ${2:foo} = new ${1}($3);", + "$0" ], "description": "Create new Object" }, - "Private field": { - "prefix": "prf", + "Field": { + "prefix": "field", "body": [ - "private ${1:String} ${2:name};" + "${1|public,protected,private|} ${2:String} ${3:name};" ], - "description": "Private field" + "description": "Field" } } \ No newline at end of file diff --git a/src/TracingLanguageClient.ts b/src/TracingLanguageClient.ts new file mode 100644 index 0000000000..667b529778 --- /dev/null +++ b/src/TracingLanguageClient.ts @@ -0,0 +1,146 @@ +import { performance } from "perf_hooks"; +import { Event, EventEmitter } from "vscode"; +import { CancellationToken, LanguageClient, LanguageClientOptions, ProtocolRequestType, ProtocolRequestType0, RequestType, RequestType0, ServerOptions } from "vscode-languageclient/node"; +import { TraceEvent } from "./extension.api"; + +const requestStartEventEmitter = new EventEmitter(); +const requestEndEventEmitter = new EventEmitter(); +export const onWillRequestStart: Event = requestStartEventEmitter.event; +export const onDidRequestEnd: Event = requestEndEventEmitter.event; + +export class TracingLanguageClient extends LanguageClient { + private isStarted: boolean = false; + private isSyntaxServer: boolean = false; + + constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean) { + super(id, name, serverOptions, clientOptions, forceDebug); + this.isSyntaxServer = name?.includes("Syntax Server"); + } + + start(): Promise { + const isFirstTimeStart: boolean = !this.isStarted; + this.isStarted = true; + const startAt: number = performance.now(); + if (isFirstTimeStart) { + this.fireRequestStartTraceEvent("initialize"); + } + return super.start().then(value => { + if (isFirstTimeStart) { + this.fireSuccessTraceEvent("initialize", startAt, undefined); + } + return value; + }, reason => { + if (isFirstTimeStart) { + this.fireFailureTraceEvent("initialize", startAt, reason); + } + throw reason; + }); + } + + stop(timeout?: number): Promise { + this.isStarted = false; + return super.stop(timeout); + } + + sendRequest(type: ProtocolRequestType0, token?: CancellationToken): Promise; + sendRequest(type: ProtocolRequestType, params: P, token?: CancellationToken): Promise; + sendRequest(type: RequestType0, token?: CancellationToken): Promise; + sendRequest(type: RequestType, params: P, token?: CancellationToken): Promise; + sendRequest(method: string, token?: CancellationToken): Promise; + sendRequest(method: string, param: any, token?: CancellationToken): Promise; + sendRequest(method: any, ...args) { + const startAt: number = performance.now(); + const requestType: string = this.getRequestType(method, ...args); + let data: any = undefined; + if (args?.[0]?.context?.triggerKind !== undefined) { + data = { + triggerKind: args[0].context.triggerKind, + triggerCharacter: args[0].context.triggerCharacter, + }; + } + this.fireRequestStartTraceEvent(requestType); + return this.sendRequest0(method, ...args).then((value: any) => { + if (data && value?.itemDefaults?.data?.completionKinds) { + // Include the completionKinds from the completion response. + data.completionKinds = value.itemDefaults.data.completionKinds; + } + this.fireSuccessTraceEvent(requestType, startAt, this.getResultLength(value), data); + return value; + }, reason => { + this.fireFailureTraceEvent(requestType, startAt, reason, data); + throw reason; + }); + } + + private sendRequest0(method: any, ...args) { + if (!args || !args.length) { + return super.sendRequest(method); + } + + const first = args[0]; + const last = args[args.length - 1]; + if (CancellationToken.is(last)) { + if (first === last) { + return super.sendRequest(method, last); + } else { + return super.sendRequest(method, first, last); + } + } + + return super.sendRequest(method, first); + } + + private getRequestType(method: any, ...args): string { + let requestType: string; + if (typeof method === 'string' || method instanceof String) { + requestType = String(method); + } else { + requestType = method?.method; + } + + if (requestType === "workspace/executeCommand") { + if (args?.[0]?.command) { + requestType = `workspace/executeCommand/${args[0].command}`; + } + } + + return requestType; + } + + private fireRequestStartTraceEvent(type: string): void { + requestStartEventEmitter.fire({ + type, + fromSyntaxServer: !!this.isSyntaxServer, + }); + } + + private fireSuccessTraceEvent(type: string, startAt: number, resultLength: number | undefined, data?: any): void { + const duration: number = performance.now() - startAt; + requestEndEventEmitter.fire({ + type, + duration, + resultLength, + data, + fromSyntaxServer: !!this.isSyntaxServer, + }); + } + + private fireFailureTraceEvent(type: string, startAt: number, error: any, data?: any): void { + const duration: number = performance.now() - startAt; + requestEndEventEmitter.fire({ + type, + duration, + error, + data, + fromSyntaxServer: !!this.isSyntaxServer, + }); + } + + private getResultLength(value: any): number | undefined { + if (!value) { + return 0; + } + + return value?.length ?? value?.items?.length; + } +} diff --git a/src/apiManager.ts b/src/apiManager.ts new file mode 100644 index 0000000000..7f38791882 --- /dev/null +++ b/src/apiManager.ts @@ -0,0 +1,141 @@ +'use strict'; + +import { ExtensionAPI, ClasspathQueryOptions, ClasspathResult, extensionApiVersion, ClientStatus, SourceInvalidatedEvent } from "./extension.api"; +import { RequirementsData } from "./requirements"; +import { GetDocumentSymbolsCommand, getDocumentSymbolsProvider } from "./documentSymbols"; +import { GoToDefinitionCommand, goToDefinitionProvider } from "./goToDefinition"; +import { commands, Uri } from "vscode"; +import { Commands } from "./commands"; +import { Emitter } from "vscode-languageclient"; +import { ServerMode } from "./settings"; +import { registerHoverCommand } from "./hoverAction"; +import { onDidRequestEnd, onWillRequestStart } from "./TracingLanguageClient"; +import { getJavaConfiguration } from "./utils"; + +class ApiManager { + + private api: ExtensionAPI; + private onDidClasspathUpdateEmitter: Emitter = new Emitter(); + private onDidServerModeChangeEmitter: Emitter = new Emitter(); + private onDidProjectsImportEmitter: Emitter = new Emitter(); + private onDidProjectsDeleteEmitter: Emitter = new Emitter(); + private traceEventEmitter: Emitter = new Emitter(); + private sourceInvalidatedEventEmitter: Emitter = new Emitter(); + private serverReadyPromiseResolve: (result: boolean) => void; + private serverRunningPromiseResolve: (result: boolean) => void; + + public initialize(requirements: RequirementsData, serverMode: ServerMode): void { + // if it's manual import mode, set the server mode to lightweight, so that the + // project explorer won't spinning until import project is triggered. + if (getJavaConfiguration().get("import.projectSelection") === "manual") { + serverMode = ServerMode.lightWeight; + } + const getDocumentSymbols: GetDocumentSymbolsCommand = getDocumentSymbolsProvider(); + const goToDefinition: GoToDefinitionCommand = goToDefinitionProvider(); + + const getProjectSettings = async (uri: string, settingKeys: string[]) => { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_PROJECT_SETTINGS, uri, settingKeys); + }; + + const getClasspaths = async (uri: string, options: ClasspathQueryOptions) => { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_CLASSPATHS, uri, JSON.stringify(options)); + }; + + const isTestFile = async (uri: string) => { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.IS_TEST_FILE, uri); + }; + + const onDidClasspathUpdate = this.onDidClasspathUpdateEmitter.event; + const onDidServerModeChange = this.onDidServerModeChangeEmitter.event; + const onDidProjectsImport = this.onDidProjectsImportEmitter.event; + const onDidProjectsDelete = this.onDidProjectsDeleteEmitter.event; + const traceEvent = this.traceEventEmitter.event; + + const serverReadyPromise: Promise = new Promise((resolve) => { + this.serverReadyPromiseResolve = resolve; + }); + const serverReady = async () => { + return serverReadyPromise; + }; + + const serverRunningPromise: Promise = new Promise((resolve) => { + this.serverRunningPromiseResolve = resolve; + }); + const serverRunning = async () => { + return serverRunningPromise; + }; + + this.api = { + apiVersion: extensionApiVersion, + javaRequirement: requirements, + status: ClientStatus.starting, + registerHoverCommand: registerHoverCommand, + getDocumentSymbols, + goToDefinition, + getProjectSettings, + getClasspaths, + isTestFile, + onDidClasspathUpdate, + serverMode, + onDidServerModeChange, + onDidProjectsImport, + onDidProjectsDelete, + serverReady, + serverRunning, + onWillRequestStart, + onDidRequestEnd, + trackEvent: traceEvent, + onDidSourceInvalidate: this.sourceInvalidatedEventEmitter.event, + }; + } + + public getApiInstance(): ExtensionAPI { + if (!this.api) { + throw new Error("API instance is not initialized"); + } + + return this.api; + } + + public fireDidClasspathUpdate(event: Uri): void { + this.onDidClasspathUpdateEmitter.fire(event); + } + + public fireDidServerModeChange(event: ServerMode): void { + this.onDidServerModeChangeEmitter.fire(event); + } + + public fireDidProjectsImport(event: Uri[]): void { + this.onDidProjectsImportEmitter.fire(event); + } + + public fireDidProjectsDelete(event: Uri[]): void { + this.onDidProjectsDeleteEmitter.fire(event); + } + + public fireTraceEvent(event: any): void { + this.traceEventEmitter.fire(event); + } + + public fireSourceInvalidatedEvent(event: SourceInvalidatedEvent): void { + this.sourceInvalidatedEventEmitter.fire(event); + } + + public updateServerMode(mode: ServerMode): void { + this.api.serverMode = mode; + } + + public updateStatus(status: ClientStatus): void { + this.api.status = status; + } + + public resolveServerReadyPromise(): void { + this.serverReadyPromiseResolve(true); + } + + public resolveServerRunningPromise(): void { + this.serverRunningPromiseResolve?.(true); + } +} + +export const apiManager: ApiManager = new ApiManager(); diff --git a/src/buildFilesSelector.ts b/src/buildFilesSelector.ts new file mode 100644 index 0000000000..f595e02dbf --- /dev/null +++ b/src/buildFilesSelector.ts @@ -0,0 +1,302 @@ +import { ExtensionContext, MessageItem, QuickPickItem, QuickPickItemKind, Uri, WorkspaceFolder, window, workspace } from "vscode"; +import { convertToGlob, getExclusionGlob, getInclusionPatternsFromNegatedExclusion } from "./utils"; +import * as path from "path"; +import { IBuildTool, getContributedBuildTools } from "./plugin"; +import { ACTIVE_BUILD_TOOL_STATE } from "./settings"; + +export const PICKED_BUILD_FILES = "java.pickedBuildFiles"; +export const BUILD_TOOL_FOR_CONFLICTS = "java.buildToolForConflicts"; +export const IMPORT_METHOD = "java.importMethod"; +export class BuildFileSelector { + /** + * The build tools that are contributed/supported by extensions. + */ + private buildTools: IBuildTool[] = []; + /** + * The extension context. + */ + private context: ExtensionContext; + /** + * Glob pattern that needs to be excluded from the search. + */ + private exclusionGlobPattern: string; + /** + * Glob pattern to search build files. + */ + private searchPattern: string; + /** + * Glob pattern for build files that are explicitly + * included from the setting: "java.import.exclusions" (negated exclusion). + */ + private negatedExclusionSearchPattern: string | undefined; + + /** + * string array for the imported folder paths. + */ + private importedFolderPaths: string[]; + + /** + * Mark if the selector is used during initialization. + */ + private isInitialization: boolean; + + /** + * The build files that are found in the workspace. + */ + private foundBuildFiles: Uri[] = []; + + /** + * @param context The extension context. + * @param isInitialization Mark if the selector is used during initialization. + */ + constructor(context: ExtensionContext, importedFolderUris: string[], isInitialization: boolean = true) { + this.context = context; + this.importedFolderPaths = importedFolderUris.map(uri => Uri.parse(uri).fsPath); + this.isInitialization = isInitialization; + const buildTool = this.context.workspaceState.get(BUILD_TOOL_FOR_CONFLICTS); + if (!buildTool) { + this.buildTools = getContributedBuildTools(); + } else { + this.buildTools.push(buildTool); + } + // TODO: should we introduce the exclusion globs into the contribution point? + this.exclusionGlobPattern = getExclusionGlob(["**/target/**", "**/bin/**", "**/build/**"]); + this.searchPattern = `**/{${this.buildTools.map(buildTool => buildTool.buildFileNames.join(","))}}`; + const inclusionFolderPatterns: string[] = getInclusionPatternsFromNegatedExclusion(); + if (inclusionFolderPatterns.length > 0) { + const buildFileNames: string[] = []; + this.buildTools.forEach(buildTool => buildFileNames.push(...buildTool.buildFileNames)); + this.negatedExclusionSearchPattern = convertToGlob(buildFileNames, inclusionFolderPatterns); + } + } + + /** + * @returns `true` if there are build files in the workspace, `false` otherwise. + */ + public async hasBuildFiles(): Promise { + if (this.buildTools.length === 0) { + return false; + } + + let uris: Uri[]; + if (this.negatedExclusionSearchPattern) { + uris = await workspace.findFiles(this.negatedExclusionSearchPattern, null /* force not use default exclusion */, 1); + if (uris.length > 0) { + return true; + } + } + uris = await workspace.findFiles(this.searchPattern, this.exclusionGlobPattern, 1); + if (uris.length > 0) { + return true; + } + return false; + } + + /** + * Get the uri strings for the build files that the user selected. + * @returns An array of uri string for the build files that the user selected. + * An empty array means user canceled the selection. Or `undefined` on cancellation. + */ + public async selectBuildFiles(): Promise { + const choices = await this.chooseBuildFilePickers(); + if (choices === undefined) { + return undefined; + } + const pickedUris = await this.eliminateBuildToolConflict(choices); + this.context.workspaceState.update(PICKED_BUILD_FILES, pickedUris); + return pickedUris; + } + + private async chooseBuildFilePickers(): Promise { + return window.showQuickPick(this.getBuildFilePickers(), { + placeHolder: "Note: Currently only Maven projects can be partially imported.", + title: "Select build files to import", + ignoreFocusOut: true, + canPickMany: true, + matchOnDescription: true, + matchOnDetail: true, + }); + } + + /** + * Get pickers for all build files in the workspace. + */ + private async getBuildFilePickers(): Promise { + const addedFolders: Map = new Map(); + const uris: Uri[] = await workspace.findFiles(this.searchPattern, this.exclusionGlobPattern); + if (this.negatedExclusionSearchPattern) { + uris.push(...await workspace.findFiles(this.negatedExclusionSearchPattern, null /* force not use default exclusion */)); + } + this.foundBuildFiles.push(...uris); + + for (const uri of uris) { + const containingFolder = path.dirname(uri.fsPath); + const buildTool = this.buildTools.find(buildTool => buildTool.buildFileNames.includes(path.basename(uri.fsPath))); + if (!buildTool) { + continue; + } + if (addedFolders.has(containingFolder)) { + const picker = addedFolders.get(containingFolder); + if (!picker.buildToolAndUri.has(buildTool)) { + picker.buildToolAndUri.set(buildTool, uri); + } + } else { + addedFolders.set(containingFolder, { + label: path.basename(containingFolder), + detail: "", // update later + description: "", // update later + buildToolAndUri: new Map([[buildTool, uri]]), + }); + } + } + const pickers: IBuildFilePicker[] = Array.from(addedFolders.values()); + await this.setPickerUiComponents(pickers); + return this.addSeparator(pickers); + } + + private isImported(uri: Uri): boolean { + return this.importedFolderPaths.some(importedFolderPath => + path.relative(importedFolderPath, path.dirname(uri.fsPath)) === ""); + } + + /** + * Update the picker's UI components, including detail, description and picked flag. + */ + private async setPickerUiComponents(pickers: IBuildFilePicker[]) { + for (const picker of pickers) { + const buildTools = Array.from(picker.buildToolAndUri.keys()) + .sort((a, b) => a.displayName.localeCompare(b.displayName)); + + const details = buildTools.map(buildTool => workspace.asRelativePath(picker.buildToolAndUri.get(buildTool))); + const descriptions = buildTools.map(buildTool => buildTool.displayName); + + picker.detail = details.join(', '); + picker.description = descriptions.join(', '); + picker.picked = this.isInitialization || this.isImported(picker.buildToolAndUri.values().next().value); + } + } + + /** + * Add a separator pickers between pickers that belong to different workspace folders. + */ + private addSeparator(pickers: IBuildFilePicker[]): IBuildFilePicker[] { + // group pickers by their containing workspace folder + const workspaceFolders = new Map(); + for (const picker of pickers) { + const folder = workspace.getWorkspaceFolder(picker.buildToolAndUri.values().next().value); + if (folder) { + workspaceFolders.set(folder, [...(workspaceFolders.get(folder) || []), picker]); + } + } + + const newPickers: IBuildFilePicker[] = []; + const folderArray = Array.from(workspaceFolders.keys()); + folderArray.sort((a, b) => a.name.localeCompare(b.name)); + for (const folder of folderArray) { + const pickersInFolder = workspaceFolders.get(folder); + newPickers.push({ + label: folder.name, + kind: QuickPickItemKind.Separator, + buildToolAndUri: null + }); + newPickers.push(...this.sortPickers(pickersInFolder)); + } + return newPickers; + } + + private sortPickers(pickers: IBuildFilePicker[]): IBuildFilePicker[] { + return pickers.sort((a, b) => { + const pathA = path.dirname(a.buildToolAndUri.values().next().value.fsPath); + const pathB = path.dirname(b.buildToolAndUri.values().next().value.fsPath); + return pathA.localeCompare(pathB); + }); + } + + /** + * Ask user to choose a build tool when there are multiple build tools in the same folder. + */ + private async eliminateBuildToolConflict(choices?: IBuildFilePicker[]): Promise { + // group uris by build tool + const conflictBuildToolAndUris = new Map(); + const result: string[] = []; + for (const picker of choices) { + if (picker.buildToolAndUri.size > 1) { + picker.buildToolAndUri.forEach((uri, buildTool) => { + conflictBuildToolAndUris.set(buildTool, [...(conflictBuildToolAndUris.get(buildTool) || []), uri]); + }); + } else { + result.push(picker.buildToolAndUri.values().next().value.toString()); + } + } + + if (conflictBuildToolAndUris.size > 0) { + const buildTool = this.context.workspaceState.get(BUILD_TOOL_FOR_CONFLICTS); + if (buildTool) { + result.push(...this.filterByCachedBuildTool(conflictBuildToolAndUris, buildTool)); + } else { + result.push(...await this.askToResolveConflicts(conflictBuildToolAndUris)); + } + } + return result; + } + + private filterByCachedBuildTool(conflictBuildToolAndUris: Map, buildTool: IBuildTool): string[] { + const result: string[] = []; + if (conflictBuildToolAndUris.has(buildTool)) { + result.push(...conflictBuildToolAndUris.get(buildTool)!.map(uri => uri.toString())); + } + return result; + } + + private async askToResolveConflicts(conflictBuildToolAndUris: Map): Promise { + const result: string[] = []; + const conflictItems: IConflictItem[] = []; + for (const buildTool of conflictBuildToolAndUris.keys()) { + conflictItems.push({ + title: buildTool.displayName, + buildTool: buildTool, + uris: conflictBuildToolAndUris.get(buildTool), + }); + } + conflictItems.sort((a, b) => a.title.localeCompare(b.title)); + conflictItems.push({ + title: "Skip", + uris: [], + isCloseAffordance: true, + }); + + const choice = await window.showInformationMessage( + "Which build tool would you like to use for the workspace?", + { + modal: true, + }, + ...conflictItems + ); + + if (choice?.title !== "Skip") { + result.push(...choice.uris.map(uri => uri.toString())); + this.context.workspaceState.update(BUILD_TOOL_FOR_CONFLICTS, choice.buildTool); + } + return result; + } + + public getAllFoundBuildFiles(): Uri[] { + return this.foundBuildFiles; + } +} + +interface IConflictItem extends MessageItem { + uris: Uri[]; + buildTool?: IBuildTool; +} + +interface IBuildFilePicker extends QuickPickItem { + buildToolAndUri: Map; +} + +export function cleanupWorkspaceState(context: ExtensionContext) { + context.workspaceState.update(PICKED_BUILD_FILES, undefined); + context.workspaceState.update(BUILD_TOOL_FOR_CONFLICTS, undefined); + context.workspaceState.update(IMPORT_METHOD, undefined); + context.workspaceState.update(ACTIVE_BUILD_TOOL_STATE, undefined); +} diff --git a/src/buildpath.ts b/src/buildpath.ts index 3463b04deb..a2b9d832ca 100644 --- a/src/buildpath.ts +++ b/src/buildpath.ts @@ -1,7 +1,8 @@ 'use strict'; -import { window, commands, ExtensionContext, Uri } from 'vscode'; +import { window, commands, ExtensionContext, Uri, ConfigurationTarget } from 'vscode'; import { Commands } from './commands'; +import { getJavaConfiguration } from './utils'; interface Result { status: boolean; @@ -15,30 +16,36 @@ interface SourcePath { projectType: string; } -interface ListCommandResult extends Result { +export interface ListCommandResult extends Result { data?: SourcePath[]; } export function registerCommands(context: ExtensionContext) { - context.subscriptions.push(commands.registerCommand(Commands.ADD_TO_SOURCEPATH, async (uri: Uri) => { + context.subscriptions.push(commands.registerCommand(Commands.ADD_TO_SOURCEPATH_CMD, async (uri: Uri) => { const result = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.ADD_TO_SOURCEPATH, uri.toString()); if (result.status) { + if (result.sourcePaths) { + getJavaConfiguration().update('project.sourcePaths', result.sourcePaths, ConfigurationTarget.Workspace); + } window.showInformationMessage(result.message ? result.message : 'Successfully added the folder to the source path.'); } else { window.showErrorMessage(result.message); } })); - context.subscriptions.push(commands.registerCommand(Commands.REMOVE_FROM_SOURCEPATH, async (uri: Uri) => { + context.subscriptions.push(commands.registerCommand(Commands.REMOVE_FROM_SOURCEPATH_CMD, async (uri: Uri) => { const result = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.REMOVE_FROM_SOURCEPATH, uri.toString()); if (result.status) { + if (result.sourcePaths) { + getJavaConfiguration().update('project.sourcePaths', result.sourcePaths, ConfigurationTarget.Workspace); + } window.showInformationMessage(result.message ? result.message : 'Successfully removed the folder from the source path.'); } else { window.showErrorMessage(result.message); } })); - context.subscriptions.push(commands.registerCommand(Commands.LIST_SOURCEPATHS, async() => { + context.subscriptions.push(commands.registerCommand(Commands.LIST_SOURCEPATHS_CMD, async() => { const result: ListCommandResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.LIST_SOURCEPATHS); if (result.status) { if (!result.data || !result.data.length) { diff --git a/src/clientCodeActionProvider.ts b/src/clientCodeActionProvider.ts new file mode 100644 index 0000000000..5095f277a9 --- /dev/null +++ b/src/clientCodeActionProvider.ts @@ -0,0 +1,32 @@ +import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, Command, ExtensionContext, ProviderResult, Range, Selection, TextDocument, commands } from "vscode"; +import { apiManager } from "./apiManager"; + +const configureStaticImportsCommand = "java.action.configureFavoriteStaticMembers"; +const UNDEFINED_METHOD = "67108964"; +export class ClientCodeActionProvider implements CodeActionProvider { + constructor(readonly context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand(configureStaticImportsCommand, async () => { + commands.executeCommand("workbench.action.openSettings", "java.completion.favoriteStaticMembers"); + apiManager.fireTraceEvent({ + name: "java.ls.command", + properties: { + command: configureStaticImportsCommand, + }, + }); + })); + } + + provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(CodeAction | Command)[]> { + const codeActions = []; + if (context.diagnostics?.some(diagnostic => diagnostic.code === UNDEFINED_METHOD) + || document.lineAt(range.start.line)?.text?.startsWith("import ")) { + const action = new CodeAction("Configure static import...", CodeActionKind.QuickFix); + action.command = { + title: "Configure static import...", + command: configureStaticImportsCommand, + }; + codeActions.push(action); + } + return codeActions; + } +} diff --git a/src/clientErrorHandler.ts b/src/clientErrorHandler.ts new file mode 100644 index 0000000000..5caf1e797c --- /dev/null +++ b/src/clientErrorHandler.ts @@ -0,0 +1,79 @@ +import { window, commands } from "vscode"; +import { serverStatusBarProvider } from './serverStatusBarProvider'; +import { ErrorHandler, Message, ErrorAction, CloseAction, ErrorHandlerResult, CloseHandlerResult } from "vscode-languageclient"; +import { Commands } from "./commands"; +import { logger } from "./log"; +import { apiManager } from "./apiManager"; + +const CLIENT_ERROR = "java.client.error"; +export class ClientErrorHandler implements ErrorHandler { + private restarts: number[]; + + constructor(private name: string) { + this.restarts = []; + } + + public error(_error: Error, _message: Message, count: number): ErrorHandlerResult { + if (count && count <= 3) { + logger.error(`${this.name} server encountered error: ${_message}, ${_error && _error.toString()}`); + return { + action: ErrorAction.Continue, + handled: true + }; + } + + const errorMessage = `${this.name} server encountered error and will shut down: ${_message}, ${_error && _error.toString()}`; + apiManager.fireTraceEvent({ + name: CLIENT_ERROR, + properties: { + message: errorMessage, + }, + }); + logger.error(errorMessage); + return { + action: ErrorAction.Shutdown, + handled: true + }; + } + + public closed(): CloseHandlerResult { + this.restarts.push(Date.now()); + if (this.restarts.length < 5) { + logger.error(`The ${this.name} server crashed and will restart.`); + return { + action: CloseAction.Restart, + handled: true + }; + } else { + const diff = this.restarts[this.restarts.length - 1] - this.restarts[0]; + if (diff <= 3 * 60 * 1000) { + const message = `The ${this.name} server crashed 5 times in the last 3 minutes. The server will not be restarted.`; + apiManager.fireTraceEvent({ + name: CLIENT_ERROR, + properties: { + message, + }, + }); + logger.error(message); + serverStatusBarProvider.setError(); + const action = "Show logs"; + window.showErrorMessage(message, action).then(selection => { + if (selection === action) { + commands.executeCommand(Commands.OPEN_LOGS); + } + }); + return { + action: CloseAction.DoNotRestart, + handled: true + }; + } + + logger.error(`The ${this.name} server crashed and will restart.`); + this.restarts.shift(); + return { + action: CloseAction.Restart, + handled: true + }; + } + } +} diff --git a/src/codeActionProvider.ts b/src/codeActionProvider.ts new file mode 100644 index 0000000000..e3ac0283ca --- /dev/null +++ b/src/codeActionProvider.ts @@ -0,0 +1,45 @@ +import { CodeActionProvider, CodeActionProviderMetadata, CodeActionKind } from "vscode"; +import { Commands } from "./commands"; + +/** + * Mapping the refactoring kind to its section id in the document + */ +export const javaRefactorKinds: Map = new Map([ + [CodeActionKind.Refactor, 'java-refactoring'], + [CodeActionKind.RefactorExtract, 'extract-to-constant'], + [CodeActionKind.RefactorExtract.append('function'), 'extract-to-method'], + [CodeActionKind.RefactorExtract.append('constant'), 'extract-to-constant'], + [CodeActionKind.RefactorExtract.append('variable'), 'extract-to-local-variable'], + [CodeActionKind.RefactorExtract.append('field'), 'extract-to-field'], + [CodeActionKind.RefactorInline, 'inline-constant'], + [CodeActionKind.Refactor.append('move'), 'move'], + [CodeActionKind.Refactor.append('assign'), 'assign-to-variable'], + [CodeActionKind.Refactor.append('introduce').append('parameter'), 'introduce-parameter'] +]); + +export class RefactorDocumentProvider implements CodeActionProvider { + provideCodeActions() { + return [{ + // The aim of this is to expose the source actions in the light bulb. + title: "Source Actions...", + command: "editor.action.sourceAction", + kind: CodeActionKind.Empty, + }]; + } + + public static readonly metadata: CodeActionProviderMetadata = { + providedCodeActionKinds: [ + CodeActionKind.Refactor + ], + documentation: Array.from(javaRefactorKinds.keys()).map(kind => { + return { + kind, + command: { + command: Commands.LEARN_MORE_ABOUT_REFACTORING, + title: 'Learn more about Java refactorings...', + arguments: [kind] + } + }; + }), + }; +} diff --git a/src/commands.ts b/src/commands.ts index a2ab5f6f09..ab5aa05433 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -30,7 +30,17 @@ export namespace Commands { export const SHOW_REFERENCES = 'editor.action.showReferences'; /** - * Update project configuration + * Go to editor location + */ + export const GOTO_LOCATION = 'editor.action.goToLocations'; + + /** + * Render markdown string to html string + */ + export const MARKDOWN_API_RENDER = 'markdown.api.render'; + + /** + * Reload project */ export const CONFIGURATION_UPDATE = 'java.projectConfiguration.update'; @@ -54,6 +64,11 @@ export namespace Commands { */ export const PROJECT_CONFIGURATION_STATUS = 'java.projectConfiguration.status'; + /** + * Set null analysis mode + */ + export const NULL_ANALYSIS_SET_MODE = 'java.compile.nullAnalysis.setMode'; + /** * Apply Workspace Edit */ @@ -64,27 +79,60 @@ export namespace Commands { */ export const EXECUTE_WORKSPACE_COMMAND = 'java.execute.workspaceCommand'; - /** - * Execute Workspace build (compilation) - */ + /** + * Execute Workspace build (compilation) + */ export const COMPILE_WORKSPACE = 'java.workspace.compile'; + /** + * Execute build for projects + */ + export const BUILD_PROJECT = 'java.project.build'; + /** * Open Java Language Server Log file */ export const OPEN_SERVER_LOG = 'java.open.serverLog'; + /** + * Open Java Language Service Output Log file + */ + export const OPEN_SERVER_STDOUT_LOG = 'java.open.serverStdoutLog'; + + /** + * Open Java Language Server Error Log file + */ + export const OPEN_SERVER_STDERR_LOG = 'java.open.serverStderrLog'; + + /** + * Open Java client Log file + */ + export const OPEN_CLIENT_LOG = 'java.open.clientLog'; + + /** + * Open Java log files side by side + */ + export const OPEN_LOGS = 'java.open.logs'; + /** * Open Java formatter settings */ export const OPEN_FORMATTER = 'java.open.formatter.settings'; + + /** + * Open a file given the URI + */ + export const OPEN_FILE = 'java.open.file'; + /** * Clean the Java language server workspace */ export const CLEAN_WORKSPACE = 'java.clean.workspace'; /** * Update the source attachment for the selected class file + * client-side & server-side commands */ + export const UPDATE_SOURCE_ATTACHMENT_CMD = 'java.project.updateSourceAttachment.command'; export const UPDATE_SOURCE_ATTACHMENT = 'java.project.updateSourceAttachment'; /** * Resolve the source attachment information for the selected class file @@ -92,16 +140,29 @@ export namespace Commands { export const RESOLVE_SOURCE_ATTACHMENT = 'java.project.resolveSourceAttachment'; /** * Mark the folder as the source root of the closest project. + * client-side & server-side commands */ + export const ADD_TO_SOURCEPATH_CMD = 'java.project.addToSourcePath.command'; export const ADD_TO_SOURCEPATH = 'java.project.addToSourcePath'; /** * Unmark the folder as the source root of the project. + * client-side & server-side commands */ + export const REMOVE_FROM_SOURCEPATH_CMD = 'java.project.removeFromSourcePath.command'; export const REMOVE_FROM_SOURCEPATH = 'java.project.removeFromSourcePath'; /** * List all recognized source roots in the workspace. + * client-side & server-side commands */ + export const LIST_SOURCEPATHS_CMD = 'java.project.listSourcePaths.command'; export const LIST_SOURCEPATHS = 'java.project.listSourcePaths'; + /** + * Import new projects + * client-side & server-side commands + */ + export const IMPORT_PROJECTS_CMD = 'java.project.import.command'; + export const IMPORT_PROJECTS = 'java.project.import'; + export const CHANGE_IMPORTED_PROJECTS = 'java.project.changeImportedProjects'; /** * Override or implements the methods from the supertypes. */ @@ -110,7 +171,7 @@ export namespace Commands { * Generate hashCode() and equals(). */ export const HASHCODE_EQUALS_PROMPT = 'java.action.hashCodeEqualsPrompt'; - /** + /** * Open settings.json */ export const OPEN_JSON_SETTINGS = 'workbench.action.openSettingsJson'; @@ -118,6 +179,23 @@ export namespace Commands { * Organize imports. */ export const ORGANIZE_IMPORTS = "java.action.organizeImports"; + /** + * Organize imports silently. + */ + export const ORGANIZE_IMPORTS_SILENTLY = "java.edit.organizeImports"; + export const MANUAL_CLEANUP = "java.action.doCleanup"; + /** + * Handle a paste event. + */ + export const HANDLE_PASTE_EVENT = "java.edit.handlePasteEvent"; + /** + * Custom paste action (triggers auto-import) + */ + export const CLIPBOARD_ONPASTE = 'java.action.clipboardPasteAction'; + /** + * Custom paste action in files explorer + */ + export const FILESEXPLORER_ONPASTE = 'java.action.filesExplorerPasteAction'; /** * Choose type to import. */ @@ -146,4 +224,180 @@ export namespace Commands { * Rename Command. */ export const RENAME_COMMAND = 'java.action.rename'; -} \ No newline at end of file + /** + * Navigate To Super Method Command. + */ + export const NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND = 'java.action.navigateToSuperImplementation'; + /** + * Open Type Hierarchy of given Selection. + */ + export const SHOW_TYPE_HIERARCHY = 'java.action.showTypeHierarchy'; + /** + * Show SuperType Hierarchy of given Selection. + */ + export const SHOW_SUPERTYPE_HIERARCHY = 'java.action.showSupertypeHierarchy'; + /** + * Show SubType Hierarchy of given Selection. + */ + export const SHOW_SUBTYPE_HIERARCHY = 'java.action.showSubtypeHierarchy'; + /** + * Show Type Hierarchy of given Selection. + */ + export const SHOW_CLASS_HIERARCHY = 'java.action.showClassHierarchy'; + /** + * Change the base type of Type Hierarchy. + */ + export const CHANGE_BASE_TYPE = 'java.action.changeBaseType'; + /** + * Open the given TypeHierarchy Item. + */ + export const OPEN_TYPE_HIERARCHY = 'java.navigate.openTypeHierarchy'; + /** + * Resolve the given TypeHierarchy Item. + */ + export const RESOLVE_TYPE_HIERARCHY = 'java.navigate.resolveTypeHierarchy'; + /** + * Show server task status + */ + export const SHOW_SERVER_TASK_STATUS = 'java.show.server.task.status'; + /** + * Get the project settings + */ + export const GET_PROJECT_SETTINGS = 'java.project.getSettings'; + /** + * Get the classpaths and modulepaths + */ + export const GET_CLASSPATHS = 'java.project.getClasspaths'; + /** + * Check the input file is a test file or not + */ + export const IS_TEST_FILE = 'java.project.isTestFile'; + /** + * Get all java projects root path in URI format + */ + export const GET_ALL_JAVA_PROJECTS = 'java.project.getAll'; + /** + * Command to switch between standard mode and lightweight mode. + */ + export const SWITCH_SERVER_MODE = 'java.server.mode.switch'; + /** + * Command to restart the language server. + */ + export const RESTART_LANGUAGE_SERVER = 'java.server.restart'; + + export const LEARN_MORE_ABOUT_REFACTORING = '_java.learnMoreAboutRefactorings'; + + export const LEARN_MORE_ABOUT_CLEAN_UPS = '_java.learnMoreAboutCleanUps'; + + export const TEMPLATE_VARIABLES = '_java.templateVariables'; + + export const NOT_COVERED_EXECUTION = '_java.notCoveredExecution'; + + export const METADATA_FILES_GENERATION = '_java.metadataFilesGeneration'; + + export const RUNTIME_VALIDATION_OPEN = 'java.runtimeValidation.open'; + + export const RESOLVE_WORKSPACE_SYMBOL = 'java.project.resolveWorkspaceSymbol'; + + export const GET_WORKSPACE_PATH = '_java.workspace.path'; + + /** + * Update the gradle wrapper version for the given project + * client-side & server-side commands + */ + export const UPGRADE_GRADLE_WRAPPER_CMD = 'java.project.upgradeGradle.command'; + export const UPGRADE_GRADLE_WRAPPER = 'java.project.upgradeGradle'; + + export const LOMBOK_CONFIGURE = "java.lombokConfigure"; + + /** + * The JDT.LS command to create module-info.java + */ + export const CREATE_MODULE_INFO = "java.project.createModuleInfo"; + + /** + * The VS Code command to create module-info.java + */ + export const CREATE_MODULE_INFO_COMMAND = "java.project.createModuleInfo.command"; + + /** + * The JDT.LS command to reload the bundle list (java extension contributions). + */ + export const REFRESH_BUNDLES = "java.reloadBundles"; + + /** + * The VS Code command to reload the bundle list. + * JDT.LS will call this command before set the server to ready state. + */ + export const REFRESH_BUNDLES_COMMAND = "_java.reloadBundles.command"; + + /** + * Clean everything in the shared index directory. + */ + export const CLEAN_SHARED_INDEXES = "java.clean.sharedIndexes"; + + /** + * Get the uri of the decompiled class file. + */ + export const GET_DECOMPILED_SOURCE = "java.decompile"; + + /** + * Smart semicolon detection. + */ + export const SMARTSEMICOLON_DETECTION = "java.edit.smartSemicolonDetection"; + + /** + * Determine if pasted text is a java file and resolve packages + */ + export const RESOLVE_PASTED_TEXT = "java.project.resolveText"; + + /** + * The command when clicking the server status bar item. + */ + export const OPEN_STATUS_SHORTCUT = "_java.openShortcuts"; + + /** + * Change java search scope. + */ + export const CHANGE_JAVA_SEARCH_SCOPE = "java.change.searchScope"; + + /** + * Show Extended Outline for current document. + */ + export const SHOW_EXTEND_OUTLINE = 'java.action.showExtendedOutline'; + + /** + * Get the content of the currently visible editor. + */ + export const GET_VISIBLE_EDITOR_CONTENT = '_java.getVisibleEditorContent'; + + /** + * Get troubleshooting info command in jdt.ls + */ + export const GET_TROUBLESHOOTING_INFO = 'java.getTroubleshootingInfo'; + + /** + * Open Java Dashboard + */ + export const OPEN_JAVA_DASHBOARD = 'java.dashboard.open'; + + /** + * Add Java Runtime + */ + export const ADD_JAVA_RUNTIME = 'java.runtimes.add'; + + /** + * Copy fully qualified name. + */ + export const COPY_FULLY_QUALIFIED_NAME = 'java.action.copyFullyQualifiedName'; + export const GET_FULLY_QUALIFIED_NAME = 'java.getFullyQualifiedName'; +} + +/** + * Command titles used to render in the UI + */ +export namespace CommandTitle { + export const OPEN_JAVA_SETTINGS = "$(settings-gear) Open Java Settings"; + export const OPEN_LOGS = "$(output) Open Logs"; + export const CLEAN_WORKSPACE_CACHE = "$(trash) Clean Workspace Cache..."; +} diff --git a/src/dashboard/dashboard.ts b/src/dashboard/dashboard.ts new file mode 100644 index 0000000000..772b06e945 --- /dev/null +++ b/src/dashboard/dashboard.ts @@ -0,0 +1,185 @@ +import * as vscode from 'vscode'; +import { apiManager } from '../apiManager'; +import { Commands } from '../commands'; +import { getComputedJavaConfig, getWorkspacePath } from '../extension'; +import { isLombokSupportEnabled, Lombok } from '../lombokSupport'; +import { DashboardState, DiagnosticInfo, JVM, UpdateMessage } from '../webviewProtocol/toDashboard'; +import { getNonce, getUri } from '../webviewUtils'; +import { Uri } from 'vscode'; +import * as path from 'path'; + +const currentState: DashboardState = { +}; + + +class DashboardPanel { + private disposables: vscode.Disposable[] = []; + + constructor(private webView: vscode.Webview, private readonly context: vscode.ExtensionContext) { + this.init(); + } + + private init(): void { + this.disposables.push(vscode.workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('java.jdt.ls.lombokSupport.enabled')) { + currentState.lombokEnabled = isLombokSupportEnabled(); + const msg: UpdateMessage = { + type: "update", + lombokEnabled: isLombokSupportEnabled() + }; + this.postMessage(msg); + } + if (e.affectsConfiguration('java')) { + setTimeout(() => this.refreshLSInfo(), 1000); // wait for LS to pick up the config change + } + })); + this.setWebviewMessageListener(); + this.webView.html = this.getWebviewContent(); + this.disposables.push(vscode.commands.registerCommand('java.dashboard.refresh', async () => { + this.refreshLSInfo(); + })); + + this.disposables.push(vscode.commands.registerCommand('java.dashboard.revealFileInOS', async (arg: { path: string }) => { + await vscode.commands.executeCommand('revealFileInOS', vscode.Uri.file(arg.path)); + })); + + this.disposables.push(vscode.commands.registerCommand('java.dashboard.dumpState', async () => { + const doc = await vscode.workspace.openTextDocument({ + language: 'json', + content: JSON.stringify(currentState, null, 2) + }); + vscode.window.showTextDocument(doc); + })); + } + + private postMessage(message: UpdateMessage) { + if (this.webView) { + this.webView.postMessage(message); + } + } + + private setWebviewMessageListener() { + this.webView.onDidReceiveMessage( + async (message: any) => { + const command = message.command; + switch (command) { + case "webviewReady": { + await apiManager.getApiInstance().serverReady(); + currentState.lombokEnabled = isLombokSupportEnabled(); + currentState.activeLombokPath = Lombok.getActiveLombokPath(); + currentState.workspacePath = getWorkspacePath(); + const message: UpdateMessage = { + type: "update", + lombokEnabled: isLombokSupportEnabled(), + activeLombokPath: Lombok.getActiveLombokPath(), + workspacePath: getWorkspacePath(), + }; + await this.postMessage(message); + this.getJvms().then(jvms => { + currentState.jvms = jvms; + const msg: UpdateMessage = { + type: "update", + jvms: jvms + }; + + this.postMessage(msg); + }); + + this.refreshLSInfo(); + break; + } + } + } + ); + } + + public dispose(): void { + this.webView = undefined; + for (const disposable of this.disposables) { + disposable.dispose(); + } + } + + private async getJvms(): Promise { + const config = await getComputedJavaConfig(); + const jres: JVM[] = config.configuration.runtimes.map(jre => ({ + name: jre.name, + version: jre.version, + path: jre.path, + })); + return jres; + + } + + private getWebviewContent(): string { + const scriptUri = getUri(this.webView, this.context.extensionUri, "dist", "dashboard.js"); + const styleUri = getUri(this.webView, this.context.extensionUri, "dist", "dashboard.css"); + + return /* html*/ ` + + + + + + + + Dashboard + + + +
+ + + + `; + } + + private async refreshLSInfo(): Promise { + if (!this.webView) { + return; + } + try { + vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_TROUBLESHOOTING_INFO).then(info => { + currentState.diagnosticInfo = info; + const msg: UpdateMessage = { + type: "update", + diagnosticInfo: info + }; + this.postMessage(msg); + }); + } catch (e) { + console.error('Failed to get diagnostic info', e); + } + } +} + +export namespace Dashboard { + export function initialize(context: vscode.ExtensionContext): void { + console.log('registering dashboard webview provider'); + let dashboardPanel: DashboardPanel; + let webviewPanel: vscode.WebviewPanel; + + context.subscriptions.push(vscode.commands.registerCommand(Commands.OPEN_JAVA_DASHBOARD, async () => { + if (!dashboardPanel) { + webviewPanel = vscode.window.createWebviewPanel('java.dashboard', 'Java Dashboard', vscode.ViewColumn.Active, { + enableScripts: true, + enableCommandUris: true, + retainContextWhenHidden: true, + localResourceRoots: [context.extensionUri], + }); + webviewPanel.iconPath = Uri.file(path.join(context.extensionPath, 'icons', 'icon128.png')); + dashboardPanel = new DashboardPanel(webviewPanel.webview, context); + + webviewPanel.onDidDispose(() => { + dashboardPanel.dispose(); + dashboardPanel = undefined; + webviewPanel = undefined; + vscode.commands.executeCommand('setContext', 'java:dashboard', false); + }, undefined, context.subscriptions); + } else { + webviewPanel.reveal(); + } + })); + console.log('registered dashboard webview provider'); + } +} diff --git a/src/diagnostic.ts b/src/diagnostic.ts new file mode 100644 index 0000000000..e68d2b05a3 --- /dev/null +++ b/src/diagnostic.ts @@ -0,0 +1,19 @@ +import { ExtensionContext, window } from "vscode"; +import { ValidateDocumentNotification } from "./protocol"; +import { LanguageClient } from "vscode-languageclient/node"; +import { validateAllOpenBuffersOnChanges } from "./settings"; + +export function registerDocumentValidationListener(context: ExtensionContext, languageClient: LanguageClient) { + context.subscriptions.push(window.onDidChangeActiveTextEditor(textEditor => { + // Refresh the diagnostics when the focus is switched to a Java file. + if (textEditor?.document.uri?.scheme === "file" && textEditor?.document.languageId === "java") { + if (!validateAllOpenBuffersOnChanges()) { + languageClient.sendNotification(ValidateDocumentNotification.type, { + textDocument: { + uri: textEditor.document.uri.toString(), + }, + }); + } + } + })); +} diff --git a/src/documentSymbols.ts b/src/documentSymbols.ts new file mode 100644 index 0000000000..48f48d7669 --- /dev/null +++ b/src/documentSymbols.ts @@ -0,0 +1,29 @@ +'use strict'; + +import { + CancellationToken, + DocumentSymbol, + DocumentSymbolParams, + DocumentSymbolRequest, + SymbolInformation +} from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { getActiveLanguageClient } from "./extension"; + +type DocumentSymbolsResponse = DocumentSymbol[] | SymbolInformation[] | null; + +export type GetDocumentSymbolsCommand = (params: DocumentSymbolParams, token?: CancellationToken) => Promise; + +export function getDocumentSymbolsProvider(): GetDocumentSymbolsCommand { + return async (params: DocumentSymbolParams, token?: CancellationToken): Promise => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + if (!languageClient) { + return []; + } + + if (token !== undefined) { + return languageClient.sendRequest(DocumentSymbolRequest.type, params, token); + } + return languageClient.sendRequest(DocumentSymbolRequest.type, params); + }; +} diff --git a/src/errorUtils.ts b/src/errorUtils.ts new file mode 100644 index 0000000000..a098b73691 --- /dev/null +++ b/src/errorUtils.ts @@ -0,0 +1,24 @@ +// copied from https://github.com/redhat-developer/openshift-dd-ext/blob/f8c053bded9bc6c1bfac682cf4867b187e87ee76/client/src/utils/ErrorUtils.ts#L12 +export function getMessage(error: any): string { + return getRawMessage(error).trim(); +} + +export function getRawMessage(error: any): string { + if (typeof error === 'string') { + return error; + } + if (error.stderr) { + return error.stderr; + } + if (error.message) { + return error.message; + } + if (error.error) { + return error.error; + } + + // Unlikely to happen, as we're either getting an Error object with a message + // or we're dealing with a failed promise with a stderr message + // in any other case, we'll need to figure out what to return on a case by case basis + return JSON.stringify(error); +} \ No newline at end of file diff --git a/src/extension.api.ts b/src/extension.api.ts index c269c5dd0e..7e44da530b 100644 --- a/src/extension.api.ts +++ b/src/extension.api.ts @@ -1,7 +1,209 @@ +import { GetDocumentSymbolsCommand } from './documentSymbols'; +import { GoToDefinitionCommand } from './goToDefinition'; import { RequirementsData } from './requirements'; +import { TextDocumentPositionParams } from 'vscode-languageclient'; +import { CancellationToken, Command, ProviderResult, Uri, Event } from 'vscode'; +import { ServerMode } from './settings'; + +export type ProvideHoverCommandFn = (params: TextDocumentPositionParams, token: CancellationToken) => ProviderResult; +export type RegisterHoverCommand = (callback: ProvideHoverCommandFn) => void; + +/** + * Gets the project settings. This API is not supported in light weight server mode so far. + * @param uri Uri of the file that needs to be queried. Accepted uris are: source file, class file and project root path. + * @param OptionKeys the settings we want to query, for example: ["org.eclipse.jdt.core.compiler.compliance", "org.eclipse.jdt.core.compiler.source"]. + * Besides the options defined in JavaCore, the following keys can also be used: + * - "org.eclipse.jdt.ls.core.vm.location": Get the location of the VM assigned to build the given Java project + * - "org.eclipse.jdt.ls.core.sourcePaths": Get the source root paths of the given Java project + * - "org.eclipse.jdt.ls.core.outputPath": Get the default output path of the given Java project. Note that the default output path + * may not be equal to the output path of each source root. + * - "org.eclipse.jdt.ls.core.referencedLibraries": Get all the referenced library files of the given Java project + * @returns An object with all the optionKeys. + * @throws Will throw errors if the Uri does not belong to any project. + */ + +export type GetProjectSettingsCommand = (uri: string, SettingKeys: string[]) => Promise; + +/** + * Gets the classpaths and modulepaths. This API is not supported in light weight server mode so far. + * @param uri Uri of the file that needs to be queried. Accepted uris are: source file, class file and project root path. + * @param options Query options. + * @returns ClasspathResult containing both classpaths and modulepaths. + * @throws Will throw errors if the Uri does not belong to any project. + */ + +export type GetClasspathsCommand = (uri: string, options: ClasspathQueryOptions) => Promise; +export type ClasspathQueryOptions = { + /** + * Determines the scope of the classpath. Valid scopes are "runtime" and "test". + * If the given scope is not supported, "runtime" will be used. + */ + scope: string; +}; + +export type ClasspathResult = { + /** + * Uri string of the project root path. + */ + projectRoot: string; + /** + * File path array for the classpaths. + */ + classpaths: string[]; + /** + * File path array for the modulepaths. + */ + modulepaths: string[]; +}; + +/** + * Checks if the input uri is a test source file or not. This API is not supported in light weight server mode so far. + * @param uri Uri of the file that needs to be queried. Accepted uris are: source file, class file and project root path. + * @returns `true` if the input uri is a test file in its belonging project, otherwise returns false. + * @throws Will throw errors if the Uri does not belong to any project. + */ +export type IsTestFileCommand = (uri: string) => Promise; + +export enum ClientStatus { + uninitialized = "Uninitialized", + initialized = "Initialized", + starting = "Starting", + started = "Started", + error = "Error", + stopping = "Stopping", +} + +export interface TraceEvent { + /** + * Request type. + */ + type: string; + /** + * Time (in milliseconds) taken to process a request. + */ + duration?: number; + /** + * Error that occurs while processing a request. + */ + error?: any; + /** + * The number of results returned by a response. + */ + resultLength?: number | undefined; + /** + * Additional data properties, such as the completion trigger context. + */ + data?: any; + /** + * Whether the response is from the syntax server. + */ + fromSyntaxServer?: boolean; +} + +export interface SourceInvalidatedEvent { + /** + * The paths of the jar files that are linked to new source attachments. + */ + affectedRootPaths: string[]; + /** + * The opened editors with updated source. + */ + affectedEditorDocuments?: Uri[]; +} + +export const extensionApiVersion = '0.14'; export interface ExtensionAPI { - readonly apiVersion: string; + readonly apiVersion: string; readonly javaRequirement: RequirementsData; - readonly status: "Started" | "Error"; + status: ClientStatus; + readonly registerHoverCommand: RegisterHoverCommand; + readonly getDocumentSymbols: GetDocumentSymbolsCommand; + readonly getProjectSettings: GetProjectSettingsCommand; + readonly getClasspaths: GetClasspathsCommand; + readonly isTestFile: IsTestFileCommand; + /** + * An event which fires on classpath update. This API is not supported in light weight server mode so far. + * + * Note: + * 1. This event will fire when the project's configuration file (e.g. pom.xml for Maven) get changed, + * but the classpaths might still be the same as before. + * 2. The Uri points to the project root path. + */ + readonly onDidClasspathUpdate: Event; + /** + * An event fires on projects imported. This API is not supported in light weight server mode so far. + * The Uris in the array point to the project root path. + */ + readonly onDidProjectsImport: Event; + + /** + * An event fires on projects deleted. This API is not supported in light weight server mode so far. + * The Uris in the array point to the project root path. + * + * @since API version 0.13 + * @since extension version 1.25.0 + */ + readonly onDidProjectsDelete: Event; + + readonly goToDefinition: GoToDefinitionCommand; + /** + * Indicates the current active mode for Java Language Server. Possible modes are: + * - "Standard" + * - "Hybrid" + * - "LightWeight" + */ + serverMode: ServerMode; + /** + * An event which fires when the server mode has been switched. + */ + readonly onDidServerModeChange: Event; + + /** + * A promise that will be resolved when the standard language server is ready. + * Note: The server here denotes for the standard server, not the lightweight. + * @since API version 0.7 + * @since extension version 1.7.0 + */ + readonly serverReady: () => Promise; + + /** + * A promise that will be resolved when the language server process is running + * and can accept requests, even if project imports have not yet completed. + * This allows extensions to start querying for projects incrementally during import. + * @since API version 0.14 + */ + readonly serverRunning?: () => Promise; + + /** + * An event that's fired when a request is about to send to language server. + * @since API version 0.12 + * @since extension version 1.23.0 + */ + readonly onWillRequestStart: Event; + + /** + * An event that's fired when a request has been responded. + * @since API version 0.8 + * @since extension version 1.16.0 + */ + readonly onDidRequestEnd: Event; + + /** + * Allow 3rd party trace handler to track the language client & server error events. + * + * @since API version 0.9 + * @since extension version 1.20.0 + */ + readonly trackEvent: Event; + + /** + * An event that occurs when the package fragment roots have updated source attachments. + * The client should refresh the new source if it has previously requested the source + * from them. + * + * @since API version 0.10 + * @since extension version 1.21.0 + */ + readonly onDidSourceInvalidate: Event; } diff --git a/src/extension.ts b/src/extension.ts index e91c7a79fa..7cbed65d6e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,36 +1,201 @@ 'use strict'; -import * as path from 'path'; -import * as os from 'os'; +import * as chokidar from 'chokidar'; import * as fs from 'fs'; -import { workspace, extensions, ExtensionContext, window, StatusBarAlignment, commands, ViewColumn, Uri, CancellationToken, TextDocumentContentProvider, TextEditor, WorkspaceConfiguration, languages, IndentAction, ProgressLocation, InputBoxOptions, Selection, Position, EventEmitter } from 'vscode'; -import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, Position as LSPosition, Location as LSLocation, StreamInfo, VersionedTextDocumentIdentifier } from 'vscode-languageclient'; -import { onExtensionChange, collectJavaExtensions } from './plugin'; -import { prepareExecutable, awaitServerConnection } from './javaServerStarter'; -import * as requirements from './requirements'; -import { Commands } from './commands'; +import * as fse from 'fs-extra'; +import { glob } from 'glob'; +import * as os from 'os'; +import * as path from 'path'; +import * as semver from 'semver'; import { - StatusNotification, ClassFileContentsRequest, ProjectConfigurationUpdateRequest, MessageType, ActionableNotification, FeatureStatus, CompileWorkspaceRequest, CompileWorkspaceStatus, ProgressReportNotification, ExecuteClientCommandRequest, SendNotificationRequest, - SourceAttachmentRequest, SourceAttachmentResult, SourceAttachmentAttribute -} from './protocol'; -import { ExtensionAPI } from './extension.api'; -import * as buildpath from './buildpath'; -import * as sourceAction from './sourceAction'; -import * as refactorAction from './refactorAction'; -import * as net from 'net'; -import { getJavaConfiguration } from './utils'; -import { onConfigurationChange, excludeProjectSettingsFiles } from './settings'; - -let lastStatus; -let languageClient: LanguageClient; + CodeActionContext, commands, CompletionItem, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, + InputBoxOptions, Location, MarkdownString, RelativePattern, + SnippetString, SnippetTextEdit, TextDocument, TextEditorRevealType, UIKind, Uri, version, ViewColumn, window, workspace, WorkspaceConfiguration +} from 'vscode'; +import { CancellationToken, CodeActionParams, CodeActionRequest, CodeActionResolveRequest, Command, CompletionRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient'; +import { Executable, LanguageClient } from 'vscode-languageclient/node'; +import { apiManager } from './apiManager'; +import { BuildFileSelector, cleanupWorkspaceState, PICKED_BUILD_FILES } from './buildFilesSelector'; +import { ClientErrorHandler } from './clientErrorHandler'; +import { Commands } from './commands'; +import { Dashboard } from './dashboard/dashboard'; +import { getMessage } from './errorUtils'; +import { ClientStatus, ExtensionAPI, TraceEvent } from './extension.api'; +import * as fileEventHandler from './fileEventHandler'; +import { JavaClassEditorProvider } from './javaClassEditor'; +import { getSharedIndexCache, HEAP_DUMP_LOCATION, prepareExecutable, removeEquinoxFragmentOnDarwinX64, startedFromSources } from './javaServerStarter'; +import { loadSupportedJreNames } from './jdkUtils'; +import { initializeLogFile, logger } from './log'; +import { cleanupLombokCache } from "./lombokSupport"; +import { markdownPreviewProvider } from "./markdownPreviewProvider"; +import { OutputInfoCollector } from './outputInfoCollector'; +import { pasteFile } from './pasteAction'; +import { collectJavaExtensions, getBundlesToReload, getShortcuts, IJavaShortcut, isContributedPartUpdated } from './plugin'; +import { Deferred } from './promiseUtil'; +import { fixJdtSchemeHoverLinks, registerClientProviders } from './providerDispatcher'; +import * as requirements from './requirements'; +import { languageStatusBarProvider } from './runtimeStatusBarProvider'; +import { ServerStatusKind } from './serverStatus'; +import { serverStatusBarProvider, ShortcutQuickPickItem } from './serverStatusBarProvider'; +import { activationProgressNotification } from "./serverTaskPresenter"; +import { ACTIVE_BUILD_TOOL_STATE, cleanWorkspaceFileName, getImportMode, getJavaServerMode, handleTextDocumentChanges, ImportMode, onConfigurationChange, ServerMode } from './settings'; +import { snippetCompletionProvider } from './snippetCompletionProvider'; +import { StandardLanguageClient } from './standardLanguageClient'; +import { SyntaxLanguageClient } from './syntaxLanguageClient'; +import { Telemetry } from './telemetry'; +import { cleanJavaLSConfiguration, convertToGlob, deleteClientLog, deleteDirectory, ensureExists, getBuildFilePatterns, getExclusionGlob, getInclusionPatternsFromNegatedExclusion, getJavaConfig, getJavaConfiguration, getVersion, hasBuildToolConflicts, resolveActualCause } from './utils'; +import { JavaRuntimes } from './javaRuntimes'; + +const syntaxClient: SyntaxLanguageClient = new SyntaxLanguageClient(); +const standardClient: StandardLanguageClient = new StandardLanguageClient(); const jdtEventEmitter = new EventEmitter(); -const cleanWorkspaceFileName = '.cleanWorkspace'; +const extensionName = 'Language Support for Java'; +let storagePath: string; +let clientLogFile: string; + +const excutable= new Deferred(); + +export async function getExecutable(): Promise { + return excutable.promise; +} + +const javaConfigDeferred = new Deferred(); +export async function getComputedJavaConfig(): Promise { + return javaConfigDeferred.promise; +} + +/** + * Shows a message about the server crashing due to an out of memory issue + */ +async function showOOMMessage(): Promise { + const CONFIGURE = 'Increase Memory ..'; + const result = await window.showErrorMessage('The Java Language Server encountered an OutOfMemory error. Some language features may not work due to limited memory. ', + CONFIGURE); + if (result === CONFIGURE) { + let jvmArgs: string = getJavaConfiguration().get('jdt.ls.vmargs'); + const results = MAX_HEAP_SIZE_EXTRACTOR.exec(jvmArgs); + if (results && results[0]) { + const maxMemArg: string = results[0]; + const maxMemValue: number = Number(results[1]); + const newMaxMemArg: string = maxMemArg.replace(maxMemValue.toString(), (maxMemValue * 2).toString()); + jvmArgs = jvmArgs.replace(maxMemArg, newMaxMemArg); + await workspace.getConfiguration().update("java.jdt.ls.vmargs", jvmArgs, ConfigurationTarget.Workspace); + } + } +} + +function getMaxMemFromConfiguration(includeUnit?: boolean): string | undefined { + const jvmArgs: string = getJavaConfiguration().get('jdt.ls.vmargs'); + const results = includeUnit ? MAX_HEAP_SIZE_EXTRACTOR_WITH_UNIT.exec(jvmArgs) + : MAX_HEAP_SIZE_EXTRACTOR.exec(jvmArgs); + return results && results[0] ? results[1] : undefined; +} + +const HEAP_DUMP_FOLDER_EXTRACTOR = new RegExp(`${HEAP_DUMP_LOCATION}(?:'([^']+)'|"([^"]+)"|([^\\s]+))`); +const MAX_HEAP_SIZE_EXTRACTOR = new RegExp(`-Xmx([0-9]+)[kKmMgG]`); +const MAX_HEAP_SIZE_EXTRACTOR_WITH_UNIT = new RegExp(`-Xmx([0-9]+[kKmMgG])`); + +/** + * Returns the heap dump folder defined in the user's preferences, or undefined if the user does not set the heap dump folder + * + * @returns the heap dump folder defined in the user's preferences, or undefined if the user does not set the heap dump folder + */ +function getHeapDumpFolderFromSettings(): string { + const jvmArgs: string = getJavaConfiguration().get('jdt.ls.vmargs'); + const results = HEAP_DUMP_FOLDER_EXTRACTOR.exec(jvmArgs); + if (!results || !results[0]) { + return undefined; + } + return results[1] || results[2] || results[3]; +} + +const REPLACE_JDT_LINKS_PATTERN: RegExp = /(\[(?:[^\]])+\]\()(jdt:\/\/(?:(?:(?:\\\))|([^)]))+))\)/g; +const EXISTING_COMMAND_PATTERN: RegExp = /\[([^\]]+)\]\(command:[^)]+\)/g; + +/** + * Replace `jdt://` links in the documentation with links that execute the VS Code command required to open the referenced file. + * + * Extracted from {@link fixJdtSchemeHoverLinks} for use in completion item documentation. + * + * @param oldDocumentation the documentation to fix the links in + * @returns the documentation with fixed links + */ +export function fixJdtLinksInDocumentation(oldDocumentation: MarkdownString): MarkdownString { + // sanitize existing command: links + const sanitizedContent = oldDocumentation.value.replace(EXISTING_COMMAND_PATTERN, (_substring, group1: string, group2) => { + return group1; + }); + const newContent: string = sanitizedContent.replace(REPLACE_JDT_LINKS_PATTERN, (_substring, group1, group2) => { + const uri = `command:${Commands.OPEN_FILE}?${encodeURI(JSON.stringify([encodeURIComponent(group2)]))}`; + return `${group1}${uri})`; + }); + const mdString = new MarkdownString(newContent); + mdString.isTrusted = true; + return mdString; +} + +export async function activate(context: ExtensionContext): Promise { + storagePath = context.storagePath; + if (!storagePath) { + storagePath = getTempWorkspace(); + } + Dashboard.initialize(context); + + await loadSupportedJreNames(context); + await JavaRuntimes.initialize(context); + context.subscriptions.push(commands.registerCommand(Commands.FILESEXPLORER_ONPASTE, async () => { + const originalClipboard = await env.clipboard.readText(); + // Hack in order to get path to selected folder if applicable (see https://github.com/microsoft/vscode/issues/3553#issuecomment-1098562676) + await commands.executeCommand('copyFilePath'); + const folder = await env.clipboard.readText(); + await env.clipboard.writeText(originalClipboard); + pasteFile(folder); + })); + context.subscriptions.push(markdownPreviewProvider); + context.subscriptions.push(commands.registerCommand(Commands.TEMPLATE_VARIABLES, async () => { + markdownPreviewProvider.show(context.asAbsolutePath(path.join('document', `${Commands.TEMPLATE_VARIABLES}.md`)), 'Predefined Variables', "", context); + })); + context.subscriptions.push(commands.registerCommand(Commands.NOT_COVERED_EXECUTION, async () => { + markdownPreviewProvider.show(context.asAbsolutePath(path.join('document', `_java.notCoveredExecution.md`)), 'Not Covered Maven Plugin Execution', "", context); + })); + + context.subscriptions.push(commands.registerCommand(Commands.METADATA_FILES_GENERATION, async () => { + markdownPreviewProvider.show(context.asAbsolutePath(path.join('document', `_java.metadataFilesGeneration.md`)), 'Metadata Files Generation', "", context); + })); + context.subscriptions.push(commands.registerCommand(Commands.LEARN_MORE_ABOUT_CLEAN_UPS, async () => { + markdownPreviewProvider.show(context.asAbsolutePath(path.join('document', `${Commands.LEARN_MORE_ABOUT_CLEAN_UPS}.md`)), 'Java Clean Ups', "java-clean-ups", context); + })); + + const workspacePath = path.resolve(`${storagePath}/jdt_ws`); + clientLogFile = path.join(storagePath, 'client.log'); + const cleanWorkspaceExists = fs.existsSync(path.join(workspacePath, cleanWorkspaceFileName)); + if (cleanWorkspaceExists) { + deleteClientLog(storagePath); + } + initializeLogFile(clientLogFile); + + Telemetry.startTelemetry(context); + + registerOutOfMemoryDetection(storagePath); -export function activate(context: ExtensionContext): Promise { + cleanJavaWorkspaceStorage(); - enableJavadocSymbols(); + if (!startedFromSources()) { // Dev mode: version may not match package.json, deleting the in-use folder + cleanOldGlobalStorage(context); + } + + // https://github.com/redhat-developer/vscode-java/issues/3484 + if (process.platform === 'darwin' && process.arch === 'x64') { + try { + if (semver.lt(os.release(), '20.0.0')) { + removeEquinoxFragmentOnDarwinX64(context); + } + } catch (error) { + // do nothing + } + } - return requirements.resolveRequirements().catch(error => { + return requirements.resolveRequirements(context).catch(error => { // show error window.showErrorMessage(error.message, error.label).then((selection) => { if (error.label && error.label === selection && error.command) { @@ -39,415 +204,654 @@ export function activate(context: ExtensionContext): Promise { }); // rethrow to disrupt the chain. throw error; - }).then(requirements => { - return window.withProgress({ location: ProgressLocation.Window }, p => { - return new Promise((resolve, reject) => { - let storagePath = context.storagePath; - if (!storagePath) { - storagePath = getTempWorkspace(); - } - const workspacePath = path.resolve(storagePath + '/jdt_ws'); - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for java - documentSelector: [ - { scheme: 'file', language: 'java' }, - { scheme: 'jdt', language: 'java' }, - { scheme: 'untitled', language: 'java' } - ], - synchronize: { - configurationSection: 'java', - }, - initializationOptions: { - bundles: collectJavaExtensions(extensions.all), - workspaceFolders: workspace.workspaceFolders ? workspace.workspaceFolders.map(f => f.uri.toString()) : null, - settings: { java: getJavaConfiguration() }, - extendedClientCapabilities: { - progressReportProvider: getJavaConfiguration().get('progressReports.enabled'), - classFileContentsSupport: true, - overrideMethodsPromptSupport: true, - hashCodeEqualsPromptSupport: true, - advancedOrganizeImportsSupport: true, - generateToStringPromptSupport: true, - advancedGenerateAccessorsSupport: true, - generateConstructorsPromptSupport: true, - generateDelegateMethodsPromptSupport: true, - advancedExtractRefactoringSupport: true, - }, - triggerFiles: getTriggerFiles() - }, - revealOutputChannelOn: RevealOutputChannelOn.Never - }; + }).then(async (requirements) => { + const triggerFiles = await getTriggerFiles(); + return new Promise(async (resolve) => { + const syntaxServerWorkspacePath = path.resolve(`${storagePath}/ss_ws`); - const item = window.createStatusBarItem(StatusBarAlignment.Right, Number.MIN_VALUE); - item.text = '$(sync~spin)'; - item.command = Commands.OPEN_OUTPUT; - const progressBar = window.createStatusBarItem(StatusBarAlignment.Left, Number.MIN_VALUE + 1); - - let serverOptions; - const port = process.env['SERVER_PORT']; - if (!port) { - const lsPort = process.env['JDTLS_CLIENT_PORT']; - if (!lsPort) { - serverOptions = prepareExecutable(requirements, workspacePath, getJavaConfiguration()); - } else { - serverOptions = () => { - const socket = net.connect(lsPort); - const result: StreamInfo = { - writer: socket, - reader: socket - }; - return Promise.resolve(result); - }; - } - } else { - // used during development - serverOptions = awaitServerConnection.bind(null, port); - } + let serverMode = getJavaServerMode(); + const isWorkspaceTrusted = (workspace as any).isTrusted; // TODO: use workspace.isTrusted directly when other clients catch up to adopt 1.56.0 + if (isWorkspaceTrusted !== undefined && !isWorkspaceTrusted) { // keep compatibility for old engines < 1.56.0 + serverMode = ServerMode.lightWeight; + } + commands.executeCommand('setContext', 'java:serverMode', serverMode); + const isDebugModeByClientPort = !!process.env['SYNTAXLS_CLIENT_PORT'] || !!process.env['JDTLS_CLIENT_PORT']; + const requireSyntaxServer = (serverMode !== ServerMode.standard) && (!isDebugModeByClientPort || !!process.env['SYNTAXLS_CLIENT_PORT']); + let requireStandardServer = (serverMode !== ServerMode.lightWeight) && (!isDebugModeByClientPort || !!process.env['JDTLS_CLIENT_PORT']); + let initFailureReported: boolean = false; - // Create the language client and start the client. - languageClient = new LanguageClient('java', 'Language Support for Java', serverOptions, clientOptions); - languageClient.registerProposedFeatures(); - - languageClient.onReady().then(() => { - languageClient.onNotification(StatusNotification.type, (report) => { - switch (report.type) { - case 'Started': - item.text = '$(thumbsup)'; - p.report({ message: 'Finished' }); - lastStatus = item.text; - commands.executeCommand('setContext', 'javaLSReady', true); - resolve({ - apiVersion: '0.2', - javaRequirement: requirements, - status: report.type - }); - break; - case 'Error': - item.text = '$(thumbsdown)'; - lastStatus = item.text; - p.report({ message: 'Finished with Error' }); - toggleItem(window.activeTextEditor, item); - resolve({ - apiVersion: '0.2', - javaRequirement: requirements, - status: report.type - }); - break; - case 'Starting': - p.report({ message: report.message }); - break; - case 'Message': - item.text = report.message; - setTimeout(() => { item.text = lastStatus; }, 3000); - break; + const javaConfig = await getJavaConfig(requirements.java_home); + javaConfigDeferred.resolve(javaConfig); + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for java + documentSelector: [ + { scheme: 'file', language: 'java' }, + { scheme: 'jdt', language: 'java' }, + { scheme: 'untitled', language: 'java' }, + { scheme: 'vscode-notebook-cell', language: 'java' } + ], + synchronize: { + configurationSection: ['java', 'editor.insertSpaces', 'editor.tabSize', "files.associations"], + }, + initializationOptions: { + bundles: collectJavaExtensions(extensions.all), + workspaceFolders: workspace.workspaceFolders ? workspace.workspaceFolders.map(f => f.uri.toString()) : null, + settings: { java: javaConfig }, + extendedClientCapabilities: { + classFileContentsSupport: true, + overrideMethodsPromptSupport: true, + hashCodeEqualsPromptSupport: true, + advancedOrganizeImportsSupport: true, + generateToStringPromptSupport: true, + advancedGenerateAccessorsSupport: true, + generateConstructorsPromptSupport: true, + generateDelegateMethodsPromptSupport: true, + advancedExtractRefactoringSupport: true, + inferSelectionSupport: ["extractMethod", "extractVariable", "extractField"], + moveRefactoringSupport: true, + clientHoverProvider: true, + clientDocumentSymbolProvider: true, + gradleChecksumWrapperPromptSupport: true, + advancedIntroduceParameterRefactoringSupport: true, + actionableRuntimeNotificationSupport: true, + onCompletionItemSelectedCommand: "editor.action.triggerParameterHints", + extractInterfaceSupport: true, + advancedUpgradeGradleSupport: true, + executeClientCommandSupport: true, + snippetEditSupport: true, + nonStandardJavaFormatting : { + schemes: ["vscode-notebook-cell"], + extensions: ["jsh", "jshell", "ipynb"], + getContentCallback: Commands.GET_VISIBLE_EDITOR_CONTENT, } - item.tooltip = report.message; - toggleItem(window.activeTextEditor, item); - }); - languageClient.onNotification(ProgressReportNotification.type, (progress) => { - progressBar.show(); - progressBar.text = progress.status; - if (progress.complete) { - setTimeout(() => { progressBar.hide(); }, 500); + }, + triggerFiles, + }, + middleware: { + workspace: { + didChangeConfiguration: async () => { + await standardClient.getClient().sendNotification(DidChangeConfigurationNotification.type, { + settings: { + java: await getJavaConfig(requirements.java_home), + } + }); } - }); - languageClient.onNotification(ActionableNotification.type, (notification) => { - let show = null; - switch (notification.severity) { - case MessageType.Log: - show = logNotification; - break; - case MessageType.Info: - show = window.showInformationMessage; - break; - case MessageType.Warning: - show = window.showWarningMessage; - break; - case MessageType.Error: - show = window.showErrorMessage; - break; + }, + resolveCompletionItem: async (item, token, next): Promise => { + const completionItem = await next(item, token); + if (completionItem?.documentation instanceof MarkdownString) { + completionItem.documentation = fixJdtLinksInDocumentation(completionItem.documentation); } - if (!show) { - return; + return completionItem; + }, + // https://github.com/redhat-developer/vscode-java/issues/2130 + // include all diagnostics for the current line in the CodeActionContext params for the performance reason + provideCodeActions: async (document, range, context, token, next) => { + const client: LanguageClient = standardClient.getClient(); + const params: CodeActionParams = { + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), + range: client.code2ProtocolConverter.asRange(range), + context: await client.code2ProtocolConverter.asCodeActionContext(context) + }; + const showAt = getJavaConfiguration().get("quickfix.showAt"); + if (showAt === 'line' && range.start.line === range.end.line && range.start.character === range.end.character) { + const textLine = document.lineAt(params.range.start.line); + if (textLine !== null) { + const diagnostics = client.diagnostics.get(document.uri); + const allDiagnostics: Diagnostic[] = []; + for (const diagnostic of diagnostics) { + if (textLine.range.intersection(diagnostic.range)) { + const newLen = allDiagnostics.push(diagnostic); + if (newLen > 1000) { + break; + } + } + } + const codeActionContext: CodeActionContext = { + diagnostics: allDiagnostics, + only: context.only, + triggerKind: context.triggerKind, + }; + params.context = await client.code2ProtocolConverter.asCodeActionContext(codeActionContext); + } } - const titles = notification.commands.map(a => a.title); - show(notification.message, ...titles).then((selection) => { - for (const action of notification.commands) { - if (action.title === selection) { - const args: any[] = (action.arguments) ? action.arguments : []; - commands.executeCommand(action.command, ...args); - break; + return client.sendRequest(CodeActionRequest.type, params, token).then(async (values) => { + if (values === null) { + return undefined; + } + const result = []; + for (const item of values) { + if (Command.is(item)) { + result.push(client.protocol2CodeConverter.asCommand(item)); + } + else { + result.push(await client.protocol2CodeConverter.asCodeAction(item)); } } + return result; + }, (error) => { + return client.handleFailedRequest(CodeActionRequest.type, token, error, []); }); - }); - languageClient.onRequest(ExecuteClientCommandRequest.type, (params) => { - return commands.executeCommand(params.command, ...params.arguments); - }); + }, - languageClient.onRequest(SendNotificationRequest.type, (params) => { - return commands.executeCommand(params.command, ...params.arguments); - }); + resolveCodeAction: async (item, token, next) => { + const client: LanguageClient = standardClient.getClient(); + const documentUris = []; + const snippetEdits = []; + return client.sendRequest(CodeActionResolveRequest.type, client.code2ProtocolConverter.asCodeActionSync(item), token).then(async (result) => { + if (token.isCancellationRequested) { + return item; + } + const docChanges = result.edit !== undefined ? result.edit.documentChanges : undefined; + if (docChanges !== undefined) { + for (const docChange of docChanges) { + if ("textDocument" in docChange) { + for (const edit of docChange.edits) { + if ("snippet" in edit) { + documentUris.push(Uri.parse(docChange.textDocument.uri).toString()); + const snippetValue = (edit as any).snippet.value; + const snippet = new SnippetTextEdit( + client.protocol2CodeConverter.asRange((edit as any).range), + new SnippetString(escapeSnippetLiterals(snippetValue)) + ); + if (semver.gte(version, '1.98.0')) { + snippet["keepWhitespace"] = true; + } + snippetEdits.push(snippet); + } + } + } + } + const codeAction = await client.protocol2CodeConverter.asCodeAction(result, token); + const docEdits = codeAction.edit !== undefined? codeAction.edit.entries() : []; + for (const docEdit of docEdits) { + const uri = docEdit[0]; + if (documentUris.includes(uri.toString())) { + const editList = []; + for (const edit of docEdit[1]) { + let isSnippet = false; + snippetEdits.forEach((snippet, index) => { + if (edit.range.isEqual(snippet.range) && documentUris[index] === uri.toString()) { + editList.push(snippet); + isSnippet = true; + } + }); + if (!isSnippet) { + editList.push(edit); + } + } + codeAction.edit.set(uri, null); + codeAction.edit.set(uri, editList); + } + } + return codeAction; + } + return await client.protocol2CodeConverter.asCodeAction(result, token); + }, (error) => { + return client.handleFailedRequest(CodeActionResolveRequest.type, token, error, item); + }); + }, - context.subscriptions.push(commands.registerCommand(Commands.SHOW_JAVA_REFERENCES, (uri: string, position: LSPosition, locations: LSLocation[]) => { - commands.executeCommand(Commands.SHOW_REFERENCES, Uri.parse(uri), languageClient.protocol2CodeConverter.asPosition(position), locations.map(languageClient.protocol2CodeConverter.asLocation)); - })); - context.subscriptions.push(commands.registerCommand(Commands.SHOW_JAVA_IMPLEMENTATIONS, (uri: string, position: LSPosition, locations: LSLocation[]) => { - commands.executeCommand(Commands.SHOW_REFERENCES, Uri.parse(uri), languageClient.protocol2CodeConverter.asPosition(position), locations.map(languageClient.protocol2CodeConverter.asLocation)); - })); + provideReferences: async(document, position, options, token, next): Promise => { + // Override includeDeclaration from VS Code by allowing it to be configured + options.includeDeclaration = getJavaConfiguration().get('references.includeDeclarations'); + return await next(document, position, options, token); + } + }, + revealOutputChannelOn: RevealOutputChannelOn.Never, + errorHandler: new ClientErrorHandler(extensionName), + initializationFailedHandler: error => { + logger.error(`Failed to initialize ${extensionName} due to ${error && error.toString()}`); + if ((error.toString().includes('Connection') && error.toString().includes('disposed')) || error.toString().includes('Internal error')) { + if (!initFailureReported) { + apiManager.fireTraceEvent({ + name: "java.client.error.initialization", + properties: { + message: error && error.toString(), + data: resolveActualCause(error?.data), + }, + }); + } + initFailureReported = true; + return false; + } else { + return true; + } + }, + outputChannel: requireStandardServer ? new OutputInfoCollector(extensionName) : undefined, + outputChannelName: extensionName + }; - context.subscriptions.push(commands.registerCommand(Commands.CONFIGURATION_UPDATE, uri => projectConfigurationUpdate(languageClient, uri))); + apiManager.initialize(requirements, serverMode); + registerCodeCompletionTelemetryListener(); + resolve(apiManager.getApiInstance()); + // the promise is resolved + // no need to pass `resolve` into any code past this point, + // since `resolve` is a no-op from now on + if (requireSyntaxServer) { + const serverOptions = prepareExecutable(requirements, syntaxServerWorkspacePath, context, true); + excutable.resolve(serverOptions); + if (process.env['SYNTAXLS_CLIENT_PORT']) { + syntaxClient.initialize(requirements, clientOptions); + } else { + syntaxClient.initialize(requirements, clientOptions, serverOptions); + } + syntaxClient.start().then(() => { + syntaxClient.registerSyntaxClientActions(serverOptions); + }); + serverStatusBarProvider.showLightWeightStatus(); + } - context.subscriptions.push(commands.registerCommand(Commands.IGNORE_INCOMPLETE_CLASSPATH, (data?: any) => setIncompleteClasspathSeverity('ignore'))); + context.subscriptions.push(commands.registerCommand(Commands.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { + const api: ExtensionAPI = apiManager.getApiInstance(); + if (api.serverMode === ServerMode.lightWeight) { + console.warn(`The command: ${command} is not supported in LightWeight mode. See: https://github.com/redhat-developer/vscode-java/issues/1480`); + return; + } + let token: CancellationToken; + let commandArgs: any[] = rest; + if (rest && rest.length && CancellationToken.is(rest[rest.length - 1])) { + token = rest[rest.length - 1]; + commandArgs = rest.slice(0, rest.length - 1); + } + const params: ExecuteCommandParams = { + command, + arguments: commandArgs + }; + if (token) { + return standardClient.getClient().sendRequest(ExecuteCommandRequest.type, params, token); + } else { + return standardClient.getClient().sendRequest(ExecuteCommandRequest.type, params); + } + })); - context.subscriptions.push(commands.registerCommand(Commands.IGNORE_INCOMPLETE_CLASSPATH_HELP, (data?: any) => { - commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse('https://github.com/redhat-developer/vscode-java/wiki/%22Classpath-is-incomplete%22-warning')); - })); + if (cleanWorkspaceExists) { + const data = {}; + try { + cleanupLombokCache(context); + cleanupWorkspaceState(context); + deleteDirectory(workspacePath); + deleteDirectory(syntaxServerWorkspacePath); + cleanJavaLSConfiguration(context); + } catch (error) { + data['error'] = getMessage(error); + window.showErrorMessage(`Failed to delete ${workspacePath}: ${error}`); + } + await Telemetry.sendTelemetry(Commands.CLEAN_WORKSPACE, data); + } - context.subscriptions.push(commands.registerCommand(Commands.PROJECT_CONFIGURATION_STATUS, (uri, status) => setProjectConfigurationUpdate(languageClient, uri, status))); + // Register commands here to make it available even when the language client fails + context.subscriptions.push(commands.registerCommand(Commands.OPEN_STATUS_SHORTCUT, async (status: string) => { + const items: ShortcutQuickPickItem[] = []; + if (status === ServerStatusKind.error || status === ServerStatusKind.warning) { + commands.executeCommand("workbench.panel.markers.view.focus"); + } else { + commands.executeCommand(Commands.SHOW_SERVER_TASK_STATUS, true); + } - context.subscriptions.push(commands.registerCommand(Commands.APPLY_WORKSPACE_EDIT, (obj) => { - applyWorkspaceEdit(obj, languageClient); - })); + items.push(...getShortcuts().map((shortcut: IJavaShortcut) => { + return { + label: shortcut.title, + command: shortcut.command, + args: shortcut.arguments, + }; + })); - context.subscriptions.push(commands.registerCommand(Commands.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { - const params: ExecuteCommandParams = { - command, - arguments: rest - }; - return languageClient.sendRequest(ExecuteCommandRequest.type, params); - })); - - context.subscriptions.push(commands.registerCommand(Commands.COMPILE_WORKSPACE, (isFullCompile: boolean) => { - return window.withProgress({ location: ProgressLocation.Window }, async p => { - if (typeof isFullCompile !== 'boolean') { - const selection = await window.showQuickPick(['Incremental', 'Full'], { placeHolder: 'please choose compile type:' }); - isFullCompile = selection !== 'Incremental'; - } - p.report({ message: 'Compiling workspace...' }); - const start = new Date().getTime(); - const res = await languageClient.sendRequest(CompileWorkspaceRequest.type, isFullCompile); - const elapsed = new Date().getTime() - start; - const humanVisibleDelay = elapsed < 1000 ? 1000 : 0; - return new Promise((resolve, reject) => { - setTimeout(() => { // set a timeout so user would still see the message when build time is short - if (res === CompileWorkspaceStatus.SUCCEED) { - resolve(res); - } else { - reject(res); - } - }, humanVisibleDelay); - }); - }); - })); + const choice = await window.showQuickPick(items); + if (!choice) { + return; + } - context.subscriptions.push(commands.registerCommand(Commands.UPDATE_SOURCE_ATTACHMENT, async (classFileUri: Uri): Promise => { - const resolveRequest: SourceAttachmentRequest = { - classFileUri: classFileUri.toString(), - }; - const resolveResult: SourceAttachmentResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_SOURCE_ATTACHMENT, JSON.stringify(resolveRequest)); - if (resolveResult.errorMessage) { - window.showErrorMessage(resolveResult.errorMessage); - return false; - } + apiManager.fireTraceEvent({ + name: "triggerShortcutCommand", + properties: { + message: choice.command, + }, + }); - const attributes: SourceAttachmentAttribute = resolveResult.attributes || {}; - const defaultPath = attributes.sourceAttachmentPath || attributes.jarPath; - const sourceFileUris: Uri[] = await window.showOpenDialog({ - defaultUri: defaultPath ? Uri.file(defaultPath) : null, - openLabel: 'Select Source File', - canSelectFiles: true, - canSelectFolders: false, - canSelectMany: false, - filters: { - 'Source files': ['jar', 'zip'] - }, - }); + if (choice.command) { + commands.executeCommand(choice.command, ...(choice.args || [])); + } + })); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_SERVER_LOG, (column: ViewColumn) => openServerLogFile(storagePath, column))); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_SERVER_STDOUT_LOG, (column: ViewColumn) => openRollingServerLogFile(storagePath, '.out-jdt.ls', column))); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_SERVER_STDERR_LOG, (column: ViewColumn) => openRollingServerLogFile(storagePath, '.error-jdt.ls', column))); - if (sourceFileUris && sourceFileUris.length) { - const updateRequest: SourceAttachmentRequest = { - classFileUri: classFileUri.toString(), - attributes: { - ...attributes, - sourceAttachmentPath: sourceFileUris[0].fsPath - }, - }; - const updateResult: SourceAttachmentResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.UPDATE_SOURCE_ATTACHMENT, JSON.stringify(updateRequest)); - if (updateResult.errorMessage) { - window.showErrorMessage(updateResult.errorMessage); - return false; - } + context.subscriptions.push(commands.registerCommand(Commands.OPEN_CLIENT_LOG, (column: ViewColumn) => openClientLogFile(clientLogFile, column))); - // Notify jdt content provider to rerender the classfile contents. - jdtEventEmitter.fire(classFileUri); - return true; - } - })); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_LOGS, () => openLogs())); - buildpath.registerCommands(context); - sourceAction.registerCommands(languageClient, context); - refactorAction.registerCommands(languageClient, context); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_FORMATTER, async () => openFormatter(context.extensionPath))); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_FILE, async (uri: string) => { + const parsedUri = Uri.parse(uri); + const editor = await window.showTextDocument(parsedUri); + // Reveal the document at the specified line, if possible (e.g. jumping to a specific javadoc method). + if (editor && parsedUri.scheme === 'jdt' && parsedUri.fragment) { + const line = parseInt(parsedUri.fragment); + if (isNaN(line) || line < 1 || line > editor.document.lineCount) { + return; + } + const range = editor.document.lineAt(line -1).range; + editor.revealRange(range, TextEditorRevealType.AtTop); + } + })); - context.subscriptions.push(window.onDidChangeActiveTextEditor((editor) => { - toggleItem(editor, item); - })); + context.subscriptions.push(commands.registerCommand(Commands.CLEAN_WORKSPACE, (force?: boolean) => cleanWorkspace(workspacePath, force))); + context.subscriptions.push(commands.registerCommand(Commands.CLEAN_SHARED_INDEXES, () => cleanSharedIndexes(context))); - const provider: TextDocumentContentProvider = { - onDidChange: jdtEventEmitter.event, - provideTextDocumentContent: (uri: Uri, token: CancellationToken): Thenable => { - return languageClient.sendRequest(ClassFileContentsRequest.type, { uri: uri.toString() }, token).then((v: string): string => { - return v || ''; - }); - } - }; - context.subscriptions.push(workspace.registerTextDocumentContentProvider('jdt', provider)); - if (extensions.onDidChange) {// Theia doesn't support this API yet - extensions.onDidChange(() => { - onExtensionChange(extensions.all); - }); + context.subscriptions.push(commands.registerCommand(Commands.GET_WORKSPACE_PATH, () => workspacePath)); + + context.subscriptions.push(commands.registerCommand(Commands.REFRESH_BUNDLES_COMMAND, () => { + return getBundlesToReload(); + })); + + context.subscriptions.push(onConfigurationChange(workspacePath, context)); + + context.subscriptions.push(commands.registerCommand(Commands.GET_VISIBLE_EDITOR_CONTENT, (uri: string) => { + for (const editor of window.visibleTextEditors) { + if (editor.document.uri.toString() === uri) { + return editor.document.getText(); } - excludeProjectSettingsFiles(); - }); + } + const editor = window.activeTextEditor; + if (editor) { + return editor.document.getText(); + } else { + return null; + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.COPY_FULLY_QUALIFIED_NAME, async () => { + const editor = window.activeTextEditor; + if (!editor || editor.document.languageId !== 'java') { + return; + } + + const params = { + textDocument: { + uri: editor.document.uri.toString() + }, + position: { + line: editor.selection.active.line, + character: editor.selection.active.character + } + }; + + const fullyQualifiedName = await commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.GET_FULLY_QUALIFIED_NAME, + JSON.stringify(params) + ); + + if (fullyQualifiedName) { + await env.clipboard.writeText(fullyQualifiedName); + } + })); + registerRestartJavaLanguageServerCommand(context); - const cleanWorkspaceExists = fs.existsSync(path.join(workspacePath, cleanWorkspaceFileName)); - if (cleanWorkspaceExists) { - try { - deleteDirectory(workspacePath); - } catch (error) { - window.showErrorMessage(`Failed to delete ${workspacePath}: ${error}`); + /** + * Command to switch the server mode. Currently it only supports switch from lightweight to standard. + * @param force force to switch server mode without asking + */ + commands.registerCommand(Commands.SWITCH_SERVER_MODE, async (switchTo: ServerMode, force: boolean = false) => { + const isWorkspaceTrusted = (workspace as any).isTrusted; + if (isWorkspaceTrusted !== undefined && !isWorkspaceTrusted) { // keep compatibility for old engines < 1.56.0 + const button = "Manage Workspace Trust"; + const choice = await window.showInformationMessage("For security concern, Java language server cannot be switched to Standard mode in untrusted workspaces.", button); + if (choice === button) { + commands.executeCommand("workbench.trust.manage"); } + return; } - languageClient.start(); - // Register commands here to make it available even when the language client fails + const clientStatus: ClientStatus = standardClient.getClientStatus(); + if (clientStatus === ClientStatus.starting || clientStatus === ClientStatus.started) { + return; + } - context.subscriptions.push(commands.registerCommand(Commands.OPEN_OUTPUT, () => languageClient.outputChannel.show(ViewColumn.Three))); + const api: ExtensionAPI = apiManager.getApiInstance(); + if (!force && (api.serverMode === switchTo || api.serverMode === ServerMode.standard)) { + return; + } - context.subscriptions.push(commands.registerCommand(Commands.OPEN_SERVER_LOG, () => openServerLogFile(workspacePath))); + let choice: string; + if (force) { + choice = "Yes"; + } else { + choice = await window.showInformationMessage("Are you sure you want to switch the Java language server to Standard mode?", "Yes", "No"); + } - const extensionPath = context.extensionPath; - context.subscriptions.push(commands.registerCommand(Commands.OPEN_FORMATTER, async () => openFormatter(extensionPath))); + if (choice === "Yes") { + await startStandardServer(context, requirements, clientOptions, workspacePath, true /* triggeredByCommand */); + } + }); + + context.subscriptions.push(commands.registerCommand(Commands.CHANGE_JAVA_SEARCH_SCOPE, async () => { + const selection = await window.showQuickPick(["all", "main"], { + canPickMany: false, + placeHolder: `Current: ${workspace.getConfiguration().get("java.search.scope")}`, + }); + if(selection) { + workspace.getConfiguration().update("java.search.scope", selection, false); + } + })); + + context.subscriptions.push(snippetCompletionProvider.initialize()); + context.subscriptions.push(serverStatusBarProvider); + context.subscriptions.push(languageStatusBarProvider); - context.subscriptions.push(commands.registerCommand(Commands.CLEAN_WORKSPACE, () => cleanWorkspace(workspacePath))); + const classEditorProviderRegistration = window.registerCustomEditorProvider(JavaClassEditorProvider.viewType, new JavaClassEditorProvider(context)); + context.subscriptions.push(classEditorProviderRegistration); - context.subscriptions.push(onConfigurationChange()); - toggleItem(window.activeTextEditor, item); + registerClientProviders(context, { contentProviderEvent: jdtEventEmitter.event }); + + apiManager.getApiInstance().onDidServerModeChange((event: ServerMode) => { + if (event === ServerMode.standard) { + syntaxClient.stop(); + fileEventHandler.setServerStatus(true); + languageStatusBarProvider.initialize(context); + } + commands.executeCommand('setContext', 'java:serverMode', event); }); + + if (serverMode === ServerMode.hybrid && !await fse.pathExists(path.join(workspacePath, ".metadata", ".plugins"))) { + const config = getJavaConfiguration(); + const importOnStartupSection: string = "project.importOnFirstTimeStartup"; + const importOnStartup = config.get(importOnStartupSection); + if (importOnStartup === "disabled" || + env.uiKind === UIKind.Web && env.appName.includes("Visual Studio Code")) { + apiManager.getApiInstance().serverMode = ServerMode.lightWeight; + apiManager.fireDidServerModeChange(ServerMode.lightWeight); + requireStandardServer = false; + } else if (importOnStartup === "interactive" && await workspaceContainsBuildFiles()) { + apiManager.getApiInstance().serverMode = ServerMode.lightWeight; + apiManager.fireDidServerModeChange(ServerMode.lightWeight); + requireStandardServer = await promptUserForStandardServer(config); + } else { + requireStandardServer = true; + } + } + + if (requireStandardServer) { + await startStandardServer(context, requirements, clientOptions, workspacePath); + } + + const onDidGrantWorkspaceTrust = (workspace as any).onDidGrantWorkspaceTrust; + if (onDidGrantWorkspaceTrust !== undefined) { // keep compatibility for old engines < 1.56.0 + context.subscriptions.push(onDidGrantWorkspaceTrust(() => { + if (getJavaServerMode() !== ServerMode.lightWeight) { + // See the issue https://github.com/redhat-developer/vscode-java/issues/1994 + // Need to recollect the Java bundles before starting standard mode. + let pollingCount: number = 0; + // Poll every ~100ms (timeout after 1s) and check whether contributing javaExtensions have changed. + const intervalId = setInterval(() => { + const existingJavaExtensions = clientOptions.initializationOptions.bundles; + clientOptions.initializationOptions.bundles = collectJavaExtensions(extensions.all); + if (++pollingCount >= 10 || isContributedPartUpdated(existingJavaExtensions, clientOptions.initializationOptions.bundles)) { + clearInterval(intervalId); + commands.executeCommand(Commands.SWITCH_SERVER_MODE, ServerMode.standard, true); + return; + } + }, 100); + } + })); + } + context.subscriptions.push(workspace.onDidChangeTextDocument(event => handleTextDocumentChanges(event.document, event.contentChanges))); }); }); } -export function deactivate(): Thenable { - if (!languageClient) { - return undefined; +async function startStandardServer(context: ExtensionContext, requirements: requirements.RequirementsData, clientOptions: LanguageClientOptions, workspacePath: string, triggeredByCommand: boolean = false) { + if (standardClient.getClientStatus() !== ClientStatus.uninitialized) { + return; } - return languageClient.stop(); -} - -function enableJavadocSymbols() { - // Let's enable Javadoc symbols autocompletion, shamelessly copied from MIT licensed code at - // https://github.com/Microsoft/vscode/blob/9d611d4dfd5a4a101b5201b8c9e21af97f06e7a7/extensions/typescript/src/typescriptMain.ts#L186 - languages.setLanguageConfiguration('java', { - indentationRules: { - // ^(.*\*/)?\s*\}.*$ - decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/, - // ^.*\{[^}"']*$ - increaseIndentPattern: /^.*\{[^}"']*$/ - }, - wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, - onEnterRules: [ - { - // e.g. /** | */ - beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: ' * ' } - }, - { - // e.g. /** ...| - beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: ' * ' } - }, - { - // e.g. * ...| - beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: IndentAction.None, appendText: '* ' } - }, - { - // e.g. */| - beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 } - }, - { - // e.g. *-----*/| - beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 } + + const selector: BuildFileSelector = new BuildFileSelector(context, []); + const importMode: ImportMode = await getImportMode(context, selector); + if (importMode === ImportMode.automatic) { + if (!await ensureNoBuildToolConflicts(context, clientOptions)) { + return; + } + } else { + const buildFiles: string[] = []; + if (importMode === ImportMode.manual) { + const cache = context.workspaceState.get(PICKED_BUILD_FILES); + if (cache === undefined || cache.length === 0 && triggeredByCommand) { + buildFiles.push(...await selector.selectBuildFiles() || []); + } else { + buildFiles.push(...cache); } - ] - }); -} + } + if (buildFiles.length === 0) { + commands.executeCommand('setContext', 'java:serverMode', ServerMode.lightWeight); + serverStatusBarProvider.showNotImportedStatus(); + return; + } + clientOptions.initializationOptions.projectConfigurations = buildFiles; + } -function logNotification(message: string, ...items: string[]) { - return new Promise((resolve, reject) => { - console.log(message); + if (apiManager.getApiInstance().serverMode === ServerMode.lightWeight) { + // Before standard server is ready, we are in hybrid. + apiManager.getApiInstance().serverMode = ServerMode.hybrid; + apiManager.fireDidServerModeChange(ServerMode.hybrid); + } + await standardClient.initialize(context, requirements, clientOptions, workspacePath, jdtEventEmitter); + standardClient.start().then(async () => { + standardClient.registerLanguageClientActions(context, await fse.pathExists(path.join(workspacePath, ".metadata", ".plugins")), jdtEventEmitter); }); + serverStatusBarProvider.setBusy("Activating..."); } -function setIncompleteClasspathSeverity(severity: string) { - const config = getJavaConfiguration(); - const section = 'errors.incompleteClasspath.severity'; - config.update(section, severity, true).then( - () => console.log(`${section} globally set to ${severity}`), - (error) => console.log(error) - ); +async function workspaceContainsBuildFiles(): Promise { + // Since the VS Code API does not support put negated exclusion pattern in findFiles(), we need to first parse the + // negated exclusion to inclusion and do the search. (If negated exclusion pattern is set by user) + const inclusionPatterns: string[] = getBuildFilePatterns(); + const inclusionPatternsFromNegatedExclusion: string[] = getInclusionPatternsFromNegatedExclusion(); + if (inclusionPatterns.length > 0 && inclusionPatternsFromNegatedExclusion.length > 0 && + (await workspace.findFiles(convertToGlob(inclusionPatterns, inclusionPatternsFromNegatedExclusion), null, 1 /* maxResults */)).length > 0) { + return true; + } + + // Nothing found in negated exclusion pattern, do a normal search then. + const inclusionGlob: string = convertToGlob(inclusionPatterns); + const exclusionGlob: string = getExclusionGlob(); + if (inclusionGlob && (await workspace.findFiles(inclusionGlob, exclusionGlob, 1 /* maxResults */)).length > 0) { + return true; + } + + return false; } -function projectConfigurationUpdate(languageClient: LanguageClient, uri?: Uri) { - let resource = uri; - if (!(resource instanceof Uri)) { - if (window.activeTextEditor) { - resource = window.activeTextEditor.document.uri; +async function ensureNoBuildToolConflicts(context: ExtensionContext, clientOptions: LanguageClientOptions): Promise { + const isMavenEnabled: boolean = getJavaConfiguration().get("import.maven.enabled"); + const isGradleEnabled: boolean = getJavaConfiguration().get("import.gradle.enabled"); + if (isMavenEnabled && isGradleEnabled) { + let activeBuildTool: string | undefined = context.workspaceState.get(ACTIVE_BUILD_TOOL_STATE); + if (!activeBuildTool) { + if (!await hasBuildToolConflicts()) { + return true; + } + activeBuildTool = await window.showInformationMessage("Build tool conflicts are detected in workspace. Which one would you like to use?", "Use Maven", "Use Gradle"); + } + + if (!activeBuildTool) { + return false; // user cancels + } else if (activeBuildTool.toLocaleLowerCase().includes("maven")) { + // Here we do not persist it in the settings to avoid generating/updating files in user's workspace + // Later if user want to change the active build tool, just directly set the related settings. + clientOptions.initializationOptions.settings.java.import.gradle.enabled = false; + context.workspaceState.update(ACTIVE_BUILD_TOOL_STATE, "maven"); + } else if (activeBuildTool.toLocaleLowerCase().includes("gradle")) { + clientOptions.initializationOptions.settings.java.import.maven.enabled = false; + context.workspaceState.update(ACTIVE_BUILD_TOOL_STATE, "gradle"); + } else { + throw new Error(`Unknown build tool: ${activeBuildTool}`); // unreachable } } - if (!resource) { - return window.showWarningMessage('No Java project to update!').then(() => false); - } - if (isJavaConfigFile(resource.path)) { - languageClient.sendNotification(ProjectConfigurationUpdateRequest.type, { - uri: resource.toString() - }); - } -} -function setProjectConfigurationUpdate(languageClient: LanguageClient, uri: Uri, status: FeatureStatus) { - const config = getJavaConfiguration(); - const section = 'configuration.updateBuildConfiguration'; + return true; +} - const st = FeatureStatus[status]; - config.update(section, st).then( - () => console.log(`${section} set to ${st}`), - (error) => console.log(error) - ); - if (status !== FeatureStatus.disabled) { - projectConfigurationUpdate(languageClient, uri); +async function promptUserForStandardServer(config: WorkspaceConfiguration): Promise { + const choice: string = await window.showInformationMessage("The workspace contains Java projects. Would you like to import them?", "Yes", "Always", "Later"); + switch (choice) { + case "Always": + await config.update("project.importOnFirstTimeStartup", "automatic", ConfigurationTarget.Global); + return true; + case "Yes": + return true; + case "Later": + default: + const importHintSection: string = "project.importHint"; + const dontShowAgain: string = "Don't Show Again"; + const showHint: boolean = config.get(importHintSection); + if (showHint && standardClient.getClientStatus() === ClientStatus.uninitialized) { + const showRocketEmoji: boolean = process.platform === "win32" || process.platform === "darwin"; + const message: string = `Java Language Server is running in LightWeight mode. Click the ${showRocketEmoji ? '🚀' : 'Rocket'} icon in the status bar if you want to import the projects later.`; + window.showInformationMessage(message, dontShowAgain) + .then(selection => { + if (selection && selection === dontShowAgain) { + config.update(importHintSection, false, ConfigurationTarget.Global); + } + }); + } + return false; } } -function toggleItem(editor: TextEditor, item) { - if (editor && editor.document && - (editor.document.languageId === 'java' || isJavaConfigFile(editor.document.uri.path))) { - item.show(); + +export function deactivate(): Promise { + return Promise.all([ + standardClient.stop(), + syntaxClient.stop(), + ]); +} + +export async function getActiveLanguageClient(): Promise { + let languageClient: LanguageClient; + + const api: ExtensionAPI = apiManager.getApiInstance(); + if (api.serverMode === ServerMode.standard) { + languageClient = standardClient.getClient(); } else { - item.hide(); + languageClient = syntaxClient.getClient(); + } + + if (!languageClient) { + return undefined; } -} -function isJavaConfigFile(path: String) { - return path.endsWith('pom.xml') || path.endsWith('.gradle'); + if (languageClient.needsStart()) { + await languageClient.start(); + } + + return languageClient; } -function getTempWorkspace() { - return path.resolve(os.tmpdir(), 'vscodesws_' + makeRandomHexString(5)); + +export function getTempWorkspace() { + return path.resolve(os.tmpdir(), `vscodesws_${makeRandomHexString(5)}`); } function makeRandomHexString(length) { @@ -460,49 +864,119 @@ function makeRandomHexString(length) { return result; } -async function cleanWorkspace(workspacePath) { - const doIt = 'Restart and delete'; - window.showWarningMessage('Are you sure you want to clean the Java language server workspace?', 'Cancel', doIt).then(selection => { - if (selection === doIt) { - const file = path.join(workspacePath, cleanWorkspaceFileName); - fs.closeSync(fs.openSync(file, 'w')); - commands.executeCommand(Commands.RELOAD_WINDOW); +async function cleanWorkspace(workspacePath, force?: boolean) { + if (!force) { + const doIt = 'Reload and delete'; + const selection = await window.showWarningMessage('Are you sure you want to clean the Java language server workspace?', 'Cancel', doIt); + if (selection !== doIt) { + return; } - }); + } + ensureExists(workspacePath); + const file = path.join(workspacePath, cleanWorkspaceFileName); + fs.closeSync(fs.openSync(file, 'w')); + commands.executeCommand(Commands.RELOAD_WINDOW); } -function deleteDirectory(dir) { - if (fs.existsSync(dir)) { - fs.readdirSync(dir).forEach((child) => { - const entry = path.join(dir, child); - if (fs.lstatSync(entry).isDirectory()) { - deleteDirectory(entry); - } else { - fs.unlinkSync(entry); - } - }); - fs.rmdirSync(dir); +async function cleanSharedIndexes(context: ExtensionContext) { + const sharedIndexLocation: string = getSharedIndexCache(context); + if (sharedIndexLocation && fs.existsSync(sharedIndexLocation)) { + const doIt = 'Clean and Reload'; + const ans = await window.showWarningMessage('The shared indexes might be in use by other workspaces, do you want to clear it? New indexes will be built after reloading.', + doIt, "Cancel"); + if (ans === doIt) { + deleteDirectory(sharedIndexLocation); + commands.executeCommand(Commands.RELOAD_WINDOW); + } } } -function openServerLogFile(workspacePath): Thenable { +function openServerLogFile(storagePath, column: ViewColumn = ViewColumn.Active): Thenable { + const workspacePath = computeWorkspacePath(storagePath); const serverLogFile = path.join(workspacePath, '.metadata', '.log'); - if (!fs.existsSync(serverLogFile)) { - return window.showWarningMessage('Java Language Server has not started logging.').then(() => false); + return openLogFile(serverLogFile, 'Could not open Java Language Server log file', column); +} + +function computeWorkspacePath(storagePath: any) { + return path.join(storagePath, apiManager.getApiInstance().serverMode === ServerMode.lightWeight ? 'ss_ws' : 'jdt_ws'); +} + +export function getWorkspacePath() { + return computeWorkspacePath(storagePath); +} + +async function openRollingServerLogFile(storagePath, filename, column: ViewColumn = ViewColumn.Active): Promise { + const workspacePath = computeWorkspacePath(storagePath); + const dirname = path.join(workspacePath, '.metadata'); + + try { + // find out the newest one + const files = await glob(`${filename}-*`, { cwd: dirname }); + if (files.length > 0) { + files.sort(); + + const logFile = path.join(dirname, files[files.length - 1]); + return await openLogFile(logFile, `Could not open Java Language Server log file ${filename}`, column); + } + } catch (err) { + console.error("Error opening rolling server log file", err); } + return false; +} + +async function openClientLogFile(logFile: string, column: ViewColumn = ViewColumn.Active): Promise { + const filename = path.basename(logFile); + const dirname = path.dirname(logFile); - return workspace.openTextDocument(serverLogFile) + try { + // find out the newest one + const files = await glob(`${filename}.*`, { cwd: dirname }); + if (files.length > 0) { + files.sort((a, b) => { + const dateA = a.slice(11, 21), dateB = b.slice(11, 21); + if (dateA === dateB) { + if (a.length > 22 && b.length > 22) { + const extA = a.slice(22), extB = b.slice(22); + return parseInt(extA) - parseInt(extB); + } + return a.length - b.length; + } + return dateA < dateB ? -1 : 1; + }); + logFile = path.join(dirname, files[files.length - 1]); + } + + } catch (err) { + console.error("Error opening client log file", err); + } + return await openLogFile(logFile, 'Could not open Java extension log file', column); +} + +async function openLogs() { + await commands.executeCommand(Commands.OPEN_CLIENT_LOG, ViewColumn.One); + await commands.executeCommand(Commands.OPEN_SERVER_LOG, ViewColumn.One); + await commands.executeCommand(Commands.OPEN_SERVER_STDOUT_LOG, ViewColumn.One); + await commands.executeCommand(Commands.OPEN_SERVER_STDERR_LOG, ViewColumn.One); + const client = await getActiveLanguageClient(); + client?.outputChannel.show(true); +} + +function openLogFile(logFile, openingFailureWarning: string, column: ViewColumn = ViewColumn.Active): Thenable { + if (!fs.existsSync(logFile)) { + return window.showWarningMessage('No log file available').then(() => false); + } + + return workspace.openTextDocument(logFile) .then(doc => { if (!doc) { return false; } - return window.showTextDocument(doc, window.activeTextEditor ? - window.activeTextEditor.viewColumn : undefined) + return window.showTextDocument(doc, { viewColumn: column, preview: false }) .then(editor => !!editor); }, () => false) .then(didOpen => { if (!didOpen) { - window.showWarningMessage('Could not open Java Language Server log file'); + window.showWarningMessage(openingFailureWarning); } return didOpen; }); @@ -513,7 +987,7 @@ async function openFormatter(extensionPath) { const formatterUrl: string = getJavaConfiguration().get('format.settings.url'); if (formatterUrl && formatterUrl.length > 0) { if (isRemote(formatterUrl)) { - commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse(formatterUrl)); + return commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse(formatterUrl)); } else { const document = getPath(formatterUrl); if (document && fs.existsSync(document)) { @@ -530,9 +1004,7 @@ async function openFormatter(extensionPath) { relativePath = fileName; } else { const root = path.join(extensionPath, '..', 'redhat.java'); - if (!fs.existsSync(root)) { - fs.mkdirSync(root); - } + ensureExists(root); file = path.join(root, fileName); } if (!fs.existsSync(file)) { @@ -582,7 +1054,7 @@ function openDocument(extensionPath, formatterUrl, defaultFormatter, relativePat } function isRemote(f) { - return f !== null && f.startsWith('http:/') || f.startsWith('https:/'); + return f !== null && f.startsWith('http:/') || f.startsWith('https:/') || f.startsWith('file:/'); } async function addFormatter(extensionPath, formatterUrl, defaultFormatter, relativePath) { @@ -605,9 +1077,7 @@ async function addFormatter(extensionPath, formatterUrl, defaultFormatter, relat relativePath = fileName; } else { const root = path.join(extensionPath, '..', 'redhat.java'); - if (!fs.existsSync(root)) { - fs.mkdirSync(root); - } + ensureExists(root); f = path.join(root, fileName); } } else { @@ -620,9 +1090,14 @@ async function addFormatter(extensionPath, formatterUrl, defaultFormatter, relat const action = 'Yes'; window.showWarningMessage(msg, action, 'No').then((selection) => { if (action === selection) { - fs.createReadStream(defaultFormatter) - .pipe(fs.createWriteStream(f)) - .on('finish', () => openDocument(extensionPath, f, defaultFormatter, relativePath)); + try { + ensureExists(path.dirname(f)); + fs.createReadStream(defaultFormatter) + .pipe(fs.createWriteStream(f)) + .on('finish', () => openDocument(extensionPath, f, defaultFormatter, relativePath)); + } catch (error) { + window.showErrorMessage(`Failed to create ${f}: ${error}`); + } } }); } else { @@ -633,51 +1108,9 @@ async function addFormatter(extensionPath, formatterUrl, defaultFormatter, relat }); } -export async function applyWorkspaceEdit(obj, languageClient) { - const edit = languageClient.protocol2CodeConverter.asWorkspaceEdit(obj); - if (edit) { - await workspace.applyEdit(edit); - // By executing the range formatting command to correct the indention according to the VS Code editor settings. - // More details, see: https://github.com/redhat-developer/vscode-java/issues/557 - try { - const currentEditor = window.activeTextEditor; - // If the Uri path of the edit change is not equal to that of the active editor, we will skip the range formatting - if (currentEditor.document.uri.fsPath !== edit.entries()[0][0].fsPath) { - return; - } - const cursorPostion = currentEditor.selection.active; - // Get the array of all the changes - const changes = edit.entries()[0][1]; - // Get the position information of the first change - let startPosition = new Position(changes[0].range.start.line, changes[0].range.start.character); - let lineOffsets = changes[0].newText.split(/\r?\n/).length - 1; - for (let i = 1; i < changes.length; i++) { - // When it comes to a discontinuous range, execute the range formatting and record the new start position - if (changes[i].range.start.line !== startPosition.line) { - await executeRangeFormat(currentEditor, startPosition, lineOffsets); - startPosition = new Position(changes[i].range.start.line, changes[i].range.start.character); - lineOffsets = 0; - } - lineOffsets += changes[i].newText.split(/\r?\n/).length - 1; - } - await executeRangeFormat(currentEditor, startPosition, lineOffsets); - // Recover the cursor's original position - currentEditor.selection = new Selection(cursorPostion, cursorPostion); - } catch (error) { - languageClient.error(error); - } - } -} - -async function executeRangeFormat(editor, startPosition, lineOffset) { - const endPosition = editor.document.positionAt(editor.document.offsetAt(new Position(startPosition.line + lineOffset + 1, 0)) - 1); - editor.selection = new Selection(startPosition, endPosition); - await commands.executeCommand('editor.action.formatSelection'); -} - -function getTriggerFiles(): string[] { +async function getTriggerFiles(): Promise { const openedJavaFiles = []; - const activeJavaFile = getJavaFilePathOfTextEditor(window.activeTextEditor); + const activeJavaFile = getJavaFilePathOfTextDocument(window.activeTextEditor && window.activeTextEditor.document); if (activeJavaFile) { openedJavaFiles.push(Uri.file(activeJavaFile).toString()); } @@ -686,32 +1119,58 @@ function getTriggerFiles(): string[] { return openedJavaFiles; } - for (const rootFolder of workspace.workspaceFolders) { + await Promise.all(workspace.workspaceFolders.map(async (rootFolder) => { if (rootFolder.uri.scheme !== 'file') { - continue; + return; } const rootPath = path.normalize(rootFolder.uri.fsPath); if (isPrefix(rootPath, activeJavaFile)) { - continue; + return; } for (const textEditor of window.visibleTextEditors) { - const javaFileInTextEditor = getJavaFilePathOfTextEditor(textEditor); + const javaFileInTextEditor = getJavaFilePathOfTextDocument(textEditor.document); if (isPrefix(rootPath, javaFileInTextEditor)) { openedJavaFiles.push(Uri.file(javaFileInTextEditor).toString()); - break; + return; + } + } + + for (const textDocument of workspace.textDocuments) { + const javaFileInTextDocument = getJavaFilePathOfTextDocument(textDocument); + if (isPrefix(rootPath, javaFileInTextDocument)) { + openedJavaFiles.push(Uri.file(javaFileInTextDocument).toString()); + return; } } - } + + // Paths set by 'java.import.exclusions' will be ignored when searching trigger files. + const exclusionGlob = getExclusionGlob(); + const javaFilesUnderRoot: Uri[] = await workspace.findFiles(new RelativePattern(rootFolder, "*.java"), exclusionGlob, 1); + for (const javaFile of javaFilesUnderRoot) { + if (isPrefix(rootPath, javaFile.fsPath)) { + openedJavaFiles.push(javaFile.toString()); + return; + } + } + + const javaFilesInCommonPlaces: Uri[] = await workspace.findFiles(new RelativePattern(rootFolder, "{src, test}/**/*.java"), exclusionGlob, 1); + for (const javaFile of javaFilesInCommonPlaces) { + if (isPrefix(rootPath, javaFile.fsPath)) { + openedJavaFiles.push(javaFile.toString()); + return; + } + } + })); return openedJavaFiles; } -function getJavaFilePathOfTextEditor(editor: TextEditor): string | undefined { - if (editor) { - const resource = editor.document.uri; - if (resource.scheme === 'file' && resource.fsPath.endsWith('.java')) { +function getJavaFilePathOfTextDocument(document: TextDocument): string | undefined { + if (document) { + const resource = document.uri; + if (resource.scheme === 'file' && document.languageId === "java") { return path.normalize(resource.fsPath); } } @@ -726,3 +1185,126 @@ function isPrefix(parentPath: string, childPath: string): boolean { const relative = path.relative(parentPath, childPath); return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative); } + +async function cleanJavaWorkspaceStorage() { + const configCacheLimit = getJavaConfiguration().get("configuration.workspaceCacheLimit"); + + // Also leave temporary workspaces alone as they should have their own policy + if (!storagePath || !configCacheLimit || storagePath.includes('vscodesws')) { + return; + } + + const limit: number = configCacheLimit * 86400000; // days to ms + const currTime = new Date().valueOf(); // ms since Epoch + // storage path is Code/User/workspaceStorage/${id}/redhat.java/ + const wsRoot = path.dirname(path.dirname(storagePath)); + + // find all folders of the form "redhat.java/jdt_ws/" and delete "redhat.java/" + if (fs.existsSync(wsRoot)) { + try { + const matches = await glob(`${wsRoot}/**/jdt_ws`); + for (const javaWSCache of matches) { + const entry = path.dirname(javaWSCache); + const entryModTime = fs.statSync(entry).mtimeMs; + if ((currTime - entryModTime) > limit) { + logger.info(`Removing workspace storage folder : ${entry}`); + deleteDirectory(entry); + } + } + } catch (err) { + logger.error('Error cleaning workspace storage:', err); + } + } +} + +async function cleanOldGlobalStorage(context: ExtensionContext) { + const currentVersion = getVersion(context.extensionPath); + const globalStoragePath = context.globalStorageUri?.fsPath; // .../Code/User/globalStorage/redhat.java + + ensureExists(globalStoragePath); + + // delete folders in .../User/globalStorage/redhat.java that are not named the current version + fs.promises.readdir(globalStoragePath).then(async (files) => { + await Promise.all(files.map(async (file) => { + const currentPath = path.join(globalStoragePath, file); + const stat = await fs.promises.stat(currentPath); + + if (stat.isDirectory() && file !== currentVersion) { + logger.info(`Removing old folder in globalStorage : ${file}`); + deleteDirectory(currentPath); + } + })); + }); +} + +export function registerCodeCompletionTelemetryListener() { + apiManager.getApiInstance().onDidRequestEnd((traceEvent: TraceEvent) => { + if (traceEvent.type === CompletionRequest.method) { + // Exclude the invalid completion requests. + if (!traceEvent.resultLength) { + return; + } + const props = { + duration: Math.round(traceEvent.duration * 100) / 100, + resultLength: traceEvent.resultLength || 0, + error: !!traceEvent.error, + fromSyntaxServer: !!traceEvent.fromSyntaxServer, + engine: getJavaConfiguration().get('completion.engine'), + }; + return Telemetry.sendTelemetry(Telemetry.COMPLETION_EVENT, props); + } + }); +} + +function registerOutOfMemoryDetection(storagePath: string) { + const heapDumpFolder = getHeapDumpFolderFromSettings() || storagePath; + chokidar.watch(`${heapDumpFolder}/java_*.hprof`, { ignoreInitial: true }).on('add', path => { + // Only clean heap dumps that are generated in the default location. + // The default location is the extension global storage + // This means that if users change the folder where the heap dumps are placed, + // then they will be able to read the heap dumps, + // since they aren't immediately deleted. + if (heapDumpFolder === storagePath) { + fse.remove(path); + } + apiManager.fireTraceEvent({ + name: "java.process.outofmemory", + properties: { + maxMem: getMaxMemFromConfiguration(true), + } + }); + Telemetry.sendTelemetry("java.process.outofmemory", { + maxMem: getMaxMemFromConfiguration(true), + }); + showOOMMessage(); + serverStatusBarProvider.setError(); + activationProgressNotification.hide(); + }); +} + +function registerRestartJavaLanguageServerCommand(context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand(Commands.RESTART_LANGUAGE_SERVER, async () => { + switch (getJavaServerMode()) { + case (ServerMode.standard): + // Standard server restart + await standardClient.getClient().restart(); + break; + case (ServerMode.lightWeight): + // Syntax server restart + await syntaxClient.getClient().restart(); + break; + case (ServerMode.hybrid): + if (syntaxClient.isAlive()) { + await syntaxClient.getClient().restart(); + } + await standardClient.getClient().restart(); + break; + } + })); +} + +function escapeSnippetLiterals(value: string): string { + return value + .replace(/\\/g, '\\\\') // Escape backslashes + .replace(/\$(?!\{)/g, '\\$'); // Escape $ only if NOT followed by { +} diff --git a/src/fileEventHandler.ts b/src/fileEventHandler.ts new file mode 100644 index 0000000000..03e950b5a8 --- /dev/null +++ b/src/fileEventHandler.ts @@ -0,0 +1,341 @@ +'use strict'; + +import { lstatSync } from 'fs-extra'; +import * as path from 'path'; +import { workspace, FileCreateEvent, ExtensionContext, window, TextDocument, SnippetString, commands, Uri, FileRenameEvent, ProgressLocation, WorkspaceEdit as CodeWorkspaceEdit, FileWillRenameEvent, Position, FileType, ConfigurationTarget, Disposable } from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { ListCommandResult } from './buildpath'; +import { Commands } from './commands'; +import { WillRenameFiles } from './protocol'; +import { getJavaConfiguration } from './utils'; +import { userInfo } from 'os'; +import * as stringInterpolate from 'fmtr'; +import { apiManager } from './apiManager'; + +let serverReady: boolean = false; + +const BRACE_POSITION_KEY = "org.eclipse.jdt.core.formatter.brace_position_for_type_declaration"; +const END_OF_LINE = "end_of_line"; +const NEXT_LINE = "next_line"; +const NEXT_LINE_SHIFTED = "next_line_shifted"; + + +export function setServerStatus(ready: boolean) { + serverReady = ready; +} + +export function registerFileEventHandlers(client: LanguageClient, context: ExtensionContext) { + if (workspace.onDidCreateFiles) {// Theia doesn't support workspace.onDidCreateFiles yet + context.subscriptions.push(workspace.onDidCreateFiles(handleNewJavaFiles)); + } + + if (workspace.onWillRenameFiles) { + context.subscriptions.push(workspace.onWillRenameFiles(getWillRenameHandler(client))); + } + + // extension activated and empty Java file is in active editor ? + // type declaration snippet handler activated too late so adjust the file here + apiManager.getApiInstance().serverReady().then(async () => { + const te = window.activeTextEditor?.document; + if (te && te.getText().trim().length === 0) { + setServerStatus(true); + handleNewJavaFiles({ + files: [te.uri] + }); + } + }); +} + +async function handleNewJavaFiles(e: FileCreateEvent) { + if (!getJavaConfiguration().get('templates.newFile.enabled', true)) { + return; + } + const emptyFiles: Uri[] = []; + const textDocuments: TextDocument[] = []; + for (const uri of e.files) { + if (!isJavaFile(uri)) { + continue; + } + + const textDocument = await workspace.openTextDocument(uri); + if (textDocument.getText()) { // ignore the non-empty files + continue; + } + + emptyFiles.push(uri); + textDocuments.push(textDocument); + } + + if (!emptyFiles.length) { + return; + } + + let sourcePaths: string[] = []; + if (serverReady) { + const result: ListCommandResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.LIST_SOURCEPATHS); + if (result && result.data && result.data.length) { + sourcePaths = result.data.map((sourcePath) => sourcePath.path).sort((a, b) => b.length - a.length); + } + } + + // See https://github.com/redhat-developer/vscode-java/issues/2939 + // The client side listener should avoid inserting duplicated contents + // when the file creation event is triggered from a WorkspaceEdit. + // Given that the VS Code API doesn't provide a way to distinguish + // the event source, a workaround is to wait 100ms and let WorkspaceEdit + // to take effect first, then check if the workingcopy is filled with content. + const timeout = setTimeout(async() => { + const editorConfig = workspace.getConfiguration('editor'); + const insertSpaces = editorConfig.get('insertSpaces', true); + const tabSize = editorConfig.get('tabSize', 4); + const indent = insertSpaces ? ' '.repeat(tabSize) : '\t'; + + const projectSetting: {} = await commands.executeCommand<{}>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_PROJECT_SETTINGS, emptyFiles[0].toString(), [BRACE_POSITION_KEY]); + projectSetting[BRACE_POSITION_KEY] = projectSetting[BRACE_POSITION_KEY] || END_OF_LINE; + + const formatNumber = (num => num > 9 ? String(num) : `0${num}`); + for (let i = 0; i < emptyFiles.length; i++) { + if (textDocuments[i].getText()) { + continue; + } + + const typeName: string = resolveTypeName(textDocuments[i].fileName); + const isPackageInfo = typeName === 'package-info'; + const isModuleInfo = typeName === 'module-info'; + const date = new Date(); + const context: any = { + fileName: path.basename(textDocuments[i].fileName), + packageName: "", + typeName: typeName, + user: userInfo().username, + date: date.toLocaleDateString(undefined, {month: "short", day: "2-digit", year: "numeric"}), + time: date.toLocaleTimeString(), + year: date.getFullYear(), + month: formatNumber(date.getMonth() + 1), + shortmonth: date.toLocaleDateString(undefined, {month: "short"}), + day: formatNumber(date.getDate()), + hour: formatNumber(date.getHours()), + minute: formatNumber(date.getMinutes()), + }; + + if (!isModuleInfo) { + context.packageName = resolvePackageName(sourcePaths, emptyFiles[i].fsPath); + } + + const snippets: string[] = []; + const fileHeader = getJavaConfiguration().get("templates.fileHeader"); + if (fileHeader && fileHeader.length) { + for (const template of fileHeader) { + snippets.push(stringInterpolate(template, context)); + } + } + + if (!isModuleInfo) { + if (context.packageName) { + snippets.push(`package ${context.packageName};`); + snippets.push(""); + } + } + if (!isPackageInfo) { + const typeComment = getJavaConfiguration().get("templates.typeComment"); + if (typeComment && typeComment.length) { + for (const template of typeComment) { + snippets.push(stringInterpolate(template, context)); + } + } + let declaration: string; + if (isModuleInfo) { + declaration = `module \${1:name}`; + } else if (!serverReady || await isVersionLessThan(emptyFiles[i].toString(), 14)) { + declaration = `public \${1|class,interface,enum,abstract class,@interface|} ${typeName}`; + } else { + declaration = `public \${1|class ${typeName},interface ${typeName},enum ${typeName},record ${typeName}(),abstract class ${typeName},@interface ${typeName}|}`; + } + let bracePosition = projectSetting[BRACE_POSITION_KEY]; + if (bracePosition !== END_OF_LINE && bracePosition !== NEXT_LINE && bracePosition !== NEXT_LINE_SHIFTED) { + bracePosition = END_OF_LINE; + } + + let body = `${indent}\${0}`; + if (bracePosition === END_OF_LINE) { + snippets.push(`${declaration} {`); + } else if (bracePosition === NEXT_LINE) { + snippets.push(`${declaration}`); + snippets.push("{"); + } else if (bracePosition === NEXT_LINE_SHIFTED) { + snippets.push(declaration); + snippets.push(`${indent}{`); + body = `${indent}${body}`; + } + snippets.push(body); + if (bracePosition === NEXT_LINE_SHIFTED) { + snippets.push(`${indent}}`); + } else { + snippets.push("}"); + } + + snippets.push(""); + } + const textEditor = await window.showTextDocument(textDocuments[i]); + if (textDocuments[i].getText()) { + continue; + } + + textEditor.insertSnippet(new SnippetString(snippets.join("\n"))); + } + + clearTimeout(timeout); + }, 100); +} + +function getWillRenameHandler(client: LanguageClient) { + return function handleWillRenameFiles(e: FileWillRenameEvent): void { + if (!serverReady) { + return; + } + + e.waitUntil(new Promise(async (resolve, reject) => { + try { + const javaRenameEvents: Array<{ oldUri: string; newUri: string }> = []; + for (const file of e.files) { + if (await isJavaFileWillRename(file.oldUri, file.newUri) + || await isFolderWillRename(file.oldUri, file.newUri) + || await isJavaWillMove(file.oldUri, file.newUri)) { + javaRenameEvents.push({ + oldUri: file.oldUri.toString(), + newUri: file.newUri.toString(), + }); + } + } + + if (!javaRenameEvents.length) { + resolve(undefined); + return; + } + + const edit = await client.sendRequest(WillRenameFiles.type, { + files: javaRenameEvents + }); + resolve(await client.protocol2CodeConverter.asWorkspaceEdit(edit)); + } catch (ex) { + reject(ex); + } + })); + }; +} + +function isJavaFile(uri: Uri): boolean { + if (uri.fsPath && uri.fsPath.endsWith(".java")) { + return true; + } + let result = false; + const associations = workspace.getConfiguration().get("files.associations"); + if (associations !== null) { + Object.keys(associations).forEach(pattern => { + const langId = associations[pattern]; + if (langId === 'java' && pattern.startsWith('*.') && pattern.length > 2) { + const ext = pattern.substring(2); + if (!ext.includes('?') && !ext.includes('*')) { + if (uri.fsPath && uri.fsPath.endsWith(`.${ext}`)) { + result = true; + } + } + } + }); + } + return result; +} + +async function isFile(uri: Uri): Promise { + try { + return (await workspace.fs.stat(uri)).type === FileType.File; + } catch { + return lstatSync(uri.fsPath).isFile(); + } +} + +async function isDirectory(uri: Uri): Promise { + try { + return (await workspace.fs.stat(uri)).type === FileType.Directory; + } catch { + return lstatSync(uri.fsPath).isDirectory(); + } +} + +async function isJavaFileWillRename(oldUri: Uri, newUri: Uri): Promise { + if (isInSameDirectory(oldUri, newUri)) { + return await isFile(oldUri) && isJavaFile(oldUri) && isJavaFile(newUri); + } + + return false; +} + +async function isFolderWillRename(oldUri: Uri, newUri: Uri): Promise { + return await isDirectory(oldUri); +} + +async function isJavaWillMove(oldUri: Uri, newUri: Uri): Promise { + return await isFile(oldUri) && isJavaFile(oldUri) && isJavaFile(newUri) + && !isInSameDirectory(oldUri, newUri); +} + +function isInSameDirectory(oldUri: Uri, newUri: Uri): boolean { + const oldDir = path.dirname(oldUri.fsPath); + const newDir = path.dirname(newUri.fsPath); + return !path.relative(oldDir, newDir); +} + +function resolveTypeName(filePath: string): string { + const fileName: string = path.basename(filePath); + const extName: string = path.extname(fileName); + return fileName.substring(0, fileName.length - extName.length); +} + +function resolvePackageName(sourcePaths: string[], filePath: string): string { + if (!sourcePaths || !sourcePaths.length) { + return ""; + } + + for (const sourcePath of sourcePaths) { + if (isPrefix(sourcePath, filePath)) { + const relative = path.relative(sourcePath, path.dirname(filePath)); + return relative.replace(/[\/\\]/g, "."); + } + } + + return ""; +} + +function isPrefix(parentPath: string, filePath: string): boolean { + const relative = path.relative(parentPath, filePath); + return !relative || (!relative.startsWith('..') && !path.isAbsolute(relative)); +} + +const COMPLIANCE = "org.eclipse.jdt.core.compiler.compliance"; +async function isVersionLessThan(fileUri: string, targetVersion: number): Promise { + let projectSettings = {}; + try { + projectSettings = await commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_PROJECT_SETTINGS, fileUri, [ COMPLIANCE ]); + } catch (err) { + // do nothing. + } + + let javaVersion = 0; + let complianceVersion = projectSettings[COMPLIANCE]; + if (complianceVersion) { + // Ignore '1.' prefix for legacy Java versions + if (complianceVersion.startsWith('1.')) { + complianceVersion = complianceVersion.substring(2); + } + + // look into the interesting bits now + const regexp = /\d+/g; + const match = regexp.exec(complianceVersion); + if (match) { + javaVersion = parseInt(match[0]); + } + } + + return javaVersion < targetVersion; +} diff --git a/src/goToDefinition.ts b/src/goToDefinition.ts new file mode 100644 index 0000000000..b026eb7f7d --- /dev/null +++ b/src/goToDefinition.ts @@ -0,0 +1,27 @@ +'use strict'; + +import { + CancellationToken, DefinitionParams, + DefinitionRequest, Location, + LocationLink +} from 'vscode-languageclient'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { getActiveLanguageClient } from './extension'; + +type GoToDefinitionResponse = Location | Location[] | LocationLink[] | null; + +export type GoToDefinitionCommand = (params: DefinitionParams, token?: CancellationToken) => Promise; + +export function goToDefinitionProvider(): GoToDefinitionCommand { + return async (params: DefinitionParams, token?: CancellationToken): Promise => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + if (!languageClient) { + return null; + } + + if (token !== undefined) { + return languageClient.sendRequest(DefinitionRequest.type, params, token); + } + return languageClient.sendRequest(DefinitionRequest.type, params); + }; +} \ No newline at end of file diff --git a/src/gradle/gradleCodeActionProvider.ts b/src/gradle/gradleCodeActionProvider.ts new file mode 100644 index 0000000000..d09af47046 --- /dev/null +++ b/src/gradle/gradleCodeActionProvider.ts @@ -0,0 +1,61 @@ +'use strict'; + +import * as fse from "fs-extra"; +import * as path from "path"; +import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, CodeActionProviderMetadata, Command, commands, Diagnostic, DiagnosticRelatedInformation, ExtensionContext, ProviderResult, Range, Selection, TextDocument, Uri } from "vscode"; +import { Commands } from "../commands"; +import { upgradeGradle } from "../standardLanguageClientUtils"; + +const UPGRADE_GRADLE_WRAPPER_TITLE = "Upgrade Gradle Wrapper"; +const WRAPPER_PROPERTIES_DESCRIPTOR = "gradle/wrapper/gradle-wrapper.properties"; +const GRADLE_PROBLEM_ID = 0x00080000; +const GRADLE_INVALID_TYPE_CODE_ID = GRADLE_PROBLEM_ID + 1; + +export class GradleCodeActionProvider implements CodeActionProvider { + + public provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(CodeAction | Command)[]> { + if (context?.diagnostics?.length && context.diagnostics[0].source === "Java") { + return this.provideGradleCodeActions(document, context.diagnostics); + } + return []; + } + + async provideGradleCodeActions(document: TextDocument, diagnostics: readonly Diagnostic[]): Promise { + const codeActions = []; + for (const diagnostic of diagnostics) { + if (diagnostic.message?.startsWith("The build file has been changed")) { + const reloadProjectAction = new CodeAction("Reload project", CodeActionKind.QuickFix); + reloadProjectAction.command = { + title: "Reload Project", + command: Commands.CONFIGURATION_UPDATE, + arguments: [document.uri], + }; + codeActions.push(reloadProjectAction); + continue; + } + + const documentUri = document.uri.toString(); + if (documentUri.endsWith(WRAPPER_PROPERTIES_DESCRIPTOR) && diagnostic.code === GRADLE_INVALID_TYPE_CODE_ID.toString()) { + const projectPath = path.resolve(Uri.parse(documentUri).fsPath, "..", "..", "..").normalize(); + if (await fse.pathExists(projectPath)) { + const projectUri = Uri.file(projectPath).toString(); + const upgradeWrapperCommand: Command = { + title: UPGRADE_GRADLE_WRAPPER_TITLE, + command: Commands.UPGRADE_GRADLE_WRAPPER_CMD, + arguments: [projectUri] + }; + const codeAction = new CodeAction(UPGRADE_GRADLE_WRAPPER_TITLE, CodeActionKind.QuickFix.append("gradle")); + codeAction.command = upgradeWrapperCommand; + codeActions.push(codeAction); + } + } + } + return codeActions; + } +} + +export const gradleCodeActionMetadata: CodeActionProviderMetadata = { + providedCodeActionKinds: [ + CodeActionKind.QuickFix.append("gradle") + ] +}; diff --git a/src/hoverAction.ts b/src/hoverAction.ts new file mode 100644 index 0000000000..f4e91f4d0d --- /dev/null +++ b/src/hoverAction.ts @@ -0,0 +1,110 @@ +'use strict'; + +import { HoverProvider, CancellationToken, Hover, Position, TextDocument, MarkdownString, MarkedString, Command } from "vscode"; +import { TextDocumentPositionParams, HoverRequest } from "vscode-languageclient"; +import { LanguageClient } from 'vscode-languageclient/node'; +import { Commands as javaCommands } from "./commands"; +import { FindLinks } from "./protocol"; +import { ProvideHoverCommandFn } from "./extension.api"; +import { logger } from "./log"; + +export function createClientHoverProvider(languageClient: LanguageClient): JavaHoverProvider { + const hoverProvider: JavaHoverProvider = new JavaHoverProvider(languageClient); + registerHoverCommand(async (params: TextDocumentPositionParams, token: CancellationToken) => { + return await provideHoverCommand(languageClient, params, token); + }); + + return hoverProvider; +} + +async function provideHoverCommand(languageClient: LanguageClient, params: TextDocumentPositionParams, token: CancellationToken): Promise { + const response = await languageClient.sendRequest(FindLinks.type, { + type: 'superImplementation', + position: params, + }, token); + if (response && response.length) { + const location = response[0]; + let tooltip; + if (location.kind === 'method') { + tooltip = `Go to super method '${location.displayName}'`; + } else { + tooltip = `Go to super implementation '${location.displayName}'`; + } + + return [{ + title: 'Go to Super Implementation', + command: javaCommands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND, + tooltip, + arguments: [{ + uri: encodeBase64(location.uri), + range: location.range, + }], + }]; + } +} + +function encodeBase64(text: string): string { + return Buffer.from(text).toString('base64'); +} + +const hoverCommandRegistry: ProvideHoverCommandFn[] = []; +export function registerHoverCommand(callback: ProvideHoverCommandFn): void { + hoverCommandRegistry.push(callback); +} + +class JavaHoverProvider implements HoverProvider { + + constructor(readonly languageClient: LanguageClient) { + } + + async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + const params = { + textDocument: this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document), + position: this.languageClient.code2ProtocolConverter.asPosition(position), + }; + + // Fetch the javadoc from Java language server. + const hoverResponse = await this.languageClient.sendRequest(HoverRequest.type, params, token); + const serverHover = this.languageClient.protocol2CodeConverter.asHover(hoverResponse); + + // Fetch the contributed hover commands from third party extensions. + const contributedCommands: Command[] = await this.getContributedHoverCommands(params, token); + if (!contributedCommands.length) { + return serverHover; + } + + const contributed = new MarkdownString(contributedCommands.map((command) => this.convertCommandToMarkdown(command)).join(' | ')); + contributed.isTrusted = true; + let contents: MarkdownString[] = [ contributed ]; + let range; + if (serverHover && serverHover.contents) { + contents = contents.concat(serverHover.contents as MarkdownString[]); + range = serverHover.range; + } + return new Hover(contents, range); + } + + private async getContributedHoverCommands(params: TextDocumentPositionParams, token: CancellationToken): Promise { + const contributedCommands: Command[] = []; + for (const provideFn of hoverCommandRegistry) { + try { + if (token.isCancellationRequested) { + break; + } + + const commands = (await provideFn(params, token)) || []; + commands.forEach((command) => { + contributedCommands.push(command); + }); + } catch (error) { + logger.error(`Failed to provide hover command ${String(error)}`); + } + } + + return contributedCommands; + } + + private convertCommandToMarkdown(command: Command): string { + return `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify(command.arguments || []))} "${command.tooltip || command.command}")`; + } +} diff --git a/src/javaClassEditor.ts b/src/javaClassEditor.ts new file mode 100644 index 0000000000..2cf0f6bd0d --- /dev/null +++ b/src/javaClassEditor.ts @@ -0,0 +1,60 @@ +import path = require('path'); +import * as vscode from 'vscode'; +import { Uri, window, ExtensionContext} from "vscode"; +import { getNonce } from "./webviewUtils"; + +class JavaClassDocument implements vscode.CustomDocument { + constructor(uri: Uri) { this.uri = uri; } + uri: Uri; + dispose(): void { } +} + +export class JavaClassEditorProvider implements vscode.CustomReadonlyEditorProvider { + + private context: ExtensionContext; + + openCustomDocument(uri: Uri, openContext: vscode.CustomDocumentOpenContext, token: vscode.CancellationToken): JavaClassDocument { + return new JavaClassDocument(uri); + } + + constructor (context: ExtensionContext) { + this.context = context; + } + + public static readonly viewType = 'decompiled.javaClass'; + + async resolveCustomEditor(document: vscode.CustomDocument, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken): Promise { + const nonce: string = getNonce(); + webviewPanel.webview.options = { + enableScripts: true, + localResourceRoots: [Uri.joinPath(Uri.parse(this.context.extensionPath), 'webview-resources')] + }; + const classUri = Uri.parse((document.uri.toString()).replace(/^file/, "class")); + const styleUri = Uri.file( + path.join(this.context.extensionPath, 'webview-resources', 'button.css') + ); + const style: string = ``; + webviewPanel.webview.html = ` + + + + ${style} + + + + + + `; + webviewPanel.webview.onDidReceiveMessage(message => { + switch (message.command) { + case 'decompiled': + webviewPanel.dispose(); + window.showTextDocument(classUri, { preview: false }); + return; + } + }, undefined, this.context.subscriptions); + } +} \ No newline at end of file diff --git a/src/javaRuntimes.ts b/src/javaRuntimes.ts new file mode 100644 index 0000000000..4301318d52 --- /dev/null +++ b/src/javaRuntimes.ts @@ -0,0 +1,69 @@ +import { getRuntime, IJavaRuntime } from "jdk-utils"; +import * as vscode from "vscode"; +import { getSupportedJreNames } from "./jdkUtils"; +import { Commands } from "./commands"; +import * as path from "path"; + + +export namespace JavaRuntimes { + function compatible(runtime: IJavaRuntime, jreName: string): boolean { + if (!runtime.version) { + return true; + } + const majorVersion = runtime.version.major; + if (majorVersion === 8) { + return jreName === 'JavaSE-1.8'; + } + const versionStrings = /[0-9]+/g.exec(jreName); + if (versionStrings && versionStrings.length > 0) { + return majorVersion >= parseInt(versionStrings[0]); + } + return false; + } + + export async function initialize(context: vscode.ExtensionContext): Promise { + context.subscriptions.push(vscode.commands.registerCommand(Commands.ADD_JAVA_RUNTIME, async () => { + const lastSelectedDirectory: vscode.Uri | undefined = context.workspaceState.get('java.runtimes.lastSelectedDirectory'); + const directory = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + title: 'Select JDK Directory', + defaultUri: lastSelectedDirectory, + }); + if (directory) { + context.workspaceState.update('java.runtimes.lastSelectedDirectory', vscode.Uri.file(path.dirname(directory[0].fsPath))); + const runtime = await getRuntime(directory[0].fsPath, {withVersion: true}); + if (runtime) { + const config = vscode.workspace.getConfiguration('java.configuration').get('runtimes'); + if (Array.isArray(config)) { + const candidates = getSupportedJreNames().filter(name => compatible(runtime, name)).reverse(); + if (candidates.length > 0) { + const name = await vscode.window.showQuickPick(candidates, { + title: 'Select Java Runtime', + }); + if (name) { + const newConfig = { + name: name, + path: directory[0].fsPath, + }; + const index = config.findIndex(r => r.name === name); + if (index >= 0) { + config[index] = newConfig; + } else { + config.push(newConfig); + } + vscode.workspace.getConfiguration('java.configuration').update('runtimes', config, vscode.ConfigurationTarget.Global); + vscode.window.showInformationMessage(`JDK Directory ${directory[0].fsPath} added`); + } + } else { + vscode.window.showErrorMessage('No compatible environment available'); + } + } + } else { + vscode.window.showErrorMessage(`Invalid JDK Directory ${directory[0].fsPath}`); + } + } + })); + } +} \ No newline at end of file diff --git a/src/javaServerStarter.ts b/src/javaServerStarter.ts index 633001fc98..5e5cbed6f2 100644 --- a/src/javaServerStarter.ts +++ b/src/javaServerStarter.ts @@ -1,24 +1,76 @@ -import * as path from 'path'; +import * as fs from 'fs'; +import * as fse from 'fs-extra'; +import { globSync } from 'glob'; import * as net from 'net'; -import * as glob from 'glob'; import * as os from 'os'; -import { StreamInfo, Executable, ExecutableOptions } from 'vscode-languageclient'; +import * as path from 'path'; +import { ExtensionContext, version, workspace } from 'vscode'; +import { Executable, ExecutableOptions, StreamInfo, TransportKind, generateRandomPipeName } from 'vscode-languageclient/node'; +import { logger } from './log'; +import { addLombokParam, isLombokSupportEnabled } from './lombokSupport'; import { RequirementsData } from './requirements'; -import { getJavaEncoding } from './settings'; - +import { IS_WORKSPACE_VMARGS_ALLOWED, getJavaEncoding, getJavaagentFlag, getKey, isInWorkspaceFolder } from './settings'; +import { deleteDirectory, ensureExists, getJavaConfiguration, getTimestamp, getVersion, getVSCodeVariablesMap, isInsiderEditor, isPrereleaseOrInsiderVersion } from './utils'; +// eslint-disable-next-line no-var declare var v8debug; -const DEBUG = (typeof v8debug === 'object') || startedInDebugMode(); +export const DEBUG = (typeof v8debug === 'object') || startedInDebugMode(); + +/** + * Argument that tells the program where to generate the heap dump that is created when an OutOfMemoryError is raised and `HEAP_DUMP` has been passed + */ +export const HEAP_DUMP_LOCATION = '-XX:HeapDumpPath='; + +/** + * Argument that tells the program to generate a heap dump file when an OutOfMemoryError is raised + */ +export const HEAP_DUMP = '-XX:+HeapDumpOnOutOfMemoryError'; -export function prepareExecutable(requirements: RequirementsData, workspacePath, javaConfig): Executable { +/** + * Argument that specifies name of the dependency collector implementation to use. + * `df` for depth-first and `bf` for breadth-first. + * See: https://github.com/apache/maven-resolver/blob/maven-resolver-1.9.7/src/site/markdown/configuration.md + */ +const DEPENDENCY_COLLECTOR_IMPL= '-Daether.dependencyCollector.impl='; +const DEPENDENCY_COLLECTOR_IMPL_BF= 'bf'; + +const UNLOCK_DIAGNOSTIC_VM_OPTIONS= '-XX:+UnlockDiagnosticVMOptions'; +const ALLOW_ARCHIVING_WITH_JAVA_AGENT= '-XX:+AllowArchivingWithJavaAgent'; +const AUTO_CREATE_SHARED_ARCHIVE= '-XX:+AutoCreateSharedArchive'; +const SHARED_ARCHIVE_FILE_LOC= '-XX:SharedArchiveFile='; + +export function prepareExecutable(requirements: RequirementsData, workspacePath, context: ExtensionContext, isSyntaxServer: boolean): Executable { const executable: Executable = Object.create(null); const options: ExecutableOptions = Object.create(null); - options.env = process.env; - options.stdio = 'pipe'; + options.env = Object.assign({ syntaxserver: isSyntaxServer }, process.env, getVSCodeVariablesMap()); + if (os.platform() === 'win32') { + const vmargs = getJavaConfiguration().get('jdt.ls.vmargs', ''); + const watchParentProcess = '-DwatchParentProcess=false'; + if (vmargs.indexOf(watchParentProcess) < 0) { + options.detached = true; + } + } executable.options = options; - executable.command = path.resolve(requirements.java_home + '/bin/java'); - executable.args = prepareParams(requirements, javaConfig, workspacePath); - console.log(`Starting Java server with: ${executable.command} ${executable.args.join(' ')}`); + executable.command = path.resolve(`${requirements.tooling_jre}/bin/java`); + executable.args = prepareParams(requirements, workspacePath, context, isSyntaxServer); + const transportKind = getJavaConfiguration().get('transport'); + + switch (transportKind) { + case 'stdio': + executable.transport = TransportKind.stdio; + break; + case 'pipe': + default: + executable.transport = TransportKind.pipe; + try { + generateRandomPipeName(); + } catch (error) { + logger.warn(`Falling back to 'stdio' (from 'pipe') due to : ${error}`); + executable.transport = TransportKind.stdio; + } + break; + } + logger.info(`Starting Java server with: ${executable.command} ${executable.args?.join(' ')}`); return executable; } export function awaitServerConnection(port): Thenable { @@ -26,31 +78,98 @@ export function awaitServerConnection(port): Thenable { return new Promise((res, rej) => { const server = net.createServer(stream => { server.close(); - console.log('JDT LS connection established on port ' + addr); + logger.info(`JDT LS connection established on port ${addr}`); res({ reader: stream, writer: stream }); }); server.on('error', rej); server.listen(addr, () => { server.removeListener('error', rej); - console.log('Awaiting JDT LS connection on port ' + addr); + logger.info(`Awaiting JDT LS connection on port ${addr}`); }); return server; }); } -function prepareParams(requirements: RequirementsData, javaConfiguration, workspacePath): string[] { +function prepareParams(requirements: RequirementsData, workspacePath, context: ExtensionContext, isSyntaxServer: boolean): string[] { const params: string[] = []; if (DEBUG) { - params.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044,quiet=y'); + const port = isSyntaxServer ? 1045 : 1044; + params.push(`-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${port},quiet=y`); // suspend=y is the default. Use this form if you need to debug the server startup code: // params.push('-agentlib:jdwp=transport=dt_socket,server=y,address=1044'); } - if (requirements.java_version > 8) { - params.push('--add-modules=ALL-SYSTEM', - '--add-opens', - 'java.base/java.util=ALL-UNNAMED', - '--add-opens', - 'java.base/java.lang=ALL-UNNAMED'); + + // See https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3465 + if (requirements.tooling_jre_version >= 24) { + params.push('-Djdk.xml.maxGeneralEntitySizeLimit=0', + '-Djdk.xml.totalEntitySizeLimit=0' + ); + } + + params.push('--add-modules=ALL-SYSTEM', + '--add-opens', + 'java.base/java.util=ALL-UNNAMED', + '--add-opens', + 'java.base/java.lang=ALL-UNNAMED', + // See https://github.com/redhat-developer/vscode-java/issues/2264 + // It requires the internal API sun.nio.fs.WindowsFileAttributes.isDirectoryLink() to check if a Windows directory is symlink. + '--add-opens', + 'java.base/sun.nio.fs=ALL-UNNAMED' + ); + + const javacEnabled = 'on' === getJavaConfiguration().get('jdt.ls.javac.enabled'); + if (javacEnabled) { + // Javac flags + params.push( + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', + '--add-opens', + 'jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.taglets.snippet=ALL-UNNAMED', + '--add-opens', + 'jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.taglets=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED', + '--add-opens', + 'jdk.compiler/com.sun.tools.javac.resources=ALL-UNNAMED', + '--add-opens', + 'java.base/sun.nio.ch=ALL-UNNAMED', + '--add-opens', + 'jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED', + '--add-opens', + 'java.compiler/javax.tools=ALL-UNNAMED', + '--add-opens', + 'java.base/java.nio.channels=ALL-UNNAMED', + '-DICompilationUnitResolver=org.eclipse.jdt.core.dom.JavacCompilationUnitResolver', + '-DAbstractImageBuilder.compilerFactory=org.eclipse.jdt.internal.javac.JavacCompilerFactory', + '-DCompilationUnit.DOM_BASED_OPERATIONS=true', + '-DSourceIndexer.DOM_BASED_INDEXER=true', + '-DMatchLocator.DOM_BASED_MATCH=true', + '-DIJavaSearchDelegate=org.eclipse.jdt.internal.core.search.DOMJavaSearchDelegate', + ); + + if('dom' === getJavaConfiguration().get('completion.engine')){ + params.push('-DCompilationUnit.codeComplete.DOM_BASED_OPERATIONS=true'); + }; } params.push('-Declipse.application=org.eclipse.jdt.ls.core.id1', @@ -59,22 +178,88 @@ function prepareParams(requirements: RequirementsData, javaConfiguration, worksp if (DEBUG) { params.push('-Dlog.level=ALL'); } - - const vmargs = javaConfiguration.get('jdt.ls.vmargs', ''); + const metadataLocation = workspace.getConfiguration().get('java.import.generatesMetadataFilesAtProjectRoot'); + if (metadataLocation !== undefined) { + params.push(`-Djava.import.generatesMetadataFilesAtProjectRoot=${metadataLocation}`); + } + let vmargsCheck = workspace.getConfiguration().inspect('java.jdt.ls.vmargs').workspaceValue; + if (vmargsCheck !== undefined) { + const isWorkspaceTrusted = (workspace as any).isTrusted; // keep compatibility for old engines < 1.56.0 + const agentFlag = getJavaagentFlag(vmargsCheck); + if (agentFlag !== null && (isWorkspaceTrusted === undefined || !isWorkspaceTrusted)) { + const keyVmargs = getKey(IS_WORKSPACE_VMARGS_ALLOWED, context.storagePath, vmargsCheck); + const key = context.globalState.get(keyVmargs); + if (key !== true && (workspace.workspaceFolders && isInWorkspaceFolder(agentFlag, workspace.workspaceFolders))) { + vmargsCheck = workspace.getConfiguration().inspect('java.jdt.ls.vmargs').globalValue; + } + } + } else { + vmargsCheck = getJavaConfiguration().get('jdt.ls.vmargs'); + } + let vmargs; + if (vmargsCheck !== undefined) { + vmargs = String(vmargsCheck); + } else { + vmargs = ''; + } + if (vmargs.indexOf('-DDetectVMInstallationsJob.disabled=') < 0) { + params.push('-DDetectVMInstallationsJob.disabled=true'); + } const encodingKey = '-Dfile.encoding='; if (vmargs.indexOf(encodingKey) < 0) { params.push(encodingKey + getJavaEncoding()); } - if (os.platform() === 'win32') { - const watchParentProcess = '-DwatchParentProcess='; - if (vmargs.indexOf(watchParentProcess) < 0) { - params.push(watchParentProcess + 'false'); - } + if (vmargs.indexOf('-Xlog:') < 0) { + params.push('-Xlog:disable'); } parseVMargs(params, vmargs); - const serverHome: string = path.resolve(__dirname, '../server'); - const launchersFound: Array = glob.sync('**/plugins/org.eclipse.equinox.launcher_*.jar', { cwd: serverHome }); + + if (isLombokSupportEnabled()) { + addLombokParam(context, params); + } + + if (!isSyntaxServer) { + if (vmargs.indexOf(HEAP_DUMP) < 0) { + params.push(HEAP_DUMP); + } + if (vmargs.indexOf(HEAP_DUMP_LOCATION) < 0) { + params.push(`${HEAP_DUMP_LOCATION}${path.dirname(workspacePath)}`); + } + if (vmargs.indexOf(DEPENDENCY_COLLECTOR_IMPL) < 0) { + params.push(`${DEPENDENCY_COLLECTOR_IMPL}${DEPENDENCY_COLLECTOR_IMPL_BF}`); + } + + const sharedIndexLocation: string = resolveIndexCache(context); + if (sharedIndexLocation) { + params.push(`-Djdt.core.sharedIndexLocation=${sharedIndexLocation}`); + } + + const hasJDWP = params.find((param: string) => param.includes('jdwp')) !== undefined; + const extVersion = getVersion(context.extensionPath); + const globalStoragePath = path.resolve(context.globalStorageUri?.fsPath, extVersion); // .../Code/User/globalStorage/redhat.java/1.42.0/ + const appCDSMode = workspace.getConfiguration().get('java.jdt.ls.appcds.enabled'); + const useAppCDS = (appCDSMode === 'on') || (appCDSMode === 'auto' && (isPrereleaseOrInsiderVersion(context))); + + ensureExists(globalStoragePath); + const sharedArchiveLocation = path.join(globalStoragePath, "jdtls.jsa"); + if (useAppCDS && vmargs.indexOf(SHARED_ARCHIVE_FILE_LOC) < 0 && !hasJDWP) { + params.push(UNLOCK_DIAGNOSTIC_VM_OPTIONS); + params.push(ALLOW_ARCHIVING_WITH_JAVA_AGENT); // required due to use of '-javaagent' + params.push(AUTO_CREATE_SHARED_ARCHIVE); + params.push(`${SHARED_ARCHIVE_FILE_LOC}${sharedArchiveLocation}`); + } + } + + // "OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify + // were deprecated in JDK 13 and will likely be removed in a future release." + // so only add -noverify for older versions + if (params.indexOf('-noverify') < 0 && params.indexOf('-Xverify:none') < 0 && requirements.tooling_jre_version < 13) { + params.push('-noverify'); + } + + const serverHome: string = process.env.JDT_LS_PATH || path.resolve(__dirname, '../server'); + const launchersFound: Array = globSync('**/plugins/org.eclipse.equinox.launcher_*.jar', { cwd: serverHome }); if (launchersFound.length) { params.push('-jar'); params.push(path.resolve(serverHome, launchersFound[0])); } else { @@ -82,21 +267,109 @@ function prepareParams(requirements: RequirementsData, javaConfiguration, worksp } // select configuration directory according to OS - let configDir = 'config_win'; + let configDir = isSyntaxServer ? 'config_ss_win' : 'config_win'; if (process.platform === 'darwin') { - configDir = 'config_mac'; + configDir = isSyntaxServer ? 'config_ss_mac' : 'config_mac'; } else if (process.platform === 'linux') { - configDir = 'config_linux'; + configDir = isSyntaxServer ? 'config_ss_linux' : 'config_linux'; + } + params.push('-configuration'); + params.push(startedFromSources() || process.env.JDT_LS_PATH !== undefined ? + path.resolve(serverHome, configDir) : resolveConfiguration(context, configDir)); + if (startedFromSources()) { // Dev Mode: keep the config.ini in the installation location + console.log(`Starting jdt.ls ${isSyntaxServer?'(syntax)' : '(standard)'} from vscode-java sources`); } - params.push('-configuration'); params.push(path.resolve(__dirname, '../server', configDir)); + params.push('-data'); params.push(workspacePath); return params; } +function resolveIndexCache(context: ExtensionContext) { + let enabled: string = getJavaConfiguration().get("sharedIndexes.enabled"); + if (enabled === "auto") { + enabled = isInsiderEditor() ? "on" : "off"; + } + + if (enabled !== "on") { + return; + } + + const location: string = getSharedIndexCache(context); + if (location) { + ensureExists(location); + if (!fs.existsSync(location)) { + logger.error(`Failed to create the shared index directory '${location}', fall back to local index.`); + return; + } + } + + return location; +} + +export function getSharedIndexCache(context: ExtensionContext): string { + let location: string = getJavaConfiguration().get("sharedIndexes.location"); + if (!location) { + switch (process.platform) { + case "win32": + location = process.env.APPDATA ? path.join(process.env.APPDATA, ".jdt", "index") + : path.join(os.homedir(), ".jdt", "index"); + break; + case "darwin": + location = path.join(os.homedir(), "Library", "Caches", ".jdt", "index"); + break; + case "linux": + location = process.env.XDG_CACHE_HOME ? path.join(process.env.XDG_CACHE_HOME, ".jdt", "index") + : path.join(os.homedir(), ".cache", ".jdt", "index"); + break; + default: + const globalStoragePath = context.globalStorageUri?.fsPath; // .../Code/User/globalStorage/redhat.java + location = globalStoragePath ? path.join(globalStoragePath, "index") : undefined; + } + } else { + // expand homedir + location = location.startsWith(`~${path.sep}`) ? path.join(os.homedir(), location.slice(2)) : location; + } + + return location; +} + +function resolveConfiguration(context, configDir) { + ensureExists(context.globalStoragePath); + const version = getVersion(context.extensionPath); + let configuration = path.resolve(context.globalStoragePath, version); + ensureExists(configuration); + configuration = path.resolve(configuration, configDir); + ensureExists(configuration); + const configIniName = "config.ini"; + const configIni = path.resolve(configuration, configIniName); + const ini = path.resolve(__dirname, '../server', configDir, configIniName); + if (!fs.existsSync(configIni)) { + fs.copyFileSync(ini, configIni); + } else { + const configIniTime = getTimestamp(configIni); + const iniTime = getTimestamp(ini); + if (iniTime > configIniTime) { + deleteDirectory(configuration); + resolveConfiguration(context, configDir); + } + } + return configuration; +} + function startedInDebugMode(): boolean { - const args = (process as any).execArgv; + const args = (process as any).execArgv as string[]; + return hasDebugFlag(args); +} + +export function startedFromSources(): boolean { + return process.env['DEBUG_VSCODE_JAVA'] === 'true'; +} + +// exported for tests +export function hasDebugFlag(args: string[]): boolean { if (args) { - return args.some((arg) => /^--debug=?/.test(arg) || /^--debug-brk=?/.test(arg) || /^--inspect-brk=?/.test(arg)); + // See https://nodejs.org/en/docs/guides/debugging-getting-started/ + return args.some( arg => /^--inspect/.test(arg) || /^--debug/.test(arg)); } return false; } @@ -115,8 +388,16 @@ export function parseVMargs(params: any[], vmargsLine: string) { arg = arg.replace(/(\\)?"/g, ($0, $1) => { return ($1 ? $0 : ''); }); // unescape all escaped double quotes arg = arg.replace(/(\\)"/g, '"'); - if (params.indexOf(arg) < 0) { - params.push(arg); - } + params.push(arg); }); } + +export function removeEquinoxFragmentOnDarwinX64(context: ExtensionContext) { + // https://github.com/redhat-developer/vscode-java/issues/3484 + const extensionPath = context.extensionPath; + const matches = globSync(`${extensionPath}/server/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64*.jar`); + for (const fragment of matches) { + fse.removeSync(fragment); + logger.info(`Removing Equinox launcher fragment : ${fragment}`); + } +} diff --git a/src/jdkUtils.ts b/src/jdkUtils.ts new file mode 100644 index 0000000000..5cf801b343 --- /dev/null +++ b/src/jdkUtils.ts @@ -0,0 +1,96 @@ +'use strict'; + +import { existsSync } from 'fs'; +import { IJavaRuntime, findRuntimes, getSources } from 'jdk-utils'; +import { join } from 'path'; +import { ExtensionContext, Uri, workspace } from 'vscode'; + +let cachedJdks: IJavaRuntime[]; +let cachedJreNames: string[]; + +export async function loadSupportedJreNames(context: ExtensionContext): Promise { + const config = await getContributesConfiguration(context, "java.configuration.runtimes"); + cachedJreNames = config?.items?.properties?.name?.enum; +} + +async function getContributesConfiguration(context: ExtensionContext, configId: string): Promise { + const buffer = await workspace.fs.readFile(Uri.file(context.asAbsolutePath("package.json"))); + const packageJson = JSON.parse(buffer.toString()); + /** + * contributes.configuration can either be a single object, + * representing a single category of settings, or an array + * of objects, representing multiple categories of settings. + */ + const categories = packageJson?.contributes?.configuration; + if (Array.isArray(categories)) { + for (const category of categories) { + if (category?.properties?.[configId]) { + return category.properties[configId]; + } + } + } else { + return categories?.properties?.[configId]; + } +} + +export function getSupportedJreNames(): string[] { + return cachedJreNames; +} + +export async function listJdks(force?: boolean): Promise { + if (force || !cachedJdks) { + cachedJdks = await findRuntimes({ checkJavac: true, withVersion: true, withTags: true }) + .then(jdks => jdks.filter(jdk => { + // Validate if it's a real Java Home. + return existsSync(join(jdk.homedir, "lib", "rt.jar")) + || existsSync(join(jdk.homedir, "jre", "lib", "rt.jar")) // Java 8 + || existsSync(join(jdk.homedir, "lib", "jrt-fs.jar")); // Java 9+ + })); + } + + return [].concat(cachedJdks); +} + +/** + * Sort by source where JDk is located. + * The order is: + * 1. JDK_HOME, JAVA_HOME, PATH + * 2. JDK manager such as SDKMAN, jEnv, jabba, asdf + * 3. Common places such as /usr/lib/jvm + * 4. Others + */ +export function sortJdksBySource(jdks: IJavaRuntime[]) { + const rankedJdks = jdks as Array; + const env: string[] = ["JDK_HOME", "JAVA_HOME", "PATH"]; + const jdkManagers: string[] = ["SDKMAN", "jEnv", "jabba", "asdf"]; + for (const jdk of rankedJdks) { + const detectedSources: string[] = getSources(jdk); + for (const [index, source] of env.entries()) { + if (detectedSources.includes(source)) { + jdk.rank = index; // jdk from environment variables + break; + } + } + + if (jdk.rank) { + continue; + } + + const fromManager: boolean = detectedSources.some(source => jdkManagers.includes(source)); + if (fromManager) { + jdk.rank = env.length + 1; // jdk from the jdk managers such as SDKMAN + } else if (!detectedSources.length){ + jdk.rank = env.length + 2; // jdk from common places + } else { + jdk.rank = env.length + 3; // jdk from other source such as ~/.gradle/jdks + } + } + rankedJdks.sort((a, b) => a.rank - b.rank); +} + +/** + * Sort by major version in descend order. + */ +export function sortJdksByVersion(jdks: IJavaRuntime[]) { + jdks.sort((a, b) => (b.version?.major ?? 0) - (a.version?.major ?? 0)); +} diff --git a/src/languageStatusItemFactory.ts b/src/languageStatusItemFactory.ts new file mode 100644 index 0000000000..d647bf6d2f --- /dev/null +++ b/src/languageStatusItemFactory.ts @@ -0,0 +1,84 @@ +'use strict'; + +import * as path from "path"; +import * as vscode from "vscode"; +import { Commands } from "./commands"; + +const languageServerDocumentSelector = [ + { scheme: 'file', language: 'java' }, + { scheme: 'jdt', language: 'java' }, + { scheme: 'untitled', language: 'java' }, + { pattern: '**/pom.xml' }, + { pattern: '**/{build,settings}.gradle'}, + { pattern: '**/{build,settings}.gradle.kts'} +]; + +export namespace StatusCommands { + export const switchToStandardCommand = { + title: "Load Projects", + command: Commands.SWITCH_SERVER_MODE, + arguments: ['Standard', true], + tooltip: "LightWeight mode only provides limited features, please load projects to get full feature set" + }; + + export const configureJavaRuntimeCommand = { + title: "Configure Java Runtime", + command: "workbench.action.openSettings", + arguments: ["java.configuration.runtimes"], + tooltip: "Configure Java Runtime" + }; + + export const startStandardServerCommand = { + title: "Select Projects...", + command: Commands.SWITCH_SERVER_MODE, + arguments: ['Standard', true], + tooltip: "Select Projects..." + }; +} + +export namespace RuntimeStatusItemFactory { + export function create(text: string, vmInstallPath: string): vscode.LanguageStatusItem { + const item = vscode.languages.createLanguageStatusItem("javaRuntimeStatusItem", languageServerDocumentSelector); + item.severity = vscode.LanguageStatusSeverity?.Information; + item.name = "Java Runtime"; + item.text = text; + item.command = StatusCommands.configureJavaRuntimeCommand; + if (vmInstallPath) { + item.command.tooltip = `Language Level: ${text} <${vmInstallPath}>`; + } + return item; + } + + export function update(item: any, text: string, vmInstallPath: string): void { + item.text = text; + item.command.tooltip = vmInstallPath ? `Language Level: ${text} <${vmInstallPath}>` : "Configure Java Runtime"; + } +} + +export namespace BuildFileStatusItemFactory { + export function create(buildFilePath: string): vscode.LanguageStatusItem { + const fileName = path.basename(buildFilePath); + const item = vscode.languages.createLanguageStatusItem("javaBuildFileStatusItem", languageServerDocumentSelector); + item.severity = vscode.LanguageStatusSeverity?.Information; + item.name = "Java Build File"; + item.text = fileName; + item.command = getOpenBuildFileCommand(buildFilePath); + return item; + } + + export function update(item: any, buildFilePath: string): void { + const fileName = path.basename(buildFilePath); + item.text = fileName; + item.command = getOpenBuildFileCommand(buildFilePath); + } + + function getOpenBuildFileCommand(buildFilePath: string): vscode.Command { + const relativePath = vscode.workspace.asRelativePath(buildFilePath); + return { + title: `Open Config File`, + command: Commands.OPEN_BROWSER, + arguments: [vscode.Uri.file(buildFilePath)], + tooltip: `Open ${relativePath}` + }; + } +} diff --git a/src/log.ts b/src/log.ts new file mode 100644 index 0000000000..ce340c3d96 --- /dev/null +++ b/src/log.ts @@ -0,0 +1,25 @@ +import { createLogger, format, transports } from 'winston'; +import * as DailyRotateFile from 'winston-daily-rotate-file'; + +export function initializeLogFile(filename: string) { + logger.add(new DailyRotateFile({ + filename: filename, + datePattern: 'YYYY-MM-DD', + maxSize: '1m', // 1MB max size per file + maxFiles: '2d' // retain logs of the last two days + })); +} + +export const logger = createLogger({ + format: format.combine( + format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss.SSS' + }), + format.prettyPrint() + ), + transports: [ + // See https://github.com/microsoft/vscode/issues/117327 + // Disable console.log for lsp trace because intense logging will freeze the code render process. + // new transports.Console() + ] +}); diff --git a/src/lombokSupport.ts b/src/lombokSupport.ts new file mode 100644 index 0000000000..1ec595d565 --- /dev/null +++ b/src/lombokSupport.ts @@ -0,0 +1,283 @@ +'use strict'; + +import * as fse from "fs-extra"; +import * as path from "path"; +import * as semver from 'semver'; +import * as vscode from "vscode"; +import { ExtensionContext, window, commands, Uri } from "vscode"; +import { Commands } from "./commands"; +import { apiManager } from "./apiManager"; +import { languageStatusBarProvider } from './runtimeStatusBarProvider'; +import { logger } from './log'; +import { getAllJavaProjects } from "./utils"; + +export const JAVA_LOMBOK_PATH = "java.lombokPath"; + +const languageServerDocumentSelector = [ + { scheme: 'file', language: 'java' }, + { scheme: 'jdt', language: 'java' }, + { scheme: 'untitled', language: 'java' }, + { pattern: '**/pom.xml' }, + { pattern: '**/{build,settings}.gradle'}, + { pattern: '**/{build,settings}.gradle.kts'} +]; + +const lombokJarRegex = /lombok-\d+.*\.jar$/; +const compatibleVersion = '1.18.4'; +let activeLombokPath: string = undefined; +let isLombokStatusBarInitialized: boolean = false; +let isLombokCommandInitialized: boolean = false; +let isExtensionLombok: boolean = false; // whether use extension's Lombok or not +let projectLombokPath: string = undefined; // the project's Lombok classpath + +export namespace Lombok { + + export function getActiveLombokPath(): string | undefined { + return activeLombokPath; + } +} +export function isLombokSupportEnabled(): boolean { + return vscode.workspace.getConfiguration().get("java.jdt.ls.lombokSupport.enabled"); +} + +export function isLombokImported(): boolean { + return projectLombokPath!==undefined; +} + +export function updateActiveLombokPath(path: string) { + activeLombokPath = path; +} + +export function isLombokActive(context: ExtensionContext): boolean { + return activeLombokPath!==undefined; +} + +export function cleanupLombokCache(context: ExtensionContext) { + context.workspaceState.update(JAVA_LOMBOK_PATH, undefined); +} + +function getExtensionLombokPath(context: ExtensionContext): string { + if (!fse.pathExistsSync(context.asAbsolutePath("lombok"))) { + return undefined; + } + const files = fse.readdirSync(context.asAbsolutePath("lombok")); + if (!files.length) { + return undefined; + } + return path.join(context.asAbsolutePath("lombok"), files[0]); +} + +function lombokPath2Version(lombokPath: string): string | undefined { + const match = lombokJarRegex.exec(lombokPath); + if (!match) { + return undefined; + } + const lombokVersion = match[0].split('.jar')[0]; + return lombokVersion; +} + +function lombokPath2VersionNumber(lombokPath: string): string | undefined { + const lombokVersion = lombokPath2Version(lombokPath); + if (!lombokVersion) { + return undefined; + } + const lombokVersionNumber = lombokVersion.split('-')[1]; + return lombokVersionNumber; +} + +export function getLombokVersion(): string | undefined { + return lombokPath2VersionNumber(activeLombokPath); +} + +function isCompatibleLombokVersion(currentVersion: string | undefined): boolean { + return currentVersion && semver.gte(currentVersion, compatibleVersion); +} + +export function addLombokParam(context: ExtensionContext, params: string[]) { + // Exclude user setting Lombok agent parameter + const reg = /-javaagent:.*[\\|/]lombok.*\.jar/; + const deleteIndex = []; + for (let i = 0; i < params.length; i++) { + if (reg.test(params[i])) { + deleteIndex.push(i); + } + } + for (let i = deleteIndex.length - 1; i >= 0; i--) { + params.splice(deleteIndex[i], 1); + } + // add -javaagent arg to support Lombok. + // use the extension's Lombok version by default. + isExtensionLombok = true; + let lombokJarPath: string = context.workspaceState.get(JAVA_LOMBOK_PATH); + if (lombokJarPath && fse.existsSync(lombokJarPath)) { + const lombokVersion = lombokPath2VersionNumber(lombokJarPath); + if (lombokVersion && isCompatibleLombokVersion(lombokVersion)) { + isExtensionLombok = false; + } + else { + cleanupLombokCache(context); + const extensionLombokVersion = lombokPath2VersionNumber(getExtensionLombokPath(context)); + logger.warn(`The project's Lombok version ${lombokVersion || 'unknown'} is not supported, Falling back to the built-in Lombok version ${extensionLombokVersion || 'unknown'}`); + } + } + if (isExtensionLombok) { + lombokJarPath = getExtensionLombokPath(context); + } + // check if the Lombok.jar exists. + if (!lombokJarPath) { + logger.warn("Could not find lombok.jar path."); + return; + } + const lombokAgentParam = `-javaagent:${lombokJarPath}`; + params.push(lombokAgentParam); + updateActiveLombokPath(lombokJarPath); +} + +export async function checkLombokDependency(context: ExtensionContext, projectUri?: Uri) { + if (!isLombokSupportEnabled()) { + return; + } + let versionChange: boolean = false; + let lombokFound: boolean = false; + let currentLombokVersion: string = undefined; + let previousLombokVersion: string = undefined; + let currentLombokClasspath: string = undefined; + const projectUris: string[] = projectUri ? [projectUri.toString()] : await getAllJavaProjects(); + for (const projectUri of projectUris) { + const classpathResult = await apiManager.getApiInstance().getClasspaths(projectUri, {scope: 'test'}); + for (const classpath of classpathResult.classpaths) { + if (lombokJarRegex.test(classpath)) { + currentLombokClasspath = classpath; + if (activeLombokPath && !isExtensionLombok) { + currentLombokVersion = lombokJarRegex.exec(classpath)[0]; + previousLombokVersion = lombokJarRegex.exec(activeLombokPath)[0]; + if (currentLombokVersion !== previousLombokVersion) { + versionChange = true; + } + } + lombokFound = true; + break; + } + } + if (lombokFound) { + break; + } + } + projectLombokPath = currentLombokClasspath; + /* if projectLombokPath is undefined, it means that this project has not imported Lombok. + * We don't need initialize Lombok status bar in this case. + */ + if (!isLombokStatusBarInitialized && projectLombokPath) { + if (!isLombokCommandInitialized) { + registerLombokConfigureCommand(context); + isLombokCommandInitialized = true; + } + languageStatusBarProvider.initializeLombokStatusBar(); + isLombokStatusBarInitialized = true; + } + if (isLombokStatusBarInitialized && !projectLombokPath) { + languageStatusBarProvider.destroyLombokStatusBar(); + isLombokStatusBarInitialized = false; + cleanupLombokCache(context); + } + if (versionChange && !isExtensionLombok) { + context.workspaceState.update(JAVA_LOMBOK_PATH, currentLombokClasspath); + const msg = `Lombok version changed from ${previousLombokVersion.split('.jar')[0].split('-')[1]} to ${currentLombokVersion.split('.jar')[0].split('-')[1]} \ + . Do you want to reload the window to load the new Lombok version?`; + const action = 'Reload'; + const restartId = Commands.RELOAD_WINDOW; + window.showInformationMessage(msg, action).then((selection) => { + if (action === selection) { + commands.executeCommand(restartId); + } + }); + } +} + +export function registerLombokConfigureCommand(context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand(Commands.LOMBOK_CONFIGURE, async (buildFilePath: string) => { + const extensionLombokPath: string = getExtensionLombokPath(context); + if (!extensionLombokPath || !projectLombokPath) { + return; + } + const extensionItemLabel = 'Use Extension\'s Version'; + const extensionItemLabelCheck = `• ${extensionItemLabel}`; + const projectItemLabel = 'Use Project\'s Version'; + const projectItemLabelCheck = `• ${projectItemLabel}`; + const lombokPathItems = [ + { + label: isExtensionLombok? extensionItemLabelCheck : extensionItemLabel, + description: `Lombok ${lombokPath2VersionNumber(extensionLombokPath) || 'unknown'}` + }, + { + label: isExtensionLombok? projectItemLabel : projectItemLabelCheck, + description: `Lombok ${lombokPath2VersionNumber(projectLombokPath) || 'unknown'}`, + detail: projectLombokPath + } + ]; + const selectLombokPathItem = await window.showQuickPick(lombokPathItems, { + placeHolder: 'Select the Lombok version used in the Java extension' + }); + let shouldReload: boolean = false; + if (!selectLombokPathItem) { + return; + } + if (selectLombokPathItem.label === extensionItemLabel || selectLombokPathItem.label === extensionItemLabelCheck) { + if (!isExtensionLombok) { + shouldReload = true; + cleanupLombokCache(context); + } + } + else { + if (isExtensionLombok) { + const projectLombokVersion = lombokPath2VersionNumber(projectLombokPath); + if (!isCompatibleLombokVersion(projectLombokVersion)) { + const msg = `The project's Lombok version ${projectLombokVersion || 'unknown'} is not supported. Falling back to the built-in Lombok version in the extension.`; + window.showWarningMessage(msg); + return; + } + else { + shouldReload = true; + context.workspaceState.update(JAVA_LOMBOK_PATH, projectLombokPath); + } + } + } + if (shouldReload) { + const msg = `The Lombok version used in Java extension has changed, please reload the window.`; + const action = 'Reload'; + const restartId = Commands.RELOAD_WINDOW; + window.showInformationMessage(msg, action).then((selection) => { + if (action === selection) { + commands.executeCommand(restartId); + } + }); + } + else { + const msg = `Current Lombok version is ${isExtensionLombok?'extension\'s' : 'project\'s'} version. Nothing to do.`; + window.showInformationMessage(msg); + } + })); +} + +export namespace LombokVersionItemFactory { + export function create(version: string): vscode.LanguageStatusItem { + const item = vscode.languages.createLanguageStatusItem("javaLombokVersionItem", languageServerDocumentSelector); + item.severity = vscode.LanguageStatusSeverity?.Information; + item.name = "Lombok Version"; + update(item, version); + item.command = getLombokChangeCommand(); + return item; + } + + export function update(item: any, version: string | undefined): void { + item.text = `Lombok ${version || 'unknown'}`; + } + + function getLombokChangeCommand(): vscode.Command { + return { + title: `Configure Version`, + command: Commands.LOMBOK_CONFIGURE, + tooltip: `Configure Lombok Version` + }; + } +} \ No newline at end of file diff --git a/src/markdownPreviewProvider.ts b/src/markdownPreviewProvider.ts new file mode 100644 index 0000000000..ad43e535cb --- /dev/null +++ b/src/markdownPreviewProvider.ts @@ -0,0 +1,99 @@ +import { Disposable, WebviewPanel, window, ViewColumn, commands, Uri, Webview, ExtensionContext, env } from "vscode"; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import { Commands } from "./commands"; +import { getNonce } from "./webviewUtils"; + +class MarkdownPreviewProvider implements Disposable { + private panel: WebviewPanel | undefined; + // a cache maps document path to rendered html + private documentCache: Map = new Map(); + private disposables: Disposable[] = []; + + public async show(markdownFilePath: string, title: string, section: string, context: ExtensionContext): Promise { + if (!this.panel) { + this.panel = window.createWebviewPanel('java.markdownPreview', title, ViewColumn.Active, { + localResourceRoots: [ + Uri.file(path.join(context.extensionPath, 'webview-resources')), + Uri.file(path.dirname(markdownFilePath)), + ], + retainContextWhenHidden: true, + enableFindWidget: true, + enableScripts: true, + }); + } + + this.disposables.push(this.panel.onDidDispose(() => { + this.panel = undefined; + })); + + this.panel.iconPath = Uri.file(path.join(context.extensionPath, 'icons', 'icon128.png')); + this.panel.webview.html = await this.getHtmlContent(this.panel.webview, markdownFilePath, section, context); + this.panel.title = title; + this.panel.reveal(this.panel.viewColumn); + } + + public dispose(): void { + if (this.panel) { + this.panel.dispose(); + } + for (const disposable of this.disposables) { + disposable.dispose(); + } + } + + protected async getHtmlContent(webview: Webview, markdownFilePath: string, section: string, context: ExtensionContext): Promise { + const nonce: string = getNonce(); + const styles: string = this.getStyles(webview, context); + let body: string | undefined = this.documentCache.get(markdownFilePath); + if (!body) { + let markdownString: string = await fse.readFile(markdownFilePath, 'utf8'); + markdownString = markdownString.replace(/__VSCODE_ENV_APPNAME_PLACEHOLDER__/, env.appName); + body = await commands.executeCommand(Commands.MARKDOWN_API_RENDER, markdownString); + this.documentCache.set(markdownFilePath, body); + } + return ` + + + + + + + ${styles} + + + + ${body} + + + + + `; + } + + protected getStyles(webview: Webview, context: ExtensionContext): string { + const styles: Uri[] = [ + Uri.file(path.join(context.extensionPath, 'webview-resources', 'highlight.css')), + Uri.file(path.join(context.extensionPath, 'webview-resources', 'markdown.css')), + Uri.file(path.join(context.extensionPath, 'webview-resources', 'document.css')), + ]; + return styles.map((styleUri: Uri) => ``).join('\n'); + } +} + +export const markdownPreviewProvider: MarkdownPreviewProvider = new MarkdownPreviewProvider(); diff --git a/src/outline/extendedOutlineQuickPick.ts b/src/outline/extendedOutlineQuickPick.ts new file mode 100644 index 0000000000..79c4e2b406 --- /dev/null +++ b/src/outline/extendedOutlineQuickPick.ts @@ -0,0 +1,81 @@ +import { DocumentSymbolParams, LanguageClient, TextDocumentIdentifier } from "vscode-languageclient/node"; +import { getActiveLanguageClient } from "../extension"; +import { ExtendedDocumentSymbolRequest } from "./protocol"; +import { Location, Position, QuickPick, QuickPickItem, Uri, window, workspace } from "vscode"; +import { getLThemeIcon } from "../themeUtils"; + +export class ExtendedOutlineQuickPick { + private api: QuickPick; + private client: LanguageClient; + public initialized: boolean; + + constructor() { + this.initialized = false; + } + + async initialize() { + this.api = window.createQuickPick(); + this.api.ignoreFocusOut = true; + this.api.onDidChangeActive((items: QuickPickItem[]) => { + if (items.length > 0) { + const active: QuickPickItem = items[0]; + const uri = active["uri"]; + const range = active["range"]; + if (uri !== undefined) { + workspace.openTextDocument(Uri.parse(uri)).then(doc => { + window.showTextDocument(doc, {preserveFocus: true, selection: range}); + }); + } else { + window.showTextDocument(window.activeTextEditor.document, {preserveFocus: true, selection: range}); + } + } + }); + this.api.onDidAccept(() => { + this.api.hide(); + }); + this.client = await getActiveLanguageClient(); + this.initialized = true; + } + + async open(uri: Uri) { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.api) { + return; + } + + const location = new Location(uri, new Position(0, 0)); + const params: DocumentSymbolParams = { + textDocument: TextDocumentIdentifier.create(location.uri.toString()) + }; + const symbols = await this.client.sendRequest(ExtendedDocumentSymbolRequest.type, params); + let quickPickItems: QuickPickItem[] = []; + for (const s of symbols) { + const icon = getLThemeIcon(s.kind).id; + const item = { + label: `$(${icon}) ${s.name}`, + description: s.detail.trim(), + uri: s.uri, + range: s.range + }; + quickPickItems.push(item); + if (icon === 'symbol-class' || icon === 'symbol-interface') { + const items: QuickPickItem[] = s.children.map(s => ({ + label: `$(${getLThemeIcon(s.kind).id}) ${s.name}`, + // custom quick pick has automatic space between label & description + description: s.detail.trim(), + uri: s.uri, + range: s.range + })); + quickPickItems = quickPickItems.concat(items); + } + } + this.api.items = quickPickItems; + this.api.activeItems = []; + this.api.show(); + } +} + +export const extendedOutlineQuickPick: ExtendedOutlineQuickPick = new ExtendedOutlineQuickPick(); diff --git a/src/outline/protocol.ts b/src/outline/protocol.ts new file mode 100644 index 0000000000..ffba1508a7 --- /dev/null +++ b/src/outline/protocol.ts @@ -0,0 +1,10 @@ +import { DocumentSymbol, DocumentSymbolParams, RequestType } from "vscode-languageclient"; + +export namespace ExtendedDocumentSymbolRequest { + export const type = new RequestType('java/extendedDocumentSymbol'); +} + +export interface ExtendedDocumentSymbol extends DocumentSymbol { + uri: string; + children?: ExtendedDocumentSymbol[]; +} \ No newline at end of file diff --git a/src/outputInfoCollector.ts b/src/outputInfoCollector.ts new file mode 100644 index 0000000000..c166e450cb --- /dev/null +++ b/src/outputInfoCollector.ts @@ -0,0 +1,43 @@ +import { OutputChannel, window, ViewColumn } from "vscode"; +import { logger } from "./log"; + +export class OutputInfoCollector implements OutputChannel { + private channel: OutputChannel = null; + + constructor(public name: string) { + this.channel = window.createOutputChannel(this.name); + } + + append(value: string): void { + logger.info(value); + this.channel.append(value); + } + + appendLine(value: string): void { + logger.info(value); + this.channel.appendLine(value); + } + + replace(value: string): void { + this.clear(); + this.append(value); + } + + clear(): void { + this.channel.clear(); + } + + show(preserveFocus?: boolean): void; + show(column?: ViewColumn, preserveFocus?: boolean): void; + show(column?: any, preserveFocus?: any) { + this.channel.show(column, preserveFocus); + } + + hide(): void { + this.channel.hide(); + } + + dispose(): void { + this.channel.dispose(); + } +} diff --git a/src/pasteAction.ts b/src/pasteAction.ts new file mode 100644 index 0000000000..e5e03d9d71 --- /dev/null +++ b/src/pasteAction.ts @@ -0,0 +1,86 @@ +'use strict'; + +import { TextEncoder } from 'util'; +import { commands, env, ExtensionContext, Range, TextEditor, Uri, window, workspace } from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { apiManager } from './apiManager'; +import { Commands } from './commands'; +import fs = require('fs'); + +export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand(Commands.CLIPBOARD_ONPASTE, () => { + registerOrganizeImportsOnPasteCommand(); + })); +} + +export async function registerOrganizeImportsOnPasteCommand(): Promise { + + const clipboardText: string = await env.clipboard.readText(); + const editor: TextEditor = window.activeTextEditor; + const documentText: string = editor.document.getText(); + const numCursors = editor.selections.length; + let bits: string[] = []; + if (numCursors > 1) { + bits = clipboardText.split(/\r?\n/); + } + const action = editor.edit(textInserter => { + for (let i = 0; i < numCursors; i++) { + const selection = editor.selections[i]; + const isCursorOnly = selection.isEmpty; + const text = bits.length === numCursors ? bits[i] : clipboardText; + if (isCursorOnly) { + textInserter.insert(selection.start, text); + } + else { + const start = selection.start; + const end = selection.end; + textInserter.replace(new Range(start, end), text); + } + } + }); + + action.then((wasApplied) => { + if (wasApplied && editor.document.languageId === "java") { + const updateImportsOnPasteEnabled = workspace.getConfiguration().get("java.updateImportsOnPaste.enabled", true); + if (!updateImportsOnPasteEnabled) { + return; + } + const fileURI = editor.document.uri.toString(); + const hasText: boolean = documentText !== null && /\S/.test(documentText); + if (hasText) { + // Organize imports silently to avoid surprising the user + commands.executeCommand(Commands.ORGANIZE_IMPORTS_SILENTLY, fileURI); + } else { + commands.executeCommand(Commands.ORGANIZE_IMPORTS, { textDocument: { uri: fileURI } }); + } + } + }); +} + +let serverReady = false; + +export async function pasteFile(folder: fs.PathLike): Promise { + const clipboardText: string = await env.clipboard.readText(); + let filePath = folder.toString(); + fs.stat(folder, async (err, stats) => { + // If given path to selected folder is invalid (no folder is selected) + if (filePath === clipboardText || stats.isFile() || (filePath === "." && workspace.workspaceFolders !== undefined)) { + filePath = workspace.workspaceFolders[0].uri.fsPath; + } + if (!serverReady) { + await apiManager.getApiInstance().serverReady().then( async () => { + serverReady = true; + }); + } + const fileString: string = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_PASTED_TEXT, filePath, clipboardText); + const fileUri = fileString !== null ? Uri.file(fileString) : null; + if (fileUri !== null){ + try { + await workspace.fs.writeFile(fileUri, new TextEncoder().encode(clipboardText)); + window.showTextDocument(fileUri, { preview: false }); + } catch (error: unknown) { + // Do nothing (file does not have write permissions) + } + } + }); +} \ No newline at end of file diff --git a/src/pasteEventHandler.ts b/src/pasteEventHandler.ts new file mode 100644 index 0000000000..c93cc0376a --- /dev/null +++ b/src/pasteEventHandler.ts @@ -0,0 +1,123 @@ +import { CancellationToken, commands, DataTransfer, DocumentPasteEdit as VDocumentPasteEdit, DocumentPasteEditProvider, DocumentPasteProviderMetadata, ExtensionContext, languages, Range, TextDocument, window, DocumentPasteEditContext, ProviderResult, DocumentPasteEdit, version } from "vscode"; +import { FormattingOptions, Location, WorkspaceEdit as PWorkspaceEdit } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { Commands } from "./commands"; +import { JAVA_SELECTOR } from "./standardLanguageClient"; +import * as semver from 'semver'; + +const TEXT_MIMETYPE: string = "text/plain"; +const MIMETYPES: DocumentPasteProviderMetadata = { + pasteMimeTypes: [TEXT_MIMETYPE], + providedPasteEditKinds: [] +}; + +/** + * Parameters for `Commands.HANDLE_PASTE_EVENT` + */ +interface PasteEventParams { + location: Location; + text: string; + formattingOptions: FormattingOptions; + copiedDocumentUri?: string; +} + +/** + * Response from jdt.ls for `Commands.HANDLE_PASTE_EVENT` that's similar, but not identical, to VS Code's paste edit. + * + * @see VDocumentPasteEdit + */ +interface PDocumentPasteEdit { + insertText: string; + additionalEdit: PWorkspaceEdit; +} + +/** + * Registers the vscode-java DocumentPasteEditProviders and sets them up to be disposed. + * + * @param context the extension context + */ +export function registerPasteEventHandler(context: ExtensionContext, languageClient: LanguageClient) { + if (languages["registerDocumentPasteEditProvider"]) { + context.subscriptions.push(languages["registerDocumentPasteEditProvider"](JAVA_SELECTOR, new PasteEditProvider(languageClient), MIMETYPES)); + } +} + +/** + * `DocumentPasteEditProvider` that delegates to jdt.ls to make any changes necessary to the pasted text and add any additional workspace edits. + */ +class PasteEditProvider implements DocumentPasteEditProvider { + + private languageClient: LanguageClient; + private copiedContent: string | undefined; + private copiedDocumentUri: string | undefined; + + constructor(languageClient: LanguageClient) { + this.languageClient = languageClient; + } + + + async prepareDocumentPaste?(document: TextDocument, _ranges: readonly Range[], dataTransfer: DataTransfer, _token: CancellationToken): Promise { + const copiedContent: string = await dataTransfer.get(TEXT_MIMETYPE).asString(); + if (copiedContent) { + this.copiedDocumentUri = document.uri.toString(); + this.copiedContent = copiedContent; + } + } + + async provideDocumentPasteEdits?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, context: DocumentPasteEditContext, token: CancellationToken): Promise { + + + const insertText: string = await dataTransfer.get(TEXT_MIMETYPE).asString(); + + // don't try to provide for multi character inserts; the implementation will get messy and the feature won't be that helpful + if (!insertText || (!!token && token.isCancellationRequested) || ranges.length !== 1) { + return null; + } + + const editorData = dataTransfer.get("vscode-editor-data")?.value; + const isSingleLineCopy = Boolean(editorData && JSON.parse(editorData).isFromEmptySelection); + const isFromSameDocument = this.copiedContent === insertText && this.copiedDocumentUri === document.uri.toString(); + if (isSingleLineCopy && isFromSameDocument) { + return undefined; // Let VS Code handle this normally + } + + const range = ranges[0]; + + const location: Location = { + range: this.languageClient.code2ProtocolConverter.asRange(range), + uri: document.uri.toString(), + }; + + const activeTextEditor = window.activeTextEditor; + + const pasteEventParams: PasteEventParams = { + location: location, + text: insertText, + copiedDocumentUri: this.copiedContent === insertText ? this.copiedDocumentUri : undefined, + formattingOptions: { + insertSpaces: activeTextEditor.options.insertSpaces, + tabSize: activeTextEditor.options.tabSize + } + }; + + try { + const pasteResponse: PDocumentPasteEdit = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.HANDLE_PASTE_EVENT, JSON.stringify(pasteEventParams)); + if (pasteResponse) { + const pasteEdit = { + insertText: pasteResponse.insertText, + additionalEdit: pasteResponse.additionalEdit ? await this.languageClient.protocol2CodeConverter.asWorkspaceEdit(pasteResponse.additionalEdit) : undefined + }; + if (semver.lt(version, '1.88.0')) { + return pasteEdit as DocumentPasteEdit; + } else { + return [ pasteEdit ] as DocumentPasteEdit[]; + } + } + } catch (e) { + // Do nothing + } + // either the handler returns null or encounters problems, fall back to return undefined to let VS Code ignore this handler + return undefined; + } + +} diff --git a/src/plugin.ts b/src/plugin.ts index b930e230ea..d35dcdaaf1 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -3,10 +3,52 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { Commands } from './commands'; +import { extensions } from 'vscode'; -let existingExtensions: Array; +export let existingExtensions: Array = []; +export let buildFilePatterns: Array = []; -export function collectJavaExtensions(extensions: vscode.Extension[]): string[] { +let javaShortcuts: Array | undefined; +export interface IJavaShortcut { + title: string; + command: string; + arguments?: any[]; +} +export function getShortcuts(): Array { + if (javaShortcuts === undefined) { + javaShortcuts = []; + const selfOwnedShortcuts = getShortcutsRegistration(extensions.getExtension(EXTENSION_ID)); + if (selfOwnedShortcuts) { + javaShortcuts.push(...selfOwnedShortcuts); + } + for (const extension of extensions.all) { + if (extension.id === EXTENSION_ID) { + continue; + } + const shortcuts = getShortcutsRegistration(extension); + if (shortcuts) { + javaShortcuts.push(...shortcuts); + } + } + } + return javaShortcuts; +} + +function getShortcutsRegistration(extension: vscode.Extension): Array | undefined { + if (!extension) { + return undefined; + } + const contributesSection = extension.packageJSON['contributes']; + if (contributesSection) { + const shortcuts = contributesSection['javaShortcuts']; + if (shortcuts && Array.isArray(shortcuts) && shortcuts.length) { + return shortcuts; + } + } + return undefined; +} + +export function collectJavaExtensions(extensions: readonly vscode.Extension[]): string[] { const result = []; if (extensions && extensions.length) { for (const extension of extensions) { @@ -26,30 +68,101 @@ export function collectJavaExtensions(extensions: vscode.Extension[]): stri return result; } -export function onExtensionChange(extensions: vscode.Extension[]) { - if (!existingExtensions) { - return; +export function collectBuildFilePattern(extensions: readonly vscode.Extension[]) { + const result = []; + if (extensions && extensions.length) { + for (const extension of extensions) { + const contributesSection = extension.packageJSON['contributes']; + if (contributesSection) { + const buildFilePatterns = contributesSection['javaBuildFilePatterns']; + if (Array.isArray(buildFilePatterns) && buildFilePatterns.length) { + result.push(...buildFilePatterns); + } + } + } } - const oldExtensions = new Set(existingExtensions.slice()); - const newExtensions = collectJavaExtensions(extensions); - let hasChanged = ( oldExtensions.size !== newExtensions.length); + buildFilePatterns = result.slice(); + return result; +} + +export function getBundlesToReload(): string[] { + const previousContributions: string[] = [...existingExtensions]; + const currentContributions = collectJavaExtensions(extensions.all); + if (isContributedPartUpdated(previousContributions, currentContributions)) { + return currentContributions; + } + + return []; +} + +export async function onExtensionChange(extensions: readonly vscode.Extension[]): Promise { + if (isContributedPartUpdated(buildFilePatterns, collectBuildFilePattern(extensions))) { + return promptToReload(); + } + + const bundlesToRefresh: string[] = getBundlesToReload(); + if (bundlesToRefresh.length) { + const success = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.REFRESH_BUNDLES, bundlesToRefresh); + if (!success) { + // if hot refreshing bundle fails, fallback to reload window. + return promptToReload(); + } + } +} + +function promptToReload() { + const msg = `Java Extension Contributions changed, reloading ${vscode.env.appName} is required for the changes to take effect.`; + const action = 'Reload'; + const restartId = Commands.RELOAD_WINDOW; + vscode.window.showWarningMessage(msg, action).then((selection) => { + if (action === selection) { + vscode.commands.executeCommand(restartId); + } + }); +} + +export function isContributedPartUpdated(oldContributedPart: Array, newContributedPart: Array) { + if (!oldContributedPart) { + return false; + } + const oldContribution = new Set(oldContributedPart.slice()); + const newContribution = newContributedPart; + const hasChanged = (oldContribution.size !== newContribution.length); if (!hasChanged) { - for (const newExtension of newExtensions) { - if (!oldExtensions.has(newExtension)) { - hasChanged = true; - break; + for (const newExtension of newContribution) { + if (!oldContribution.has(newExtension)) { + return true; } } } + return hasChanged; +} - if (hasChanged) { - const msg = 'Extensions to the Java Language Server changed, reloading Visual Studio Code is required for the changes to take effect.'; - const action = 'Reload'; - const restartId = Commands.RELOAD_WINDOW; - vscode.window.showWarningMessage(msg, action).then((selection) => { - if (action === selection) { - vscode.commands.executeCommand(restartId); +export function getContributedBuildTools(): IBuildTool[] { + const buildTypes: IBuildTool[] = []; + for (const extension of extensions.all) { + const javaBuildTools: IBuildTool[] = extension.packageJSON.contributes?.javaBuildTools; + if (!Array.isArray(javaBuildTools)) { + continue; + } + + for (const buildType of javaBuildTools) { + if (!isValidBuildTypeConfiguration(buildType)) { + continue; } - }); + buildTypes.push(buildType); + } } + return buildTypes; } + +export interface IBuildTool { + displayName: string; + buildFileNames: string[]; +} + +function isValidBuildTypeConfiguration(buildType: IBuildTool): boolean { + return !!buildType.displayName && !!buildType.buildFileNames; +} + +const EXTENSION_ID = 'redhat.java'; diff --git a/src/pom/pomCodeActionProvider.ts b/src/pom/pomCodeActionProvider.ts new file mode 100644 index 0000000000..14f1c61bce --- /dev/null +++ b/src/pom/pomCodeActionProvider.ts @@ -0,0 +1,106 @@ +'use strict'; + +import { CodeActionProvider, CodeAction, TextDocument, Range, Selection, CodeActionContext, CancellationToken, ProviderResult, Command, CodeActionKind, Diagnostic, WorkspaceEdit, EndOfLine, ExtensionContext, commands, CodeActionProviderMetadata, workspace, Uri, window, TextEditor } from "vscode"; +import { Commands } from "../commands"; + +export class PomCodeActionProvider implements CodeActionProvider { + constructor(context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand("_java.projectConfiguration.saveAndUpdate", async (uri: Uri) => { + const document: TextDocument = await workspace.openTextDocument(uri); + await document.save(); + commands.executeCommand(Commands.CONFIGURATION_UPDATE, uri); + })); + } + + provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(Command | CodeAction)[]> { + if (context?.diagnostics?.length && context.diagnostics[0].source === "Java") { + return this.collectCodeActions(document, context.diagnostics); + } + + return undefined; + } + + collectCodeActions(document: TextDocument, diagnostics: readonly Diagnostic[]): CodeAction[] { + const codeActions: CodeAction[] = []; + for (const diagnostic of diagnostics) { + if (diagnostic.message?.startsWith("Plugin execution not covered by lifecycle configuration")) { + const indentation = this.getNewTextIndentation(document, diagnostic); + const saveAndUpdateConfigCommand: Command = { + title: "Save and reload project", + command: "_java.projectConfiguration.saveAndUpdate", + arguments: [document.uri], + }; + + const action1 = new CodeAction("Enable this execution in project configuration phase", CodeActionKind.QuickFix.append("pom")); + action1.edit = new WorkspaceEdit(); + action1.edit.insert(document.uri, diagnostic.range.end, `${indentation}`); + action1.command = saveAndUpdateConfigCommand; + codeActions.push(action1); + + const action2 = new CodeAction("Enable this execution in project build phase", CodeActionKind.QuickFix.append("pom")); + action2.edit = new WorkspaceEdit(); + action2.edit.insert(document.uri, diagnostic.range.end, `${indentation}`); + action2.command = saveAndUpdateConfigCommand; + codeActions.push(action2); + + const action3 = new CodeAction("Mark this execution as ignored in pom.xml", CodeActionKind.QuickFix.append("pom")); + action3.edit = new WorkspaceEdit(); + action3.edit.insert(document.uri, diagnostic.range.end, `${indentation}`); + action3.command = saveAndUpdateConfigCommand; + codeActions.push(action3); + } else if (diagnostic.message?.startsWith("The build file has been changed")) { + const reloadProjectAction = new CodeAction("Reload project", CodeActionKind.QuickFix); + reloadProjectAction.command = { + title: "Reload Project", + command: Commands.CONFIGURATION_UPDATE, + arguments: [document.uri], + }; + codeActions.push(reloadProjectAction); + } + } + + return codeActions; + } + + getNewTextIndentation(document: TextDocument, diagnostic: Diagnostic): string { + const textline = document.lineAt(diagnostic.range.end.line); + if (textline.text.lastIndexOf("") > diagnostic.range.end.character) { + return ""; + } + + let tabSize: number = 2; // default value + let insertSpaces: boolean = true; // default value + const activeEditor: TextEditor | undefined = window.activeTextEditor; + if (activeEditor && activeEditor.document.uri.toString() === document.uri.toString()) { + tabSize = Number(activeEditor.options.tabSize); + insertSpaces = Boolean(activeEditor.options.insertSpaces); + } + + const lineSeparator = document.eol === EndOfLine.LF ? "\r" : "\r\n"; + let newIndentation = lineSeparator + textline.text.substring(0, textline.firstNonWhitespaceCharacterIndex); + if (insertSpaces) { + for (let i = 0; i < tabSize; i++) { + newIndentation += ' '; // insert a space char. + } + } else { + newIndentation += ' '; // insert a tab char. + } + + return newIndentation; + } +} + +export const pomCodeActionMetadata: CodeActionProviderMetadata = { + providedCodeActionKinds: [ + CodeActionKind.QuickFix.append("pom") + ], + documentation: [ + { + kind: CodeActionKind.QuickFix.append("pom"), + command: { + title: "Learn more about not covered Maven execution", + command: Commands.NOT_COVERED_EXECUTION + } + } + ], +}; diff --git a/src/promiseUtil.ts b/src/promiseUtil.ts new file mode 100644 index 0000000000..b38510e68e --- /dev/null +++ b/src/promiseUtil.ts @@ -0,0 +1,13 @@ +export class Deferred { + readonly promise: Promise; + + resolve: (result: T) => void; + reject: (error: any) => void; + + constructor() { + this.promise= new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } +} diff --git a/src/protocol.ts b/src/protocol.ts index aad0512cb6..c31b5a590e 100644 --- a/src/protocol.ts +++ b/src/protocol.ts @@ -1,7 +1,19 @@ 'use strict'; -import { RequestType, NotificationType, TextDocumentIdentifier, ExecuteCommandParams, CodeActionParams, WorkspaceEdit, FormattingOptions } from 'vscode-languageclient'; import { Command, Range } from 'vscode'; +import { + CodeActionParams, + ExecuteCommandParams, + FormattingOptions, + Location, + NotificationType, + RequestType, + SymbolInformation, + TextDocumentIdentifier, + TextDocumentPositionParams, + WorkspaceEdit, + WorkspaceSymbolParams, +} from 'vscode-languageclient'; /** * The message type. Copied from vscode protocol @@ -10,19 +22,19 @@ export enum MessageType { /** * An error message. */ - Error = 1, + error = 1, /** * A warning message. */ - Warning = 2, + warning = 2, /** * An information message. */ - Info = 3, + info = 3, /** * A log message. */ - Log = 4, + log = 4, } /** @@ -43,65 +55,106 @@ export enum FeatureStatus { automatic = 2, } +export enum EventType { + classpathUpdated = 100, + projectsImported = 200, + projectsDeleted = 210, + incompatibleGradleJdkIssue = 300, + upgradeGradleWrapper = 400, + sourceInvalidated = 500, +} + export enum CompileWorkspaceStatus { - FAILED = 0, - SUCCEED = 1, - WITHERROR = 2, - CANCELLED = 3, + failed = 0, + succeed = 1, + withError = 2, + cancelled = 3, +} + +export enum AccessorKind { + getter = 0, + setter = 1, + both = 2 } export interface StatusReport { - message: string; - type: string; + message: string; + type: string; } export interface ProgressReport { - id: string; - task: string; - subTask: string; - status: string; - workDone: number; - totalWork: number; - complete: boolean; + token: string; + value: any; + complete: boolean; +} + +export enum ProgressKind { + begin = "begin", + report = "report", + end = "end" } export interface ActionableMessage { - severity: MessageType; - message: string; - data?: any; - commands?: Command[]; + severity: MessageType; + message: string; + data?: any; + commands?: Command[]; +} + +export interface EventNotification { + eventType: EventType; + data?: any; } export namespace StatusNotification { - export const type = new NotificationType('language/status'); + export const type = new NotificationType('language/status'); } -export namespace ProgressReportNotification { - export const type = new NotificationType('language/progressReport'); +// See https://github.com/microsoft/vscode-languageserver-node/blob/release/client/8.1.0/jsonrpc/src/common/connection.ts#L53-L55 +export namespace ProgressNotification { + export const type = new NotificationType('$/progress'); } export namespace ClassFileContentsRequest { - export const type = new RequestType ('java/classFileContents'); + export const type = new RequestType ('java/classFileContents'); } export namespace ProjectConfigurationUpdateRequest { - export const type = new NotificationType ('java/projectConfigurationUpdate'); + export const type = new NotificationType ('java/projectConfigurationUpdate'); + export const typeV2 = new NotificationType ('java/projectConfigurationsUpdate'); +} + +export interface ProjectConfigurationsUpdateParam { + identifiers: TextDocumentIdentifier[]; } export namespace ActionableNotification { - export const type = new NotificationType('language/actionableNotification'); + export const type = new NotificationType('language/actionableNotification'); +} + +export namespace EventNotification { + export const type = new NotificationType('language/eventNotification'); } export namespace CompileWorkspaceRequest { - export const type = new RequestType('java/buildWorkspace'); + export const type = new RequestType('java/buildWorkspace'); +} + +export namespace BuildProjectRequest { + export const type = new RequestType('java/buildProjects'); +} + +export interface BuildProjectParams { + identifiers: TextDocumentIdentifier[]; + isFullBuild: boolean; } export namespace ExecuteClientCommandRequest { - export const type = new RequestType('workspace/executeClientCommand'); + export const type = new RequestType('workspace/executeClientCommand'); } -export namespace SendNotificationRequest { - export const type = new RequestType('workspace/notify'); +export namespace ServerNotification { + export const type = new NotificationType('workspace/notify'); } export interface SourceAttachmentRequest { @@ -131,12 +184,12 @@ export interface OverridableMethod { } export interface OverridableMethodsResponse { - type: string; - methods: OverridableMethod[]; + type: string; + methods: OverridableMethod[]; } export namespace ListOverridableMethodsRequest { - export const type = new RequestType('java/listOverridableMethods'); + export const type = new RequestType('java/listOverridableMethods'); } export interface AddOverridableMethodParams { @@ -145,13 +198,15 @@ export interface AddOverridableMethodParams { } export namespace AddOverridableMethodsRequest { - export const type = new RequestType('java/addOverridableMethods'); + export const type = new RequestType('java/addOverridableMethods'); } export interface VariableBinding { bindingKey: string; name: string; type: string; + isField: boolean; + isSelected?: boolean; } export interface CheckHashCodeEqualsResponse { @@ -161,7 +216,7 @@ export interface CheckHashCodeEqualsResponse { } export namespace CheckHashCodeEqualsStatusRequest { - export const type = new RequestType('java/checkHashCodeEqualsStatus'); + export const type = new RequestType('java/checkHashCodeEqualsStatus'); } export interface GenerateHashCodeEqualsParams { @@ -171,11 +226,15 @@ export interface GenerateHashCodeEqualsParams { } export namespace GenerateHashCodeEqualsRequest { - export const type = new RequestType('java/generateHashCodeEquals'); + export const type = new RequestType('java/generateHashCodeEquals'); } export namespace OrganizeImportsRequest { - export const type = new RequestType('java/organizeImports'); + export const type = new RequestType('java/organizeImports'); +} + +export namespace CleanupRequest { + export const type = new RequestType('java/cleanup'); } export interface ImportCandidate { @@ -195,7 +254,7 @@ export interface CheckToStringResponse { } export namespace CheckToStringStatusRequest { - export const type = new RequestType('java/checkToStringStatus'); + export const type = new RequestType('java/checkToStringStatus'); } export interface GenerateToStringParams { @@ -204,7 +263,7 @@ export interface GenerateToStringParams { } export namespace GenerateToStringRequest { - export const type = new RequestType('java/generateToString'); + export const type = new RequestType('java/generateToString'); } export interface AccessorField { @@ -212,10 +271,15 @@ export interface AccessorField { isStatic: boolean; generateGetter: boolean; generateSetter: boolean; + typeName: string; +} + +export interface AccessorCodeActionParams extends CodeActionParams { + kind: AccessorKind; } -export namespace ResolveUnimplementedAccessorsRequest { - export const type = new RequestType('java/resolveUnimplementedAccessors'); +export namespace AccessorCodeActionRequest { + export const type = new RequestType('java/resolveUnimplementedAccessors'); } export interface GenerateAccessorsParams { @@ -224,7 +288,7 @@ export interface GenerateAccessorsParams { } export namespace GenerateAccessorsRequest { - export const type = new RequestType('java/generateAccessors'); + export const type = new RequestType('java/generateAccessors'); } export interface MethodBinding { @@ -239,7 +303,7 @@ export interface CheckConstructorsResponse { } export namespace CheckConstructorStatusRequest { - export const type = new RequestType('java/checkConstructorsStatus'); + export const type = new RequestType('java/checkConstructorsStatus'); } export interface GenerateConstructorsParams { @@ -249,7 +313,7 @@ export interface GenerateConstructorsParams { } export namespace GenerateConstructorsRequest { - export const type = new RequestType('java/generateConstructors'); + export const type = new RequestType('java/generateConstructors'); } export interface DelegateField { @@ -262,7 +326,7 @@ export interface CheckDelegateMethodsResponse { } export namespace CheckDelegateMethodsStatusRequest { - export const type = new RequestType('java/checkDelegateMethodsStatus'); + export const type = new RequestType('java/checkDelegateMethodsStatus'); } export interface DelegateEntry { @@ -276,7 +340,7 @@ export interface GenerateDelegateMethodsParams { } export namespace GenerateDelegateMethodsRequest { - export const type = new RequestType('java/generateDelegateMethods'); + export const type = new RequestType('java/generateDelegateMethods'); } export interface RenamePosition { @@ -288,6 +352,7 @@ export interface RenamePosition { export interface RefactorWorkspaceEdit { edit: WorkspaceEdit; command?: Command; + errorMessage?: string; } export interface GetRefactorEditParams { @@ -298,5 +363,144 @@ export interface GetRefactorEditParams { } export namespace GetRefactorEditRequest { - export const type = new RequestType('java/getRefactorEdit'); + export const type = new RequestType('java/getRefactorEdit'); +} + +export namespace GetChangeSignatureInfoRequest { + export const type = new RequestType('java/getChangeSignatureInfo'); +} + +export interface SelectionInfo { + name: string; + length: number; + offset: number; + params?: string[]; +} + +export interface ChangeSignatureInfo { + methodIdentifier: string; + modifier: string; + returnType: string; + methodName: string; + parameters: any; + exceptions: any; + errorMessage: string; +} + +export interface InferSelectionParams { + command: string; + context: CodeActionParams; +} + +export namespace InferSelectionRequest { + export const type = new RequestType('java/inferSelection'); +} + +export interface PackageNode { + displayName: string; + uri: string; + path: string; + project: string; + isDefaultPackage: boolean; + isParentOfSelectedFile: boolean; +} + +export interface MoveParams { + moveKind: string; + sourceUris: string[]; + params: CodeActionParams; + destination?: any; + updateReferences?: boolean; +} + +export interface MoveDestinationsResponse { + errorMessage?: string; + destinations: any[]; +} + +export namespace GetMoveDestinationsRequest { + export const type = new RequestType('java/getMoveDestinations'); +} + +export namespace MoveRequest { + export const type = new RequestType('java/move'); +} + +export interface SearchSymbolParams extends WorkspaceSymbolParams { + projectName: string; + maxResults?: number; + sourceOnly?: boolean; +} + +export namespace SearchSymbols { + export const type = new RequestType('java/searchSymbols'); +} + +export interface FindLinksParams { + type: string; + position: TextDocumentPositionParams; +} + +export interface LinkLocation extends Location { + displayName: string; + kind: string; +} + +export namespace FindLinks { + export const type = new RequestType('java/findLinks'); +} + +export interface RenameFilesParams { + files: Array<{ oldUri: string; newUri: string }>; +} + +export namespace WillRenameFiles { + export const type = new RequestType('workspace/willRenameFiles'); +} + +export interface GradleCompatibilityInfo { + projectUri: string; + message: string; + highestJavaVersion: string; + recommendedGradleVersion: string; +} + +export interface UpgradeGradleWrapperInfo { + projectUri: string; + message: string; + recommendedGradleVersion: string; +} + +export interface Member { + name: string; + typeName: string; + parameters: string[]; + handleIdentifier: string; +} + +export interface CheckExtractInterfaceStatusResponse { + members: Member[]; + subTypeName: string; + destinationResponse: MoveDestinationsResponse; +} + +export namespace CheckExtractInterfaceStatusRequest { + export const type = new RequestType('java/checkExtractInterfaceStatus'); +} + +export interface ValidateDocumentParams { + textDocument: TextDocumentIdentifier; +} + +export namespace ValidateDocumentNotification { + export const type = new NotificationType('java/validateDocument'); +} + +export interface SourceInvalidatedEvent { + /** + * The package fragment roots that get new source attachments. + * The key is its root path, the value means if its source is + * automatically downloaded. + */ + affectedRootPaths: { [key: string]: boolean }; } diff --git a/src/providerDispatcher.ts b/src/providerDispatcher.ts new file mode 100644 index 0000000000..3d4e294148 --- /dev/null +++ b/src/providerDispatcher.ts @@ -0,0 +1,221 @@ +'use strict'; + +import { CancellationToken, commands, DocumentSymbol, DocumentSymbolProvider, Event, ExtensionContext, Hover, HoverProvider, languages, MarkdownString, MarkedString, Position, Range, SymbolInformation, SymbolKind, TextDocument, TextDocumentContentProvider, Uri, workspace, WorkspaceSymbolProvider } from "vscode"; +import { DocumentSymbol as clientDocumentSymbol, DocumentSymbolRequest, HoverRequest, SymbolInformation as clientSymbolInformation, WorkspaceSymbolRequest } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { apiManager } from "./apiManager"; +import { Commands } from "./commands"; +import { fixJdtLinksInDocumentation, getActiveLanguageClient } from "./extension"; +import { createClientHoverProvider } from "./hoverAction"; +import { ClassFileContentsRequest } from "./protocol"; +import { ServerMode } from "./settings"; + +export interface ProviderOptions { + contentProviderEvent: Event; +} + +export interface ProviderHandle { + handles: any[]; +} + +export function registerClientProviders(context: ExtensionContext, options: ProviderOptions): ProviderHandle { + const hoverProvider = new ClientHoverProvider(); + context.subscriptions.push(languages.registerHoverProvider('java', hoverProvider)); + + const symbolProvider = createDocumentSymbolProvider(); + context.subscriptions.push(languages.registerDocumentSymbolProvider('java', symbolProvider)); + + const jdtProvider = createJDTContentProvider(options); + context.subscriptions.push(workspace.registerTextDocumentContentProvider('jdt', jdtProvider)); + + const classProvider = createClassContentProvider(options); + context.subscriptions.push(workspace.registerTextDocumentContentProvider('class', classProvider)); + + overwriteWorkspaceSymbolProvider(context); + + return { + handles: [hoverProvider, symbolProvider, jdtProvider, classProvider] + }; +} + +export class ClientHoverProvider implements HoverProvider { + private delegateProvider; + + async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + + if (!languageClient) { + return undefined; + } + + const serverMode: ServerMode = apiManager.getApiInstance().serverMode; + if (serverMode === ServerMode.standard) { + if (!this.delegateProvider) { + this.delegateProvider = createClientHoverProvider(languageClient); + } + const hover = await this.delegateProvider.provideHover(document, position, token); + return fixJdtSchemeHoverLinks(hover); + } else { + const params = { + textDocument: languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document), + position: languageClient.code2ProtocolConverter.asPosition(position) + }; + const hoverResponse = await languageClient.sendRequest(HoverRequest.type, params, token); + const hover = languageClient.protocol2CodeConverter.asHover(hoverResponse); + return fixJdtSchemeHoverLinks(hover); + } + } +} + +function createJDTContentProvider(options: ProviderOptions): TextDocumentContentProvider { + return { + onDidChange: options.contentProviderEvent, + provideTextDocumentContent: async (uri: Uri, token: CancellationToken): Promise => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + + if (!languageClient) { + return ''; + } + + return languageClient.sendRequest(ClassFileContentsRequest.type, { uri: uri.toString() }, token).then((v: string): string => { + return v || ''; + }); + } + }; +} + +function createClassContentProvider(options: ProviderOptions): TextDocumentContentProvider { + return { + onDidChange: options.contentProviderEvent, + provideTextDocumentContent: async (uri: Uri, token: CancellationToken): Promise => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + + if (!languageClient) { + return ''; + } + const originalUri = uri.toString().replace(/^class/, "file"); + const decompiledContent: string = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_DECOMPILED_SOURCE, originalUri); + if (!decompiledContent) { + console.log(`Error while getting decompiled source : ${originalUri}`); + return "Error while getting decompiled source."; + } else { + return decompiledContent; + } + } + }; +} + +function createDocumentSymbolProvider(): DocumentSymbolProvider { + return { + provideDocumentSymbols: async (document: TextDocument, token: CancellationToken): Promise => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + + if (!languageClient) { + return []; + } + + const params = { + textDocument: languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document), + }; + const symbolResponse = await languageClient.sendRequest(DocumentSymbolRequest.type, params, token); + if (!symbolResponse || !symbolResponse.length) { + return []; + } + + if ((symbolResponse[0]).containerName) { + return languageClient.protocol2CodeConverter.asSymbolInformations(symbolResponse); + } + + return languageClient.protocol2CodeConverter.asDocumentSymbols(symbolResponse); + } + }; +} + +const START_OF_DOCUMENT = new Range(new Position(0, 0), new Position(0, 0)); + +function createWorkspaceSymbolProvider(existingWorkspaceSymbolProvider: WorkspaceSymbolProvider): WorkspaceSymbolProvider { + return { + provideWorkspaceSymbols: async (query: string, token: CancellationToken) => { + // This is a workaround until vscode add support for qualified symbol search which is tracked by + // https://github.com/microsoft/vscode/issues/98125 + const result = existingWorkspaceSymbolProvider.provideWorkspaceSymbols(query, token); + if (query.indexOf('.') > -1) { // seems like a qualified name + return new Promise((resolve) => { + ((result as Promise)).then((symbols) => { + if (symbols === null) { + resolve(null); + } else { + resolve(symbols?.map((s) => { + s.name = `${s.containerName}.${s.name}`; + return s; + })); + } + }); + }); + } + return result; + }, + resolveWorkspaceSymbol: async (symbol: SymbolInformation, token: CancellationToken): Promise => { + const range = symbol.location.range; + if (range && !range.isEqual(START_OF_DOCUMENT)) { + return symbol; + } + + const languageClient = await getActiveLanguageClient(); + const serializableSymbol = { + name: symbol.name, + // Cannot serialize SymbolKind as number, because GSON + lsp4j.SymbolKind expect a name. + kind: SymbolKind[symbol.kind], + location: { + uri: languageClient.code2ProtocolConverter.asUri(symbol.location.uri), + range: languageClient.code2ProtocolConverter.asRange(symbol.location.range) + }, + containerName: symbol.containerName + }; + + const response = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_WORKSPACE_SYMBOL, JSON.stringify(serializableSymbol)); + if (token.isCancellationRequested) { + return undefined; + } + return languageClient.protocol2CodeConverter.asSymbolInformation(response as clientSymbolInformation); + } + }; +} + +function overwriteWorkspaceSymbolProvider(context: ExtensionContext): void { + const disposable = apiManager.getApiInstance().onDidServerModeChange(async (mode) => { + if (mode === ServerMode.standard) { + const feature = (await getActiveLanguageClient()).getFeature(WorkspaceSymbolRequest.method); + const providers = feature.getProviders(); + if (providers && providers.length > 0) { + feature.clear(); + const workspaceSymbolProvider = createWorkspaceSymbolProvider(providers[0]); + context.subscriptions.push(languages.registerWorkspaceSymbolProvider(workspaceSymbolProvider)); + disposable.dispose(); + } + } + }); +} + +/** + * Returns the hover with all jdt:// links replaced with a command:// link that opens the jdt URI. + * + * VS Code doesn't render links with the `jdt` scheme in hover popups. + * To get around this, you can create a command:// link that invokes a command that opens the corresponding URI. + * VS Code will render command:// links in hover pop ups if they are marked as trusted. + * + * @param hover The hover to fix the jdt:// links for + * @returns the hover with all jdt:// links replaced with a command:// link that opens the jdt URI + */ +export function fixJdtSchemeHoverLinks(hover: Hover): Hover { + const newContents: (MarkedString | MarkdownString)[] = []; + for (const content of hover.contents) { + if (content instanceof MarkdownString) { + newContents.push(fixJdtLinksInDocumentation(content)); + } else { + newContents.push(content); + } + } + hover.contents = newContents; + return hover; +} \ No newline at end of file diff --git a/src/refactorAction.ts b/src/refactorAction.ts index 658e8e0825..f8b37fb54c 100644 --- a/src/refactorAction.ts +++ b/src/refactorAction.ts @@ -1,9 +1,14 @@ 'use strict'; -import { commands, window, ExtensionContext, workspace, Position, Uri, TextDocument } from 'vscode'; -import { LanguageClient, FormattingOptions } from 'vscode-languageclient'; +import { existsSync } from 'fs'; +import * as path from 'path'; +import { commands, ExtensionContext, Position, QuickPickItem, TextDocument, Uri, window, workspace } from 'vscode'; +import { FormattingOptions, WorkspaceEdit, RenameFile, DeleteFile, TextDocumentEdit, CodeActionParams, SymbolInformation } from 'vscode-languageclient'; +import { LanguageClient } from 'vscode-languageclient/node'; import { Commands as javaCommands } from './commands'; -import { GetRefactorEditRequest, RefactorWorkspaceEdit, RenamePosition } from './protocol'; +import { GetRefactorEditRequest, MoveRequest, RefactorWorkspaceEdit, RenamePosition, GetMoveDestinationsRequest, SearchSymbols, SelectionInfo, InferSelectionRequest, GetChangeSignatureInfoRequest, ChangeSignatureInfo } from './protocol'; +import { ChangeSignaturePanel } from './refactoring/changeSignaturePanel'; +import { getExtractInterfaceArguments, revealExtractedInterface } from './refactoring/extractInterface'; export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) { registerApplyRefactorCommand(languageClient, context); @@ -14,7 +19,7 @@ function registerApplyRefactorCommand(languageClient: LanguageClient, context: E try { const uri: Uri = Uri.parse(position.uri); const document: TextDocument = await workspace.openTextDocument(uri); - if (document == null) { + if (document === null) { return; } @@ -30,11 +35,18 @@ function registerApplyRefactorCommand(languageClient: LanguageClient, context: E context.subscriptions.push(commands.registerCommand(javaCommands.APPLY_REFACTORING_COMMAND, async (command: string, params: any, commandInfo: any) => { if (command === 'extractVariable' + || command === 'assignVariable' || command === 'extractVariableAllOccurrence' || command === 'extractConstant' || command === 'extractMethod' || command === 'extractField' - || command === 'convertVariableToField') { + || command === 'extractInterface' + || command === 'changeSignature' + || command === 'assignField' + || command === 'convertVariableToField' + || command === 'invertVariable' + || command === 'introduceParameter' + || command === 'convertAnonymousClassToNestedCommand') { const currentEditor = window.activeTextEditor; if (!currentEditor || !currentEditor.options) { return; @@ -45,24 +57,68 @@ function registerApplyRefactorCommand(languageClient: LanguageClient, context: E insertSpaces: currentEditor.options.insertSpaces, }; const commandArguments: any[] = []; - if (command === 'extractField' || command === 'convertVariableToField') { - if (commandInfo.initializedScopes && Array.isArray(commandInfo.initializedScopes)) { - const scopes: any[] = commandInfo.initializedScopes; - let initializeIn: string; - if (scopes.length === 1) { - initializeIn = scopes[0]; - } else if (scopes.length > 1) { - initializeIn = await window.showQuickPick(scopes, { - placeHolder: "Initialize the field in", - }); - + if (command === 'extractField') { + if (!params || !params.range) { + return; + } + if (params.range.start.character === params.range.end.character && params.range.start.line === params.range.end.line) { + const expression: SelectionInfo = await getExpression(command, params, languageClient); + if (!expression) { + return; + } + if (expression.params && Array.isArray(expression.params)) { + const initializeIn = await resolveScopes(expression.params); if (!initializeIn) { return; } + commandArguments.push(initializeIn); + } + commandArguments.push(expression); + } else { + if (commandInfo.initializedScopes && Array.isArray(commandInfo.initializedScopes)) { + const initializeIn = await resolveScopes(commandInfo.initializedScopes); + if (!initializeIn) { + return; + } + commandArguments.push(initializeIn); + } + } + } else if (command === 'convertVariableToField') { + if (commandInfo.initializedScopes && Array.isArray(commandInfo.initializedScopes)) { + const initializeIn = await resolveScopes(commandInfo.initializedScopes); + if (!initializeIn) { + return; } - commandArguments.push(initializeIn); } + } else if (command === 'extractMethod' + || command === 'extractVariableAllOccurrence' + || command === 'extractVariable' + || command === 'extractConstant') { + if (!params || !params.range) { + return; + } + if (params.range.start.character === params.range.end.character && params.range.start.line === params.range.end.line) { + const expression = await getExpression(command, params, languageClient); + if (!expression) { + return; + } + commandArguments.push(expression); + } + } else if (command === 'extractInterface') { + const args = await getExtractInterfaceArguments(languageClient, params); + if (args.length === 0) { + return; + } + commandArguments.push(...args); + } else if (command === 'changeSignature') { + const changeSignatureInfo: ChangeSignatureInfo = await languageClient.sendRequest(GetChangeSignatureInfoRequest.type, params); + if (changeSignatureInfo.errorMessage !== undefined) { + window.showWarningMessage(changeSignatureInfo.errorMessage); + return; + } + ChangeSignaturePanel.render(context.extensionUri, languageClient, command, params, formattingOptions, changeSignatureInfo); + return; } const result: RefactorWorkspaceEdit = await languageClient.sendRequest(GetRefactorEditRequest.type, { @@ -72,22 +128,423 @@ function registerApplyRefactorCommand(languageClient: LanguageClient, context: E commandArguments, }); - if (!result || !result.edit) { + await applyRefactorEdit(languageClient, result); + + if (command === 'extractInterface') { + await revealExtractedInterface(result); + } + } else if (command === 'moveFile') { + if (!commandInfo || !commandInfo.uri) { return; } - const edit = languageClient.protocol2CodeConverter.asWorkspaceEdit(result.edit); - if (edit) { - await workspace.applyEdit(edit); + await moveFile(languageClient, [Uri.parse(commandInfo.uri)]); + } else if (command === 'moveInstanceMethod') { + await moveInstanceMethod(languageClient, params, commandInfo); + } else if (command === 'moveStaticMember') { + await moveStaticMember(languageClient, params, commandInfo); + } else if (command === 'moveType') { + await moveType(languageClient, params, commandInfo); + } + })); +} + +async function resolveScopes(scopes: any[]): Promise { + let initializeIn: string; + if (scopes.length === 1) { + initializeIn = scopes[0]; + } else if (scopes.length > 1) { + initializeIn = await window.showQuickPick(scopes, { + placeHolder: "Initialize the field in", + }); + + if (!initializeIn) { + return undefined; + } + } + return initializeIn; +} + +async function getExpression(command: string, params: any, languageClient: LanguageClient): Promise { + const expressions: SelectionInfo[] = await languageClient.sendRequest(InferSelectionRequest.type, { + command: command, + context: params, + }); + const options: IExpressionItem[] = []; + for (const expression of expressions) { + const extractItem: IExpressionItem = { + label: expression.name, + length: expression.length, + offset: expression.offset, + params: expression.params, + }; + options.push(extractItem); + } + let resultItem: IExpressionItem; + if (options.length === 1) { + resultItem = options[0]; + } else if (options.length > 1) { + let commandMessage: string; + switch (command) { + case 'extractMethod': + commandMessage = 'extract to method'; + break; + case 'extractVariableAllOccurrence': + case 'extractVariable': + commandMessage = 'extract to variable'; + break; + case 'extractConstant': + commandMessage = 'extract to constant'; + break; + case 'extractField': + commandMessage = 'extract to field'; + break; + default: + return undefined; + } + resultItem = await window.showQuickPick(options, { + placeHolder: `Select an expression you want to ${commandMessage}`, + }); + } + if (!resultItem) { + return undefined; + } + const resultExpression: SelectionInfo = { + name: resultItem.label, + length: resultItem.length, + offset: resultItem.offset, + params: resultItem.params, + }; + return resultExpression; +} + +interface IExpressionItem extends QuickPickItem { + label: string; + length: number; + offset: number; + params?: string[]; +} + +async function applyRefactorEdit(languageClient: LanguageClient, refactorEdit: RefactorWorkspaceEdit) { + if (!refactorEdit) { + return; + } + + if (refactorEdit.errorMessage) { + window.showErrorMessage(refactorEdit.errorMessage); + return; + } + + if (refactorEdit.edit) { + const edit = await languageClient.protocol2CodeConverter.asWorkspaceEdit(refactorEdit.edit); + if (edit) { + await workspace.applyEdit(edit); + } + } + + if (refactorEdit.command) { + await new Promise(resolve => setTimeout(resolve, 400)); + if (refactorEdit.command.arguments) { + await commands.executeCommand(refactorEdit.command.command, ...refactorEdit.command.arguments); + } else { + await commands.executeCommand(refactorEdit.command.command); + } + } +} + +async function moveFile(languageClient: LanguageClient, fileUris: Uri[]) { + if (!hasCommonParent(fileUris)) { + window.showErrorMessage("Moving files from different directories are not supported. Please make sure they are from the same directory."); + return; + } + + const moveDestinations = await languageClient.sendRequest(GetMoveDestinationsRequest.type, { + moveKind: 'moveResource', + sourceUris: fileUris.map(uri => uri.toString()), + params: null, + }); + if (!moveDestinations || !moveDestinations.destinations || !moveDestinations.destinations.length) { + window.showErrorMessage("Cannot find available Java packages to move the selected files to."); + return; + } + + const packageNodeItems = moveDestinations.destinations.map((packageNode) => { + const packageUri: Uri = packageNode.uri ? Uri.parse(packageNode.uri) : null; + const displayPath: string = packageUri ? workspace.asRelativePath(packageUri, true) : packageNode.path; + return { + label: (packageNode.isParentOfSelectedFile ? '* ' : '') + packageNode.displayName, + description: displayPath, + packageNode, + }; + }); + + const placeHolder = (fileUris.length === 1) ? `Choose the target package for ${getFileNameFromUri(fileUris[0])}.` + : `Choose the target package for ${fileUris.length} selected files.`; + const selectPackageNodeItem = await window.showQuickPick(packageNodeItems, { + placeHolder, + }); + if (!selectPackageNodeItem) { + return; + } + + const packageUri: Uri = selectPackageNodeItem.packageNode.uri ? Uri.parse(selectPackageNodeItem.packageNode.uri) : null; + if (packageUri && packageUri.fsPath) { + const duplicatedFiles: string[] = []; + const moveUris: Uri[] = []; + for (const uri of fileUris) { + const fileName: string = getFileNameFromUri(uri); + if (existsSync(path.join(packageUri.fsPath, fileName))) { + duplicatedFiles.push(fileName); + } else { + moveUris.push(uri); } - - if (result.command) { - if (result.command.arguments) { - await commands.executeCommand(result.command.command, ...result.command.arguments); - } else { - await commands.executeCommand(result.command.command); + } + + if (duplicatedFiles.length) { + window.showWarningMessage(`The files '${duplicatedFiles.join(',')}' already exist in the package '${selectPackageNodeItem.packageNode.displayName}'. The move operation will ignore them.`); + } + + if (!moveUris.length) { + return; + } + + fileUris = moveUris; + } + + const refactorEdit: RefactorWorkspaceEdit = await languageClient.sendRequest(MoveRequest.type, { + moveKind: 'moveResource', + sourceUris: fileUris.map(uri => uri.toString()), + params: null, + destination: selectPackageNodeItem.packageNode, + updateReferences: true, + }); + + await applyRefactorEdit(languageClient, refactorEdit); + if (refactorEdit && refactorEdit.edit) { + await saveEdit(refactorEdit.edit); + } +} + +function getFileNameFromUri(uri: Uri): string { + return uri.fsPath.replace(/^.*[\\\/]/, ''); +} + +function hasCommonParent(uris: Uri[]): boolean { + if (uris === null || uris.length <= 1) { + return true; + } + + const firstParent: string = path.dirname(uris[0].fsPath); + for (let i = 1; i < uris.length; i++) { + const parent = path.dirname(uris[i].fsPath); + if (path.relative(firstParent, parent) !== '.') { + return false; + } + } + + return true; +} + +async function saveEdit(edit: WorkspaceEdit) { + if (!edit) { + return; + } + + const touchedFiles: Set = new Set(); + if (edit.changes) { + for (const uri of Object.keys(edit.changes)) { + touchedFiles.add(uri); + } + } + + if (edit.documentChanges) { + for (const change of edit.documentChanges) { + const kind = ( change).kind; + if (kind === 'rename') { + if (touchedFiles.has(( change).oldUri)) { + touchedFiles.delete(( change).oldUri); + touchedFiles.add(( change).newUri); } + } else if (kind === 'delete') { + if (touchedFiles.has(( change).uri)) { + touchedFiles.delete(( change).uri); + } + } else if (!kind) { + touchedFiles.add(( change).textDocument.uri); } } - })); + } + + for (const fileUri of touchedFiles) { + const uri: Uri = Uri.parse(fileUri); + const document: TextDocument = await workspace.openTextDocument(uri); + if (document === null) { + continue; + } + + await document.save(); + } +} + +async function moveInstanceMethod(languageClient: LanguageClient, params: CodeActionParams, commandInfo: any) { + const moveDestinations = await languageClient.sendRequest(GetMoveDestinationsRequest.type, { + moveKind: 'moveInstanceMethod', + sourceUris: [ params.textDocument.uri ], + params + }); + if (moveDestinations && moveDestinations.errorMessage) { + window.showErrorMessage(moveDestinations.errorMessage); + return; + } + + if (!moveDestinations || !moveDestinations.destinations || !moveDestinations.destinations.length) { + window.showErrorMessage("Cannot find possible class targets to move the selected method to."); + return; + } + + const destinationNodeItems = moveDestinations.destinations.map((destination) => { + return { + label: `${destination.type} ${destination.name}`, + description: destination.isField ? "Field" : "Method Parameter", + destination, + }; + }); + const methodName = commandInfo && commandInfo.displayName ? commandInfo.displayName : ''; + const selected = await window.showQuickPick(destinationNodeItems, { + placeHolder: `Select the new class for the instance method ${methodName}.`, + }); + if (!selected) { + return; + } + + const refactorEdit: RefactorWorkspaceEdit = await languageClient.sendRequest(MoveRequest.type, { + moveKind: 'moveInstanceMethod', + sourceUris: [ params.textDocument.uri ], + params, + destination: selected.destination, + }); + await applyRefactorEdit(languageClient, refactorEdit); +} + +async function moveStaticMember(languageClient: LanguageClient, params: CodeActionParams, commandInfo: any) { + const memberName = commandInfo && commandInfo.displayName ? commandInfo.displayName : ''; + const exclude: Set = new Set(); + if (commandInfo.enclosingTypeName) { + exclude.add(commandInfo.enclosingTypeName); + // 55: Type, 71: Enum, 81: AnnotationType + if (commandInfo.memberType === 55 || commandInfo.memberType === 71 + || commandInfo.memberType === 81) { + exclude.add(`${commandInfo.enclosingTypeName}.${commandInfo.displayName}`); + } + } + + const projectName = commandInfo ? commandInfo.projectName : null; + const picked = await selectTargetClass(languageClient, `Select the new class for the static member ${memberName}.`, projectName, exclude); + if (picked) { + const refactorEdit: RefactorWorkspaceEdit = await languageClient.sendRequest(MoveRequest.type, { + moveKind: 'moveStaticMember', + sourceUris: [ params.textDocument.uri ], + params, + destination: picked, + }); + await applyRefactorEdit(languageClient, refactorEdit); + } +} + +async function selectTargetClass(languageClient: LanguageClient, placeHolder: string, projectName: string, exclude: Set): Promise { + const picked = await window.showQuickPick( + languageClient.sendRequest(SearchSymbols.type, { + query: '*', + projectName, + sourceOnly: true, + }).then(types => { + if (types && types.length) { + return types.filter((type) => { + const typeName = type.containerName ? `${type.containerName}.${type.name}` : type.name; + return !exclude.has(typeName); + }).sort((a, b) => { + if (a.name < b.name) { + return -1; + } else if (a.name > b.name) { + return 1; + } + return 0; + }).map((symbol => { + return { + label: symbol.name, + description: symbol.containerName, + symbolNode: symbol, + }; + })); + } else { + return [{ + label: 'No result found', + alwaysShow: true, + description: '', + symbolNode: null, + }]; + } + }), { + placeHolder, + }); + + return picked ? picked.symbolNode : null; +} + +async function moveType(languageClient: LanguageClient, params: CodeActionParams, commandInfo: any) { + if (!commandInfo || !commandInfo.supportedDestinationKinds) { + return; + } + + const destinationPickItems: any[] = commandInfo.supportedDestinationKinds.map((kind) => { + if (kind === 'newFile') { + return { + label: `Move type ${commandInfo.displayName} to new file`, + kind, + }; + } else { + return { + label: `Move type ${commandInfo.displayName} to another class`, + kind, + }; + } + }); + + if (!destinationPickItems.length) { + return; + } + + const picked = await window.showQuickPick(destinationPickItems, { + placeHolder: 'What would you like to do?', + }); + if (!picked) { + return; + } + + let refactorEdit: RefactorWorkspaceEdit; + if (picked.kind === 'newFile') { + refactorEdit = await languageClient.sendRequest(MoveRequest.type, { + moveKind: 'moveTypeToNewFile', + sourceUris: [ params.textDocument.uri ], + params, + }); + } else { + const exclude: Set = new Set(); + if (commandInfo.enclosingTypeName) { + exclude.add(commandInfo.enclosingTypeName); + exclude.add(`${commandInfo.enclosingTypeName}.${commandInfo.displayName}`); + } + + const picked = await selectTargetClass(languageClient, `Select the new class for the type ${commandInfo.displayName}.`, commandInfo.projectName, exclude); + if (picked) { + refactorEdit = await languageClient.sendRequest(MoveRequest.type, { + moveKind: 'moveTypeToClass', + sourceUris: [ params.textDocument.uri ], + params, + destination: picked, + }); + } + } + + await applyRefactorEdit(languageClient, refactorEdit); } diff --git a/src/refactoring/changeSignaturePanel.ts b/src/refactoring/changeSignaturePanel.ts new file mode 100644 index 0000000000..5935d9f728 --- /dev/null +++ b/src/refactoring/changeSignaturePanel.ts @@ -0,0 +1,190 @@ +import * as path from "path"; +import { Disposable, Webview, WebviewPanel, window, Uri, ViewColumn, workspace, WorkspaceEdit } from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; +import { GetRefactorEditRequest, RefactorWorkspaceEdit } from "../protocol"; +import { getNonce, getUri } from "../webviewUtils"; + +interface MethodParameter { + type: string; + name: string; + defaultValue: string; + originalIndex: number; +} + +interface MethodException { + type: string; + typeHandleIdentifier: string; +} + +export class ChangeSignaturePanel { + public static type = "java.refactor.changeSignature"; + public static title = "Refactor: Change Method Signature"; + public static currentPanel: ChangeSignaturePanel | undefined; + private readonly panel: WebviewPanel; + private disposables: Disposable[] = []; + + // method metadata + private methodIdentifier: string | undefined; + private methodName: string | undefined; + private modifier: string | undefined; + private returnType: string | undefined; + private parameters: MethodParameter[] | undefined; + private exceptions: MethodException[] | undefined; + + // refactor metadata + private languageClient: LanguageClient; + private params: any; + private formattingOptions: any; + private command: any; + + private constructor(panel: WebviewPanel, extensionUri: Uri) { + this.panel = panel; + this.panel.onDidDispose(() => this.dispose(), null, this.disposables); + this.panel.webview.html = this.getWebviewContent(this.panel.webview, extensionUri); + this.setWebviewMessageListener(this.panel.webview); + } + + public static render(extensionUri: Uri, languageClient: LanguageClient, command: any, params: any, formattingOptions: any, commandInfo: any) { + if (ChangeSignaturePanel.currentPanel) { + if (!commandInfo?.methodIdentifier) { + // the new method to do refactoring is not available, just reveal the current panel. + ChangeSignaturePanel.currentPanel.panel.reveal(ViewColumn.Beside); + return; + } + if (commandInfo.methodIdentifier === ChangeSignaturePanel.currentPanel.methodIdentifier) { + // the new method to do refactoring is the same as the old one, just reveal the current panel. + ChangeSignaturePanel.currentPanel.panel.reveal(ViewColumn.Beside); + return; + } else { + window.showInformationMessage(`Change Method Signature for '${ChangeSignaturePanel.currentPanel.methodName}' is in process. Would you like to reveal or abort it?`, "Reveal", "Abort").then(async (selection) => { + if (selection === "Reveal") { + ChangeSignaturePanel.currentPanel.panel.reveal(ViewColumn.Beside); + } else if (selection === "Abort") { + ChangeSignaturePanel.currentPanel.dispose(); + ChangeSignaturePanel.render(extensionUri, languageClient, command, params, formattingOptions, commandInfo); + } + }); + } + } else { + const panel = window.createWebviewPanel( + ChangeSignaturePanel.type, + ChangeSignaturePanel.title, + ViewColumn.Beside, + { + enableCommandUris: true, + enableScripts: true, + localResourceRoots: [Uri.joinPath(extensionUri, "dist")], + retainContextWhenHidden: true, + } + ); + panel.iconPath = Uri.file(path.join(extensionUri.fsPath, "icons", "icon128.png")); + ChangeSignaturePanel.currentPanel = new ChangeSignaturePanel(panel, extensionUri); + ChangeSignaturePanel.currentPanel.setMetadata(languageClient, command, params, formattingOptions, commandInfo); + } + } + + public setMetadata(languageClient: LanguageClient, command: any, params: any, formattingOptions: any, commandInfo: any) { + this.languageClient = languageClient; + this.command = command; + this.params = params; + this.formattingOptions = formattingOptions; + this.methodIdentifier = commandInfo.methodIdentifier; + this.methodName = commandInfo.methodName as string; + this.modifier = commandInfo.modifier as string; + this.returnType = commandInfo.returnType as string; + this.parameters = commandInfo.parameters as MethodParameter[]; + this.exceptions = commandInfo.exceptions as MethodException[]; + } + + public dispose() { + ChangeSignaturePanel.currentPanel = undefined; + this.panel.dispose(); + while (this.disposables.length) { + const disposable = this.disposables.pop(); + if (disposable) { + disposable.dispose(); + } + } + } + + private getWebviewContent(webview: Webview, extensionUri: Uri) { + const scriptUri = getUri(webview, extensionUri, "dist", "changeSignature.js"); + const styleUri = getUri(webview, extensionUri, "dist", "changeSignature.css"); + + return /* html*/ ` + + + + + + + + + Change Signature + + + +
+ + + + `; + } + + private setWebviewMessageListener(webview: Webview) { + webview.onDidReceiveMessage( + async (message: any) => { + const command = message.command; + switch (command) { + case "webviewReady": + await this.panel.webview.postMessage({ + command: "setInitialState", + methodIdentifier: this.methodIdentifier, + methodName: this.methodName, + modifier: this.modifier, + returnType: this.returnType, + parameters: this.parameters, + exceptions: this.exceptions + }); + break; + case "doRefactor": + if (await this.doRefactor(message.methodIdentifier, message.isDelegate, message.methodName, message.accessType, message.returnType, message.parameters, message.exceptions, message.preview)) { + this.dispose(); + } + break; + } + }, + undefined, + this.disposables + ); + } + + /** + * refactor the method with the given parameters. + * + * @param methodIdentifier the handle identifier of the method to refactor. + * @param isDelegate if true, the method will be refactored to a delegate method. + * @param methodName the new name of the method. + * @param accessType the new access type of the method. + * @param returnType the new return type of the method. + * @param parameters the new parameters of the method. + * @param exceptions the new exceptions of the method. + * @param preview if true, the refactoring will be previewed before applied. + * @returns true if the refactoring is successful, false otherwise. + */ + private async doRefactor(methodIdentifier: string, isDelegate: boolean, methodName: string, accessType: string, returnType: string, parameters: MethodParameter[], exceptions: MethodException[], preview: boolean): Promise { + const clientWorkspaceEdit: RefactorWorkspaceEdit = await this.languageClient.sendRequest(GetRefactorEditRequest.type, { + command: this.command, + context: this.params, + options: this.formattingOptions, + commandArguments: [methodIdentifier, isDelegate, methodName, accessType, returnType, parameters, exceptions, preview] + }); + if (clientWorkspaceEdit?.edit) { + const codeEdit: WorkspaceEdit = await this.languageClient.protocol2CodeConverter.asWorkspaceEdit(clientWorkspaceEdit.edit); + if (codeEdit) { + return workspace.applyEdit(codeEdit); + } + } + return false; + } +} diff --git a/src/refactoring/extractInterface.ts b/src/refactoring/extractInterface.ts new file mode 100644 index 0000000000..29302dcc75 --- /dev/null +++ b/src/refactoring/extractInterface.ts @@ -0,0 +1,174 @@ +'use strict'; + +import * as vscode from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; +import { CheckExtractInterfaceStatusRequest, CheckExtractInterfaceStatusResponse, RefactorWorkspaceEdit } from "../protocol"; + +enum Step { + selectMember, + specifyInterfaceName, + selectPackage, +} + +export async function getExtractInterfaceArguments(languageClient: LanguageClient, params: any): Promise { + if (!params || !params.range) { + return []; + } + const extractInterfaceResponse: CheckExtractInterfaceStatusResponse = await languageClient.sendRequest(CheckExtractInterfaceStatusRequest.type, params); + if (!extractInterfaceResponse) { + return []; + } + let step: Step = Step.selectMember; + // step results, initialized as undefined + let resultHandleIdentifiers: any[] | undefined; + let interfaceName: string | undefined; + let selectPackageNodeItem: SelectPackageQuickPickItem | undefined; + while (step !== undefined) { + switch (step) { + case Step.selectMember: + const items = extractInterfaceResponse.members.map((item) => { + return { + label: item.parameters ? `${item.name}(${item.parameters.join(", ")})` : item.name, + description: item.typeName, + handleIdentifier: item.handleIdentifier, + picked: resultHandleIdentifiers === undefined ? false : resultHandleIdentifiers.includes(item.handleIdentifier), + }; + }); + const members = await vscode.window.showQuickPick(items, { + title: "Extract Interface (1/3): Select members", + placeHolder: "Please select members to declare in the interface: ", + matchOnDescription: true, + ignoreFocusOut: true, + canPickMany: true, + }); + if (!members) { + return []; + } + resultHandleIdentifiers = members.map((item) => item.handleIdentifier); + if (!resultHandleIdentifiers) { + return []; + } + step = Step.specifyInterfaceName; + break; + case Step.specifyInterfaceName: + const specifyInterfaceNameDisposables = []; + const specifyInterfaceNamePromise = new Promise((resolve, _reject) => { + const inputBox = vscode.window.createInputBox(); + inputBox.title = "Extract Interface (2/3): Specify interface name"; + inputBox.placeholder = "Please specify the new interface name: "; + inputBox.ignoreFocusOut = true; + inputBox.value = interfaceName === undefined ? extractInterfaceResponse.subTypeName : interfaceName; + inputBox.buttons = [(vscode.QuickInputButtons.Back)]; + specifyInterfaceNameDisposables.push( + inputBox, + inputBox.onDidTriggerButton((button) => { + if (button === vscode.QuickInputButtons.Back) { + step = Step.selectMember; + resolve(false); + } + }), + inputBox.onDidAccept(() => { + resolve(inputBox.value); + }), + inputBox.onDidHide(() => { + resolve(undefined); + }) + ); + inputBox.show(); + }); + try { + const result = await specifyInterfaceNamePromise; + if (result === false) { + // go back + step = Step.selectMember; + } else if (result === undefined) { + // cancelled + return []; + } else { + interfaceName = result as string; + step = Step.selectPackage; + } + } finally { + specifyInterfaceNameDisposables.forEach(d => d.dispose()); + } + break; + case Step.selectPackage: + const selectPackageDisposables = []; + const packageNodeItems = extractInterfaceResponse.destinationResponse.destinations.sort((node1, node2) => { + return node1.isParentOfSelectedFile ? -1 : 0; + }).map((packageNode) => { + const packageUri: vscode.Uri = packageNode.uri ? vscode.Uri.parse(packageNode.uri) : null; + const displayPath: string = packageUri ? vscode.workspace.asRelativePath(packageUri, true) : packageNode.path; + return { + label: (packageNode.isParentOfSelectedFile ? '* ' : '') + packageNode.displayName, + description: displayPath, + packageNode, + }; + }); + const selectPackagePromise = new Promise((resolve, _reject) => { + const quickPick = vscode.window.createQuickPick(); + quickPick.items = packageNodeItems; + quickPick.title = "Extract Interface (3/3): Specify package"; + quickPick.placeholder = "Please select the target package for extracted interface."; + quickPick.ignoreFocusOut = true; + quickPick.buttons = [(vscode.QuickInputButtons.Back)]; + selectPackageDisposables.push( + quickPick, + quickPick.onDidTriggerButton((button) => { + if (button === vscode.QuickInputButtons.Back) { + resolve(false); + step = Step.specifyInterfaceName; + } + }), + quickPick.onDidAccept(() => { + if (quickPick.selectedItems.length > 0) { + resolve(quickPick.selectedItems[0] as SelectPackageQuickPickItem); + } + }), + quickPick.onDidHide(() => { + resolve(undefined); + }), + ); + quickPick.show(); + }); + try { + const result = await selectPackagePromise; + if (result === false) { + // go back + step = Step.specifyInterfaceName; + } else if (result === undefined) { + // cancelled + return []; + } else { + selectPackageNodeItem = result as SelectPackageQuickPickItem; + step = undefined; + } + } finally { + selectPackageDisposables.forEach(d => d.dispose()); + } + break; + default: + return []; + } + } + return [resultHandleIdentifiers, interfaceName, selectPackageNodeItem.packageNode]; +} + +export async function revealExtractedInterface(refactorEdit: RefactorWorkspaceEdit) { + if (refactorEdit?.edit?.documentChanges) { + for (const change of refactorEdit.edit.documentChanges) { + if ("kind" in change && change.kind === "create") { + for (const document of vscode.workspace.textDocuments) { + if (document.uri.toString() === vscode.Uri.parse(change.uri).toString()) { + await vscode.window.showTextDocument(document); + return; + } + } + } + } + } +} + +interface SelectPackageQuickPickItem extends vscode.QuickPickItem { + packageNode: any; +} diff --git a/src/requirements.ts b/src/requirements.ts index 0c6a684d06..cedb881baa 100644 --- a/src/requirements.ts +++ b/src/requirements.ts @@ -1,20 +1,24 @@ 'use strict'; -import { workspace, Uri } from 'vscode'; -import * as cp from 'child_process'; -import * as path from 'path'; -import * as pathExists from 'path-exists'; import * as expandHomeDir from 'expand-home-dir'; -import * as findJavaHome from 'find-java-home'; +import * as fse from 'fs-extra'; +import { getRuntime, getSources, JAVAC_FILENAME, JAVA_FILENAME } from 'jdk-utils'; +import * as path from 'path'; +import { env, ExtensionContext, Uri, window, workspace } from 'vscode'; import { Commands } from './commands'; +import { logger } from './log'; +import { checkJavaPreferences } from './settings'; +import { listJdks, sortJdksBySource, sortJdksByVersion } from './jdkUtils'; +import { getJavaConfiguration } from './utils'; -const isWindows = process.platform.indexOf('win') === 0; -const JAVAC_FILENAME = 'javac' + (isWindows ? '.exe' : ''); - +/* eslint-disable @typescript-eslint/naming-convention */ export interface RequirementsData { + tooling_jre: string; + tooling_jre_version: number; java_home: string; java_version: number; } +/* eslint-enable @typescript-eslint/naming-convention */ interface ErrorData { message: string; @@ -29,88 +33,151 @@ interface ErrorData { * if any of the requirements fails to resolve. * */ -export async function resolveRequirements(): Promise { - const javaHome = await checkJavaRuntime(); - const javaVersion = await checkJavaVersion(javaHome); - return Promise.resolve({ java_home: javaHome, java_version: javaVersion }); -} - -function checkJavaRuntime(): Promise { - return new Promise((resolve, reject) => { - let source: string; - let javaHome: string = readJavaConfig(); - if (javaHome) { - source = 'java.home variable defined in VS Code settings'; - } else { - javaHome = process.env['JDK_HOME']; - if (javaHome) { - source = 'JDK_HOME environment variable'; - } else { - javaHome = process.env['JAVA_HOME']; - source = 'JAVA_HOME environment variable'; - } +export async function resolveRequirements(context: ExtensionContext): Promise { + let toolingJre: string = await findEmbeddedJRE(context); + let toolingJreVersion: number = await getMajorVersion(toolingJre); + return new Promise(async (resolve, reject) => { + const javaPreferences = await checkJavaPreferences(context); + const preferenceName = javaPreferences.preference; + let javaHome = javaPreferences.javaHome; + let javaVersion: number = 0; + const REQUIRED_JDK_VERSION = ('on' === getJavaConfiguration().get('jdt.ls.javac.enabled'))?25:21; + if (toolingJreVersion < REQUIRED_JDK_VERSION) { // embedded tooling JRE doesn't meet requirement + toolingJre = null; + toolingJreVersion = 0; } if (javaHome) { + const source = `${preferenceName} variable defined in ${env.appName} settings`; javaHome = expandHomeDir(javaHome); - if (!pathExists.sync(javaHome)) { + if (!await fse.pathExists(javaHome)) { invalidJavaHome(reject, `The ${source} points to a missing or inaccessible folder (${javaHome})`); - } - else if (!pathExists.sync(path.resolve(javaHome, 'bin', JAVAC_FILENAME))) { + } else if (!await fse.pathExists(path.resolve(javaHome, 'bin', JAVAC_FILENAME))) { let msg: string; - if (pathExists.sync(path.resolve(javaHome, JAVAC_FILENAME))) { + if (await fse.pathExists(path.resolve(javaHome, JAVAC_FILENAME))) { msg = `'bin' should be removed from the ${source} (${javaHome})`; } else { msg = `The ${source} (${javaHome}) does not point to a JDK.`; } invalidJavaHome(reject, msg); } - return resolve(javaHome); + javaVersion = await getMajorVersion(javaHome); + if (preferenceName === "java.jdt.ls.java.home" || !toolingJre) { + if (javaVersion >= REQUIRED_JDK_VERSION) { + toolingJre = javaHome; + toolingJreVersion = javaVersion; + } else { + const neverShow: boolean | undefined = context.workspaceState.get("java.home.failsMinRequiredFirstTime"); + if (!neverShow) { + context.workspaceState.update("java.home.failsMinRequiredFirstTime", true); + window.showInformationMessage(`The Java runtime set by 'java.jdt.ls.java.home' does not meet the minimum required version of '${REQUIRED_JDK_VERSION}' and will not be used.`); + } + } + } } - // No settings, let's try to detect as last resort. - findJavaHome((err, home) => { - if (err) { - openJDKDownload(reject, 'Java runtime (JDK, not JRE) could not be located'); + + // search valid JDKs from env.JAVA_HOME, env.PATH, SDKMAN, jEnv, jabba, Common directories + const javaRuntimes = await listJdks(); + if (!toolingJre) { // universal version + // as latest version as possible. + sortJdksByVersion(javaRuntimes); + const validJdks = javaRuntimes.filter(r => r.version.major >= REQUIRED_JDK_VERSION); + if (validJdks.length > 0) { + sortJdksBySource(validJdks); + toolingJre = validJdks[0].homedir; + toolingJreVersion = validJdks[0].version.major; + if (!javaHome) { // keep javaHome if set even if it is an older JDK version + javaHome = toolingJre; + javaVersion = toolingJreVersion; + } } - else { - resolve(home); + } else { // pick a default project JDK/JRE + /** + * For legacy users, we implicitly following the order below to + * set a default project JDK during initialization: + * java.jdt.ls.java.home > java.home > env.JDK_HOME > env.JAVA_HOME > env.PATH + * + * We'll keep it for compatibility. + */ + if (javaHome) { + logger.info(`Use the JDK from '${preferenceName}' setting as the initial default project JDK.`); + } else if (javaRuntimes.length) { + sortJdksBySource(javaRuntimes); + javaHome = javaRuntimes[0].homedir; + javaVersion = javaRuntimes[0].version?.major; + logger.info(`Use the JDK from '${getSources(javaRuntimes[0])}' as the initial default project JDK.`); + } else if (javaHome = await findDefaultRuntimeFromSettings()) { + javaVersion = await getMajorVersion(javaHome); + logger.info("Use the JDK from 'java.configuration.runtimes' as the initial default project JDK."); + } else { + openJDKDownload(reject, "Please download and install a JDK to compile your project. You can configure your projects with different JDKs by the setting ['java.configuration.runtimes'](https://github.com/redhat-developer/vscode-java/wiki/JDK-Requirements#java.configuration.runtimes)"); } + } + + if (!toolingJre || toolingJreVersion < REQUIRED_JDK_VERSION) { + openJDKDownload(reject, `Java ${REQUIRED_JDK_VERSION} or more recent is required to run the Java extension. Please download and install a recent JDK. You can still compile your projects with older JDKs by configuring ['java.configuration.runtimes'](https://github.com/redhat-developer/vscode-java/wiki/JDK-Requirements#java.configuration.runtimes)`); + } + + /* eslint-disable @typescript-eslint/naming-convention */ + resolve({ + tooling_jre: toolingJre, + tooling_jre_version: toolingJreVersion, + java_home: javaHome, + java_version: javaVersion, }); + /* eslint-enable @typescript-eslint/naming-convention */ }); } -function readJavaConfig(): string { - const config = workspace.getConfiguration(); - return config.get('java.home', null); +async function findEmbeddedJRE(context: ExtensionContext): Promise { + const jreHome = context.asAbsolutePath("jre"); + if (fse.existsSync(jreHome) && fse.statSync(jreHome).isDirectory()) { + const candidates = fse.readdirSync(jreHome); + for (const candidate of candidates) { + if (fse.existsSync(path.join(jreHome, candidate, "bin", JAVA_FILENAME))) { + return path.join(jreHome, candidate); + } + } + } + + return; } -function checkJavaVersion(javaHome: string): Promise { - return new Promise((resolve, reject) => { - cp.execFile(javaHome + '/bin/java', ['-version'], {}, (error, stdout, stderr) => { - const javaVersion = parseMajorVersion(stderr); - if (javaVersion < 8) { - openJDKDownload(reject, 'Java 8 or more recent is required to run. Please download and install a recent JDK'); - } else { - resolve(javaVersion); +async function findDefaultRuntimeFromSettings(): Promise { + const runtimes = workspace.getConfiguration().get("java.configuration.runtimes"); + if (Array.isArray(runtimes) && runtimes.length) { + let candidate: string; + for (const runtime of runtimes) { + if (!runtime || typeof runtime !== 'object' || !runtime.path) { + continue; } - }); - }); + + const jr = await getRuntime(runtime.path); + if (jr) { + candidate = jr.homedir; + } + + if (runtime.default) { + break; + } + } + + return candidate; + } + + return undefined; } -export function parseMajorVersion(content: string): number { - let regexp = /version "(.*)"/g; - let match = regexp.exec(content); - if (!match) { +export function parseMajorVersion(version: string): number { + if (!version) { return 0; } - let version = match[1]; // Ignore '1.' prefix for legacy Java versions if (version.startsWith('1.')) { version = version.substring(2); } - // look into the interesting bits now - regexp = /\d+/g; - match = regexp.exec(version); + const regexp = /\d+/g; + const match = regexp.exec(version); let javaVersion = 0; if (match) { javaVersion = parseInt(match[0]); @@ -119,10 +186,7 @@ export function parseMajorVersion(content: string): number { } function openJDKDownload(reject, cause) { - let jdkUrl = 'https://developers.redhat.com/products/openjdk/download/?sc_cid=701f2000000RWTnAAO'; - if (process.platform === 'darwin') { - jdkUrl = 'http://www.oracle.com/technetwork/java/javase/downloads/index.html'; - } + const jdkUrl = getJdkUrl(); reject({ message: cause, label: 'Get the Java Development Kit', @@ -131,6 +195,14 @@ function openJDKDownload(reject, cause) { }); } +export function getJdkUrl() { + let jdkUrl = 'https://developers.redhat.com/products/openjdk/download/?sc_cid=701f2000000RWTnAAO'; + if (process.platform === 'darwin') { + jdkUrl = 'https://adoptopenjdk.net/'; + } + return jdkUrl; +} + function invalidJavaHome(reject, cause: string) { if (cause.indexOf("java.home") > -1) { reject({ @@ -144,3 +216,11 @@ function invalidJavaHome(reject, cause: string) { }); } } + +async function getMajorVersion(javaHome: string): Promise { + if (!javaHome) { + return 0; + } + const runtime = await getRuntime(javaHome, { withVersion: true }); + return runtime?.version?.major || 0; +} diff --git a/src/runtimeStatusBarProvider.ts b/src/runtimeStatusBarProvider.ts new file mode 100644 index 0000000000..08fa389621 --- /dev/null +++ b/src/runtimeStatusBarProvider.ts @@ -0,0 +1,269 @@ +'use strict'; + +import * as fse from "fs-extra"; +import { window, TextEditor, Uri, commands, workspace, ExtensionContext, LanguageStatusItem } from "vscode"; +import { Commands } from "./commands"; +import { Disposable } from "vscode-languageclient"; +import * as path from "path"; +import { apiManager } from "./apiManager"; +import { ACTIVE_BUILD_TOOL_STATE } from "./settings"; +import { BuildFileStatusItemFactory, RuntimeStatusItemFactory } from "./languageStatusItemFactory"; +import { getAllJavaProjects, getJavaConfiguration, hasBuildToolConflicts } from "./utils"; +import { LombokVersionItemFactory, getLombokVersion, isLombokImported } from "./lombokSupport"; + +class LanguageStatusBarProvider implements Disposable { + private runtimeStatusItem: LanguageStatusItem; + private buildFileStatusItem: LanguageStatusItem; + private lombokVersionItem: LanguageStatusItem; + private javaProjects: Map; + private fileProjectMapping: Map; + private storagePath: string | undefined; + private disposables: Disposable[]; + + constructor() { + this.javaProjects = new Map(); + this.fileProjectMapping = new Map(); + this.disposables = []; + } + + public async initialize(context: ExtensionContext): Promise { + // ignore the hash part to make it compatible in debug mode. + const storagePath = context.storagePath; + if (storagePath) { + this.storagePath = Uri.file(path.join(storagePath, "..", "..")).fsPath; + } + + let projectUriStrings: string[]; + try { + projectUriStrings = await getAllJavaProjects(false); + } catch (e) { + return; + } + + for (const uri of projectUriStrings) { + this.javaProjects.set(Uri.parse(uri).fsPath, undefined); + } + + this.disposables.push(window.onDidChangeActiveTextEditor((textEditor) => { + this.updateItem(context, textEditor); + })); + + this.disposables.push(apiManager.getApiInstance().onDidProjectsImport(async (uris: Uri[]) => { + for (const uri of uris) { + this.javaProjects.set(uri.fsPath, this.javaProjects.get(uri.fsPath)); + } + await this.updateItem(context, window.activeTextEditor); + })); + + this.disposables.push(apiManager.getApiInstance().onDidClasspathUpdate(async (e: Uri) => { + for (const projectPath of this.javaProjects.keys()) { + if (path.relative(projectPath, e.fsPath) === '') { + this.javaProjects.set(projectPath, undefined); + await this.updateItem(context, window.activeTextEditor); + return; + } + } + })); + + await this.updateItem(context, window.activeTextEditor); + } + + public initializeLombokStatusBar() { + this.lombokVersionItem = LombokVersionItemFactory.create(getLombokVersion()); + } + + public destroyLombokStatusBar(): void { + this.hideLombokVersionItem(); + } + + private hideRuntimeStatusItem(): void { + this.runtimeStatusItem?.dispose(); + this.runtimeStatusItem = undefined; + } + + private hideBuildFileStatusItem(): void { + this.buildFileStatusItem?.dispose(); + this.buildFileStatusItem = undefined; + } + + private hideLombokVersionItem(): void { + this.lombokVersionItem?.dispose(); + this.lombokVersionItem = undefined; + } + + public dispose(): void { + this.runtimeStatusItem?.dispose(); + this.buildFileStatusItem?.dispose(); + this.lombokVersionItem?.dispose(); + for (const disposable of this.disposables) { + disposable.dispose(); + } + } + + private findOwnerProject(uri: Uri): string { + let ownerProjectPath: string | undefined = this.fileProjectMapping.get(uri.fsPath); + if (ownerProjectPath) { + return ownerProjectPath; + } + + const isInWorkspaceFolder: boolean = !!workspace.getWorkspaceFolder(uri); + for (const projectPath of this.javaProjects.keys()) { + if (!isInWorkspaceFolder && this.isDefaultProjectPath(projectPath)) { + ownerProjectPath = projectPath; + break; + } + + if (uri.fsPath.startsWith(projectPath)) { + if (!ownerProjectPath) { + ownerProjectPath = projectPath; + continue; + } + + if (projectPath.length > ownerProjectPath.length) { + ownerProjectPath = projectPath; + } + } + } + + if (ownerProjectPath) { + this.fileProjectMapping.set(uri.fsPath, ownerProjectPath); + } + + return ownerProjectPath; + } + + private async getProjectInfo(projectPath: string): Promise { + let projectInfo: IProjectInfo | undefined = this.javaProjects.get(projectPath); + if (projectInfo) { + return projectInfo; + } + + try { + const settings: {} = await commands.executeCommand<{}>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_PROJECT_SETTINGS, Uri.file(projectPath).toString(), [SOURCE_LEVEL_KEY, VM_INSTALL_PATH]); + projectInfo = { + sourceLevel: settings[SOURCE_LEVEL_KEY], + vmInstallPath: settings[VM_INSTALL_PATH] + }; + + this.javaProjects.set(projectPath, projectInfo); + return projectInfo; + + } catch (e) { + // do nothing + } + + return undefined; + } + + private async updateItem(context: ExtensionContext, textEditor: TextEditor): Promise { + if (!textEditor || path.extname(textEditor.document.fileName) !== ".java") { + return; + } + + const uri: Uri = textEditor.document.uri; + const projectPath: string = this.findOwnerProject(uri); + if (!projectPath) { + this.hideRuntimeStatusItem(); + this.hideBuildFileStatusItem(); + this.hideLombokVersionItem(); + return; + } + + const projectInfo: IProjectInfo = await this.getProjectInfo(projectPath); + if (!projectInfo) { + this.hideRuntimeStatusItem(); + this.hideBuildFileStatusItem(); + this.hideLombokVersionItem(); + return; + } + + const text = this.getJavaRuntimeFromVersion(projectInfo.sourceLevel); + const buildFilePath = await this.getBuildFilePath(context, projectPath); + if (!this.runtimeStatusItem) { + this.runtimeStatusItem = RuntimeStatusItemFactory.create(text, projectInfo.vmInstallPath); + if (buildFilePath) { + this.buildFileStatusItem = BuildFileStatusItemFactory.create(buildFilePath); + } + } else { + RuntimeStatusItemFactory.update(this.runtimeStatusItem, text, projectInfo.vmInstallPath); + if (buildFilePath) { + BuildFileStatusItemFactory.update(this.buildFileStatusItem, buildFilePath); + } + } + + if (isLombokImported()) { + if (!this.lombokVersionItem) { + this.lombokVersionItem = LombokVersionItemFactory.create(getLombokVersion()); + } else { + LombokVersionItemFactory.update(this.lombokVersionItem, getLombokVersion()); + } + } + } + + private isDefaultProjectPath(fsPath: string) { + // this.storagePath === undefined indicates that it's in standalone file mode + return !this.storagePath || + fsPath.startsWith(this.storagePath) && fsPath.indexOf("jdt.ls-java-project") > -1; + } + + private getJavaRuntimeFromVersion(ver: string) { + if (!ver) { + return ""; + } + + if (ver === "1.5") { + return "J2SE-1.5"; + } + + return `JavaSE-${ver}`; + } + + private async getBuildFilePath(context: ExtensionContext, projectPath: string): Promise { + const isMavenEnabled: boolean = getJavaConfiguration().get("import.maven.enabled"); + const isGradleEnabled: boolean = getJavaConfiguration().get("import.gradle.enabled"); + if (isMavenEnabled && isGradleEnabled) { + let buildFilePath: string | undefined; + const activeBuildTool: string | undefined = context.workspaceState.get(ACTIVE_BUILD_TOOL_STATE); + if (!activeBuildTool) { + if (!(await hasBuildToolConflicts())) { + // only one build tool exists in the project + buildFilePath = await this.getBuildFilePathFromNames(projectPath, ["pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"]); + } else { + // the user has not resolved build conflicts yet + return undefined; + } + } else if (activeBuildTool.toLocaleLowerCase().includes("maven")) { + buildFilePath = await this.getBuildFilePathFromNames(projectPath, ["pom.xml"]); + } else if (activeBuildTool.toLocaleLowerCase().includes("gradle")) { + buildFilePath = await this.getBuildFilePathFromNames(projectPath, ["build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"]); + } + return buildFilePath; + } else if (isMavenEnabled) { + return this.getBuildFilePathFromNames(projectPath, ["pom.xml"]); + } else if (isGradleEnabled) { + return this.getBuildFilePathFromNames(projectPath, ["build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"]); + } else { + return undefined; + } + } + + private async getBuildFilePathFromNames(projectPath: string, buildFileNames: string[]): Promise { + for (const buildFileName of buildFileNames) { + const buildFilePath = path.join(projectPath, buildFileName); + if (await fse.pathExists(buildFilePath)) { + return buildFilePath; + } + } + return undefined; + } +} + +interface IProjectInfo { + sourceLevel: string; + vmInstallPath: string; +} + +const SOURCE_LEVEL_KEY = "org.eclipse.jdt.core.compiler.source"; +const VM_INSTALL_PATH = "org.eclipse.jdt.ls.core.vm.location"; + +export const languageStatusBarProvider: LanguageStatusBarProvider = new LanguageStatusBarProvider(); diff --git a/src/serverStatus.ts b/src/serverStatus.ts new file mode 100644 index 0000000000..28c51990a5 --- /dev/null +++ b/src/serverStatus.ts @@ -0,0 +1,66 @@ +'use strict'; + +import { EventEmitter } from "vscode"; +import { serverTasks } from "./serverTasks"; +import { serverStatusBarProvider } from "./serverStatusBarProvider"; + +export enum ServerStatusKind { + ready = "Ready", + warning = "Warning", + error = "Error", + busy = "Busy", +} + +const emitter = new EventEmitter(); +let status: ServerStatusKind = ServerStatusKind.ready; +let isBusy: boolean = false; + +function fireEvent() { + if (isBusy) { + emitter.fire(ServerStatusKind.busy); + return; + } + + emitter.fire(status); +} + +export namespace serverStatus { + + let hasError: boolean = false; + + export const onServerStatusChanged = emitter.event; + + export function initialize() { + serverTasks.onDidUpdateServerTask(tasks => { + const busyTask = tasks.find(task => !task.complete); + isBusy = !!busyTask; + if (isBusy) { + serverStatusBarProvider.setBusy(busyTask.value.message); + } + fireEvent(); + }); + } + + export function updateServerStatus(newStatus: ServerStatusKind) { + if (newStatus === ServerStatusKind.busy) { + throw new Error("Busy status cannot be set directly."); + } + + if (newStatus === ServerStatusKind.error || newStatus === ServerStatusKind.warning) { + hasError = true; + } else if (hasError) { + return; + } + + status = newStatus; + fireEvent(); + } + + export function hasErrors() { + return hasError; + } + + export function errorResolved() { + hasError = false; + } +} diff --git a/src/serverStatusBarProvider.ts b/src/serverStatusBarProvider.ts new file mode 100644 index 0000000000..a410c65cea --- /dev/null +++ b/src/serverStatusBarProvider.ts @@ -0,0 +1,92 @@ +'use strict'; + +import { StatusBarItem, window, StatusBarAlignment, ThemeColor, commands, QuickPickItem, QuickPickItemKind } from "vscode"; +import { Disposable } from "vscode-languageclient"; +import { StatusCommands } from "./languageStatusItemFactory"; +import { Commands } from "./commands"; +import { ServerStatusKind } from "./serverStatus"; + +class ServerStatusBarProvider implements Disposable { + private statusBarItem: StatusBarItem; + + constructor() { + this.statusBarItem = window.createStatusBarItem("java.serverStatus", StatusBarAlignment.Left); + this.statusBarItem.show(); + } + + public showLightWeightStatus(): void { + this.statusBarItem.name = "Java Server Mode"; + this.statusBarItem.text = `${StatusIcon.lightWeight} Java: Lightweight Mode`; + this.statusBarItem.command = StatusCommands.switchToStandardCommand; + this.statusBarItem.tooltip = "Java language server is running in LightWeight mode, click to switch to Standard mode"; + } + + public showNotImportedStatus(): void { + this.statusBarItem.name = "No projects are imported"; + this.statusBarItem.text = `${StatusIcon.notImported} Java: No Projects Imported`; + this.statusBarItem.command = StatusCommands.startStandardServerCommand; + this.statusBarItem.tooltip = "No projects are imported, click to load projects"; + } + + public setBusy(process: string): void { + this.statusBarItem.text = `${StatusIcon.busy} Java: ${process}`; + this.statusBarItem.tooltip = process; + this.statusBarItem.command = { + title: "Show Java status menu", + command: Commands.OPEN_STATUS_SHORTCUT, + tooltip: "Show Java status menu", + arguments: [ServerStatusKind.busy], + }; + } + + public setError(): void { + this.statusBarItem.text = `${StatusIcon.java} Java: Error`; + this.statusBarItem.tooltip = "Show Java status menu"; + this.statusBarItem.command = { + title: "Show Java status menu", + command: Commands.OPEN_STATUS_SHORTCUT, + tooltip: "Show Java status menu", + arguments: [ServerStatusKind.error], + }; + } + + public setWarning(): void { + this.statusBarItem.text = `${StatusIcon.java} Java: Warning`; + this.statusBarItem.tooltip = "Show Java status menu"; + this.statusBarItem.command = { + title: "Show Java status menu", + command: Commands.OPEN_STATUS_SHORTCUT, + tooltip: "Show Java status menu", + arguments: [ServerStatusKind.warning], + }; + } + + public setReady(): void { + this.statusBarItem.text = `${StatusIcon.java} Java: Ready`; + this.statusBarItem.tooltip = "Show Java status menu"; + this.statusBarItem.command = { + title: "Show Java status menu", + command: Commands.OPEN_STATUS_SHORTCUT, + tooltip: "Show Java status menu", + arguments: ["Ready"], + }; + } + + public dispose(): void { + this.statusBarItem?.dispose(); + } +} + +export enum StatusIcon { + lightWeight = "$(rocket)", + notImported = "$(info)", + busy = "$(sync~spin)", + java = "$(coffee)", +} + +export interface ShortcutQuickPickItem extends QuickPickItem { + command: string; + args?: any[]; +} + +export const serverStatusBarProvider: ServerStatusBarProvider = new ServerStatusBarProvider(); diff --git a/src/serverTaskPresenter.ts b/src/serverTaskPresenter.ts new file mode 100644 index 0000000000..2cf8a10302 --- /dev/null +++ b/src/serverTaskPresenter.ts @@ -0,0 +1,163 @@ +import { tasks, Task, TaskScope, Pseudoterminal, CustomExecution, TaskExecution, TaskRevealKind, TaskPanelKind, EventEmitter, Event, TerminalDimensions, window, Progress, ProgressLocation, workspace } from "vscode"; +import { serverTasks } from "./serverTasks"; +import { Disposable } from "vscode-languageclient"; +import { ProgressReport, ProgressKind } from "./protocol"; +import { Commands } from "./commands"; +import { getJavaConfiguration } from "./utils"; + +const JAVA_SERVER_TASK_PRESENTER_TASK_NAME = "Java Build Status"; + +export namespace serverTaskPresenter { + export async function presentServerTaskView(preserveFocus?: boolean) { + const execution = await getPresenterTaskExecution(); + const terminals = window.terminals; + const presenterTerminals = terminals.filter(terminal => terminal.name.indexOf(execution.task.name) >= 0); + if (presenterTerminals.length > 0) { + presenterTerminals[0].show(preserveFocus); + } + activationProgressNotification.hide(); + } +} + +let presenterTaskExecution: TaskExecution = null; + +async function getPresenterTaskExecution(): Promise { + await killExistingExecutions(); + + if (!!presenterTaskExecution) { + return Promise.resolve(presenterTaskExecution); + } + + const presenterTask = new Task({ type: "Java" }, TaskScope.Workspace, JAVA_SERVER_TASK_PRESENTER_TASK_NAME, "Java", new CustomExecution(async () => { + return new ServerTaskTerminal(); + })); + + presenterTask.presentationOptions = { + reveal: TaskRevealKind.Always, + panel: TaskPanelKind.Dedicated, + clear: true, + echo: false, + focus: false + }; + presenterTask.isBackground = true; + + return presenterTaskExecution = await tasks.executeTask(presenterTask); +} + +// Fix #1180. When switching to multiroot workspace by "Add Folder to Workspace...", vscode restarts the extension +// host without deactivating the extension. See https://github.com/microsoft/vscode/issues/69335 +// This is to clean up the existing task execution and terminal created by previous extension instance because they +// are no longer accessible to the current extension instance after the restart. +// TODO - As mentioned in https://github.com/microsoft/vscode/issues/69335, vscode will no long restart because of +// workspace changes. We can revisit this issue to see if we can remove the fix. +async function killExistingExecutions() { + if (!!presenterTaskExecution) { + return; + } + + let execs = tasks.taskExecutions; + execs = execs.filter(exec => exec.task.name.indexOf(JAVA_SERVER_TASK_PRESENTER_TASK_NAME) >= 0); + execs.forEach(exec => exec.terminate()); + await new Promise(resolve => setTimeout(resolve, 0)); + + let terminals = window.terminals; + terminals = terminals.filter(terminal => terminal.name.indexOf(JAVA_SERVER_TASK_PRESENTER_TASK_NAME) >= 0); + terminals.forEach(terminal => terminal.dispose()); + await new Promise(resolve => setTimeout(resolve, 0)); +} + +class ServerTaskTerminal implements Pseudoterminal { + private onDidWriteEvent = new EventEmitter(); + private onDidCloseEvent = new EventEmitter(); + private subscription: Disposable = null; + + onDidWrite: Event = this.onDidWriteEvent.event; + onDidClose?: Event = this.onDidCloseEvent.event; + + constructor() { + this.subscription = serverTasks.onDidUpdateServerTask(serverTasks => { + this.printTasks(serverTasks); + }); + } + + private printTasks(tasks: ProgressReport[]) { + this.clearScreen(); + tasks.forEach(task => this.printTask(task)); + } + + private clearScreen() { + this.onDidWriteEvent.fire("\u001Bc"); + } + + private printTask(report: ProgressReport) { + if (report.complete) { + this.onDidWriteEvent.fire(`${report.token.slice(0, 8)} ${report.value.message} [Done]\r\n`); + return; + } + + const taskMsg = `${report.token.slice(0, 8)} ${report.value.message}`; + + this.onDidWriteEvent.fire(`${taskMsg}\r\n`); + } + + open(initialDimensions: TerminalDimensions): void { + serverTasks.suggestTaskEntrySize(initialDimensions.rows - 1); + const tasks = serverTasks.getHistory(); + this.printTasks(tasks); + } + + close(): void { + presenterTaskExecution.terminate(); + presenterTaskExecution = null; + this.subscription.dispose(); + this.onDidCloseEvent.fire(); + } + + setDimensions(dimensions: TerminalDimensions) { + serverTasks.suggestTaskEntrySize(dimensions.rows - 1); + } +} + +export class ActivationProgressNotification { + private hideEmitter = new EventEmitter(); + private onHide = this.hideEmitter.event; + private disposables: Disposable[] = []; + + public showProgress() { + if (!workspace.workspaceFolders) { + return; + } + const showBuildStatusEnabled = getJavaConfiguration().get("showBuildStatusOnStart.enabled"); + if (typeof showBuildStatusEnabled === "string" || showBuildStatusEnabled instanceof String) { + if (showBuildStatusEnabled !== "notification") { + return; + } + } else if (!showBuildStatusEnabled) { + return; + } + const title = "Opening Java Projects"; + window.withProgress({ + location: ProgressLocation.Notification, + title, + cancellable: false, + }, (progress: Progress<{ message?: string; increment?: number }>) => { + return new Promise((resolve) => { + progress.report({ + message: `[check details](command:${Commands.SHOW_SERVER_TASK_STATUS})` + }); + this.onHide(() => { + for (const disposable of this.disposables) { + disposable.dispose(); + } + return resolve(); + }); + }); + }); + } + + public hide() { + this.hideEmitter.fire(); + } +} + +export const activationProgressNotification = new ActivationProgressNotification(); diff --git a/src/serverTasks.ts b/src/serverTasks.ts new file mode 100644 index 0000000000..f881be450f --- /dev/null +++ b/src/serverTasks.ts @@ -0,0 +1,67 @@ +import { EventEmitter } from "vscode"; +import { ProgressReport, ProgressKind } from "./protocol"; + +const findIndex = require("lodash.findindex"); + +let tasks: ProgressReport[] = []; + +const emitter = new EventEmitter(); +let suggestedTaskEntrySize = 10; + +export namespace serverTasks { + export const onDidUpdateServerTask = emitter.event; + + export function updateServerTask(report: ProgressReport) { + applyReport(report); + emitter.fire(tasks); + } + + export function suggestTaskEntrySize(size: number) { + if (size > suggestedTaskEntrySize) { + suggestedTaskEntrySize = size; + } + } + + export function getHistory(): ProgressReport[] { + return tasks; + } +} + +function organizeTasks() { + let newArray = tasks; + if (tasks.length > suggestedTaskEntrySize) { + newArray = recycleTasks(tasks, suggestedTaskEntrySize); + } + + // make sure in-progress items are always at the end + newArray.sort((a, b) => Number(b.complete) - Number(a.complete)); + + tasks = newArray; +} + +function recycleTasks(tasks: ProgressReport[], length: number) { + const newArray = [], delta = tasks.length - length; + let skipped = 0; + + tasks.forEach(task => { + if (skipped < delta && task.complete) { + skipped++; + return; + } + + newArray.push(task); + }); + + return newArray; +} + +function applyReport(report: ProgressReport) { + const index = findIndex(tasks, task => task.token === report.token); + if (index === -1) { + tasks.push(report); + } else { + tasks[index] = report; + } + + organizeTasks(); +} diff --git a/src/settings.ts b/src/settings.ts index 3cf0b2562a..1e3330ed25 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,11 +1,23 @@ 'use strict'; -import { window, Uri, workspace, WorkspaceConfiguration, commands, ConfigurationTarget } from 'vscode'; -import { LanguageClient } from 'vscode-languageclient'; +import * as fs from 'fs'; +import * as path from 'path'; +import { commands, ConfigurationTarget, env, ExtensionContext, Position, Range, Selection, SnippetString, TextDocument, Uri, window, workspace, WorkspaceConfiguration, WorkspaceFolder } from 'vscode'; import { Commands } from './commands'; -import { getJavaConfiguration } from './utils'; +import { cleanupLombokCache } from './lombokSupport'; +import { ensureExists, getJavaConfiguration } from './utils'; +import { apiManager } from './apiManager'; +import { isActive, setActive, smartSemicolonDetection } from './smartSemicolonDetection'; +import { BuildFileSelector, IMPORT_METHOD, PICKED_BUILD_FILES } from './buildFilesSelector'; const DEFAULT_HIDDEN_FILES: string[] = ['**/.classpath', '**/.project', '**/.settings', '**/.factorypath']; +const IS_WORKSPACE_JDK_ALLOWED = "java.ls.isJdkAllowed"; +const IS_WORKSPACE_JLS_JDK_ALLOWED = "java.jdt.ls.java.home.isAllowed"; +export const IS_WORKSPACE_VMARGS_ALLOWED = "java.ls.isVmargsAllowed"; +const extensionName = 'Language Support for Java'; +export const ACTIVE_BUILD_TOOL_STATE = "java.activeBuildTool"; + +export const cleanWorkspaceFileName = '.cleanWorkspace'; const changeItem = { global: 'Exclude globally', @@ -14,10 +26,12 @@ const changeItem = { }; const EXCLUDE_FILE_CONFIG = 'configuration.checkProjectSettingsExclusions'; +export const ORGANIZE_IMPORTS_ON_PASTE = 'actionsOnPaste.organizeImports'; // java.actionsOnPaste.organizeImports let oldConfig: WorkspaceConfiguration = getJavaConfiguration(); +const gradleWrapperPromptDialogs = []; -export function onConfigurationChange() { +export function onConfigurationChange(workspacePath: string, context: ExtensionContext) { return workspace.onDidChangeConfiguration(params => { if (!params.affectsConfiguration('java')) { return; @@ -26,17 +40,49 @@ export function onConfigurationChange() { if (newConfig.get(EXCLUDE_FILE_CONFIG)) { excludeProjectSettingsFiles(); } - if (hasJavaConfigChanged(oldConfig, newConfig)) { - const msg = 'Java Language Server configuration changed, please restart VS Code.'; - const action = 'Restart Now'; + + const isFsModeChanged: boolean = hasConfigKeyChanged('import.generatesMetadataFilesAtProjectRoot', oldConfig, newConfig); + if (isFsModeChanged) { + // Changing the FS mode needs a clean restart. + ensureExists(workspacePath); + const file = path.join(workspacePath, cleanWorkspaceFileName); + fs.closeSync(fs.openSync(file, 'w')); + } + if (isFsModeChanged || hasJavaConfigChanged(oldConfig, newConfig)) { + const msg = `Java Language Server configuration changed, please reload ${env.appName}.`; + const action = 'Reload'; const restartId = Commands.RELOAD_WINDOW; - oldConfig = newConfig; window.showWarningMessage(msg, action).then((selection) => { if (action === selection) { commands.executeCommand(restartId); } }); } + if (hasConfigKeyChanged('jdt.ls.lombokSupport.enabled', oldConfig, newConfig)) { + if (newConfig.get("jdt.ls.lombokSupport.enabled")) { + const msg = `Lombok support is enabled, please reload ${env.appName}.`; + const action = 'Reload'; + const restartId = Commands.RELOAD_WINDOW; + window.showWarningMessage(msg, action).then((selection) => { + if (action === selection) { + commands.executeCommand(restartId); + } + }); + } + else { + cleanupLombokCache(context); + const msg = `Lombok support is disabled, please reload ${env.appName}.`; + const action = 'Reload'; + const restartId = Commands.RELOAD_WINDOW; + window.showWarningMessage(msg, action).then((selection) => { + if (action === selection) { + commands.executeCommand(restartId); + } + }); + } + } + // update old config + oldConfig = newConfig; }); } @@ -49,8 +95,9 @@ export function excludeProjectSettingsFiles() { } function excludeProjectSettingsFilesForWorkspace(workspaceUri: Uri) { - const excudedConfig = getJavaConfiguration().get(EXCLUDE_FILE_CONFIG); - if (excudedConfig) { + const javaConfig = getJavaConfiguration(); + const checkExclusionConfig = javaConfig.get(EXCLUDE_FILE_CONFIG); + if (checkExclusionConfig) { const config = workspace.getConfiguration('files', workspaceUri); const excludedValue: Object = config.get('exclude'); const needExcludeFiles: string[] = []; @@ -64,42 +111,44 @@ function excludeProjectSettingsFilesForWorkspace(workspaceUri: Uri) { } if (needUpdate) { const excludedInspectedValue = config.inspect('exclude'); - const items = [changeItem.workspace, changeItem.never]; - // Workspace file.exclude is undefined - if (!excludedInspectedValue.workspaceValue) { - items.unshift(changeItem.global); - } - - window.showInformationMessage('Do you want to exclude the VS Code Java project settings files (.classpath, .project. .settings, .factorypath) from the file explorer?', ...items).then((result) => { - if (result === changeItem.global) { - excludedInspectedValue.globalValue = excludedInspectedValue.globalValue || {}; - for (const hiddenFile of needExcludeFiles) { - excludedInspectedValue.globalValue[hiddenFile] = true; - } - config.update('exclude', excludedInspectedValue.globalValue, ConfigurationTarget.Global); - } if (result === changeItem.workspace) { - excludedInspectedValue.workspaceValue = excludedInspectedValue.workspaceValue || {}; - for (const hiddenFile of needExcludeFiles) { - excludedInspectedValue.workspaceValue[hiddenFile] = true; - } - config.update('exclude', excludedInspectedValue.workspaceValue, ConfigurationTarget.Workspace); - } else if (result === changeItem.never) { - const storeInWorkspace = getJavaConfiguration().inspect(EXCLUDE_FILE_CONFIG).workspaceValue; - getJavaConfiguration().update(EXCLUDE_FILE_CONFIG, false, storeInWorkspace?ConfigurationTarget.Workspace: ConfigurationTarget.Global); + const checkExclusionInWorkspace = javaConfig.inspect(EXCLUDE_FILE_CONFIG).workspaceValue; + if (checkExclusionInWorkspace) { + const workspaceValue = excludedInspectedValue.workspaceValue || {}; + for (const hiddenFile of needExcludeFiles) { + workspaceValue[hiddenFile] = true; } - }); + config.update('exclude', workspaceValue, ConfigurationTarget.Workspace); + } else { + // by default save to global settings + const globalValue = excludedInspectedValue.globalValue = excludedInspectedValue.globalValue || {}; + for (const hiddenFile of needExcludeFiles) { + globalValue[hiddenFile] = true; + } + config.update('exclude', globalValue, ConfigurationTarget.Global); + } } } } function hasJavaConfigChanged(oldConfig: WorkspaceConfiguration, newConfig: WorkspaceConfiguration) { - return hasConfigKeyChanged('home', oldConfig, newConfig) + return hasConfigKeyChanged('jdt.ls.java.home', oldConfig, newConfig) + || hasConfigKeyChanged('home', oldConfig, newConfig) || hasConfigKeyChanged('jdt.ls.vmargs', oldConfig, newConfig) - || hasConfigKeyChanged('progressReports.enabled', oldConfig, newConfig); + || hasConfigKeyChanged('server.launchMode', oldConfig, newConfig) + || hasConfigKeyChanged('sharedIndexes.location', oldConfig, newConfig) + || hasConfigKeyChanged('transport', oldConfig, newConfig) + || hasConfigKeyChanged('diagnostic.filter', oldConfig, newConfig) + || hasConfigKeyChanged('jdt.ls.javac.enabled', oldConfig, newConfig) + || hasConfigKeyChanged('completion.engine', oldConfig, newConfig) + || hasConfigKeyChanged('jdt.ls.appcds.enabled', oldConfig, newConfig); } function hasConfigKeyChanged(key, oldConfig, newConfig) { - return oldConfig.get(key) !== newConfig.get(key); + const oldValue = oldConfig.get(key); + const newValue = newConfig.get(key); + return Array.isArray(oldValue) && Array.isArray(newValue) + ? JSON.stringify(oldValue) !== JSON.stringify(newValue) + : oldValue !== newValue; } export function getJavaEncoding(): string { @@ -114,3 +163,256 @@ export function getJavaEncoding(): string { } return javaEncoding; } + +export async function checkJavaPreferences(context: ExtensionContext): Promise<{javaHome?: string; preference: string}> { + const allow = 'Allow'; + const disallow = 'Disallow'; + let preference: string = 'java.jdt.ls.java.home'; + let javaHome = workspace.getConfiguration().inspect('java.jdt.ls.java.home').workspaceValue; + let isVerified = javaHome === undefined || javaHome === null; + if (isVerified) { + javaHome = getJavaConfiguration().get('jdt.ls.java.home'); + } + const key = getKey(IS_WORKSPACE_JLS_JDK_ALLOWED, context.storagePath, javaHome); + const globalState = context.globalState; + if (!isVerified) { + isVerified = workspace.isTrusted || globalState.get(key); + if (isVerified === undefined) { + await window.showErrorMessage(`Security Warning! Do you allow this workspace to set the java.jdt.ls.java.home variable? \n java.jdt.ls.java.home: ${javaHome}`, disallow, allow).then(async selection => { + if (selection === allow) { + globalState.update(key, true); + } else if (selection === disallow) { + globalState.update(key, false); + await workspace.getConfiguration().update('java.jdt.ls.java.home', undefined, ConfigurationTarget.Workspace); + } + }); + isVerified = globalState.get(key); + } + if (!isVerified) { // java.jdt.ls.java.home from workspace settings is disallowed. + javaHome = workspace.getConfiguration().inspect('java.jdt.ls.java.home').globalValue; + } + } + + if (!javaHome) { // Read java.home from the deprecated "java.home" setting. + preference = 'java.home'; + javaHome = workspace.getConfiguration().inspect('java.home').workspaceValue; + isVerified = javaHome === undefined || javaHome === null; + if (isVerified) { + javaHome = getJavaConfiguration().get('home'); + } + const key = getKey(IS_WORKSPACE_JDK_ALLOWED, context.storagePath, javaHome); + const globalState = context.globalState; + if (!isVerified) { + isVerified = workspace.isTrusted || globalState.get(key); + if (isVerified === undefined) { + await window.showErrorMessage(`Security Warning! Do you allow this workspace to set the java.home variable? \n java.home: ${javaHome}`, disallow, allow).then(async selection => { + if (selection === allow) { + globalState.update(key, true); + } else if (selection === disallow) { + globalState.update(key, false); + await workspace.getConfiguration().update('java.home', undefined, ConfigurationTarget.Workspace); + } + }); + isVerified = globalState.get(key); + } + if (!isVerified) { // java.home from workspace settings is disallowed. + javaHome = workspace.getConfiguration().inspect('java.home').globalValue; + } + } + } + + const vmargs = workspace.getConfiguration().inspect('java.jdt.ls.vmargs').workspaceValue; + if (vmargs !== undefined) { + const isWorkspaceTrusted = (workspace as any).isTrusted; // keep compatibility for old engines < 1.56.0 + const agentFlag = getJavaagentFlag(vmargs); + if (agentFlag !== null && (isWorkspaceTrusted === undefined || !isWorkspaceTrusted)) { + const keyVmargs = getKey(IS_WORKSPACE_VMARGS_ALLOWED, context.storagePath, vmargs); + const vmargsVerified = globalState.get(keyVmargs); + if ((vmargsVerified === undefined || vmargsVerified === null) && (workspace.workspaceFolders && isInWorkspaceFolder(agentFlag, workspace.workspaceFolders))) { + await window.showErrorMessage(`Security Warning! The java.jdt.ls.vmargs variable defined in ${env.appName} settings includes the (${agentFlag}) javagent preference. Do you allow it to be used?`, disallow, allow).then(async selection => { + if (selection === allow) { + globalState.update(keyVmargs, true); + } else if (selection === disallow) { + globalState.update(keyVmargs, false); + await workspace.getConfiguration().update('java.jdt.ls.vmargs', undefined, ConfigurationTarget.Workspace); + } + }); + } + } + } + + return { + javaHome, + preference + }; +} + +export function getKey(prefix, storagePath, value) { + const workspacePath = path.resolve(`${storagePath}/jdt_ws`); + if (workspace.name !== undefined) { + return `${prefix}::${workspacePath}::${value}`; + } + else { + return `${prefix}::${value}`; + } +} + +export function getJavaagentFlag(vmargs) { + const javaagent = '-javaagent:'; + const args = vmargs.split(" "); + let agentFlag = null; + for (const arg of args) { + if (arg.startsWith(javaagent)) { + agentFlag = arg.substring(javaagent.length); + break; + } + } + return agentFlag; +} + +export function isInWorkspaceFolder(loc: string, workspaceFolders: readonly WorkspaceFolder[]) { + return !path.isAbsolute(loc) || workspaceFolders.some(dir => loc.startsWith(dir.uri.fsPath)); +} + +export enum ServerMode { + standard = 'Standard', + lightWeight = 'LightWeight', + hybrid = 'Hybrid' +} + +export function getJavaServerMode(): ServerMode { + return workspace.getConfiguration().get('java.server.launchMode') + || ServerMode.hybrid; +} + +export function validateAllOpenBuffersOnChanges(): boolean { + return workspace.getConfiguration().get('java.edit.validateAllOpenBuffersOnChanges'); +} + +export function setGradleWrapperChecksum(wrapper: string, sha256?: string) { + const opened = gradleWrapperPromptDialogs.filter(v => (v === sha256)); + if (opened !== null && opened.length > 0) { + return; + } + gradleWrapperPromptDialogs.push(sha256); + const allow = 'Trust'; + const disallow = 'Do not trust'; + window.showErrorMessage(`"Security Warning! The gradle wrapper '${wrapper}'" [sha256 '${sha256}'] [could be malicious](https://github.com/redhat-developer/vscode-java/wiki/Gradle-Support#suspicious.wrapper). Should it be trusted?";`, disallow, allow) + .then(async selection => { + let allowed; + if (selection === allow) { + allowed = true; + } else if (selection === disallow) { + allowed = false; + } else { + unregisterGradleWrapperPromptDialog(sha256); + return false; + } + const key = "java.imports.gradle.wrapper.checksums"; + let property: any = workspace.getConfiguration().inspect(key).globalValue; + if (!Array.isArray(property)) { + property = []; + } + const entry = property.filter(p => (p.sha256 === sha256)); + if (entry === null || entry.length === 0) { + property.push({ sha256: sha256, allowed: allowed }); + workspace.getConfiguration().update(key, property, ConfigurationTarget.Global); + } + unregisterGradleWrapperPromptDialog(sha256); + }); +} + +function unregisterGradleWrapperPromptDialog(sha256: string) { + const index = gradleWrapperPromptDialogs.indexOf(sha256); + if (index > -1) { + gradleWrapperPromptDialogs.splice(index, 1); + } +} + +let serverReady = false; + +export function handleTextDocumentChanges(document: TextDocument, changes: readonly import("vscode").TextDocumentContentChangeEvent[]): any { + if (!serverReady) { + apiManager.getApiInstance().serverReady().then(() => { + serverReady = true; + }); + } + const activeTextEditor = window.activeTextEditor; + const activeDocument = activeTextEditor && activeTextEditor.document; + if (document !== activeDocument || changes.length === 0 || document.languageId !== 'java') { + setActive(false); + return; + } + const lastChange = changes[changes.length - 1]; + if (lastChange.text === null || lastChange.text.length <= 0) { + setActive(false); + return; + } + if (lastChange.text !== '"""";') { + if (lastChange.text === ';' && serverReady && !isActive()) { + smartSemicolonDetection(); + } + setActive(false); + return; + } + setActive(false); + const selection = activeTextEditor.selection.active; + if (selection !== null) { + const start = new Position(selection.line, selection.character - 2); + const end = new Position(selection.line, selection.character + 4); + const range = new Range(start, end); + const activeText = activeDocument.getText(range); + if (activeText === '""""""') { + const tabSize = activeTextEditor.options.tabSize!; + const tabSpaces = activeTextEditor.options.insertSpaces!; + const indentLevel = 2; + const indentSize = tabSpaces ? indentLevel * tabSize : indentLevel; + const repeatChar = tabSpaces ? ' ' : '\t'; + const text = `\n${repeatChar.repeat(indentSize)}\$\{0\}\n${repeatChar.repeat(indentSize)}`; + const position = new Position(selection.line, selection.character + 1); + activeTextEditor.insertSnippet(new SnippetString(text), position); + } + } +} + +export async function getImportMode(context: ExtensionContext, selector: BuildFileSelector): Promise { + const mode = getJavaConfiguration().get("import.projectSelection"); + if (mode === "manual") { + // use automatic mode if user has selected "Import All" before. + if (context.workspaceState.get(IMPORT_METHOD) === "Import All") { + return ImportMode.automatic; + } + + // if no selectable build files, use automatic mode + const hasBuildFiles = await selector.hasBuildFiles(); + if (!hasBuildFiles) { + return ImportMode.automatic; + } + + // If the the manually picked build files has already cached, return manual mode. + if (context.workspaceState.get(PICKED_BUILD_FILES) !== undefined) { + return ImportMode.manual; + } + + const answer: string = await window.showInformationMessage( + "Java build files are detected in the workspace. How do you want to import them?", + { modal: true }, + "Import All", "Let Me Select..."); + if (answer === "Import All") { + context.workspaceState.update(IMPORT_METHOD, "Import All"); + return ImportMode.automatic; + } else if (answer === "Let Me Select...") { + return ImportMode.manual; + } + + return ImportMode.skip; + } + + return ImportMode.automatic; +} + +export enum ImportMode { + automatic = 'automatic', + manual = 'manual', + skip = 'skip', +} diff --git a/src/smartSemicolonDetection.ts b/src/smartSemicolonDetection.ts new file mode 100644 index 0000000000..675f9b90a5 --- /dev/null +++ b/src/smartSemicolonDetection.ts @@ -0,0 +1,45 @@ +'use strict'; + +import { commands, Position, Range, Selection, window } from 'vscode'; +import { Commands } from './commands'; +import { getJavaConfiguration } from './utils'; +let active = false; + +export async function smartSemicolonDetection() { + if (enabled()) { + const params: SmartDetectionParams = { + uri: window.activeTextEditor.document.uri.toString(), + position: window.activeTextEditor!.selection.active, + }; + setActive(true); + const response: SmartDetectionParams = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.SMARTSEMICOLON_DETECTION, JSON.stringify(params)); + if (response !== null) { + window.activeTextEditor!.edit(editBuilder => { + const oldPosition = window.activeTextEditor!.selection.active; + editBuilder.delete(new Range(new Position(oldPosition.line, oldPosition.character - 1), oldPosition)); + const newPos = new Position(response.position.line, response.position.character + 1); + editBuilder.insert(newPos, ";"); + window.activeTextEditor.selections = [new Selection(newPos, newPos)]; + // newPosition = window.activeTextEditor!.selection.active; + }); + return; + } + } +} + +interface SmartDetectionParams { + uri: String; + position: Position; +} + +function enabled() { + return getJavaConfiguration().get("edit.smartSemicolonDetection.enabled"); +} + +export function isActive() { + return active; +} + +export function setActive(pActive: boolean) { + active = pActive; +} \ No newline at end of file diff --git a/src/snippetCompletionProvider.ts b/src/snippetCompletionProvider.ts new file mode 100644 index 0000000000..53601fd195 --- /dev/null +++ b/src/snippetCompletionProvider.ts @@ -0,0 +1,67 @@ +'use strict'; + +import { CompletionItemProvider, TextDocument, Position, CancellationToken, CompletionContext, CompletionItem, CompletionItemKind, SnippetString, MarkdownString, languages, Disposable } from "vscode"; +import * as fse from 'fs-extra'; +import * as path from 'path'; + +class SnippetCompletionProvider implements Disposable { + + private providerImpl: Disposable; + + public initialize(): SnippetCompletionProvider { + this.providerImpl = languages.registerCompletionItemProvider({ scheme: 'file', language: 'java' }, new SnippetCompletionProviderImpl()); + return this; + } + + public dispose(): void { + if (this.providerImpl) { + this.providerImpl.dispose(); + } + } +} + +class SnippetCompletionProviderImpl implements CompletionItemProvider { + + private snippets: {}; + + public constructor() { + this.snippets = fse.readJSONSync(path.join(__dirname, '..', 'snippets', 'server.json')); + } + + public async provideCompletionItems(_document: TextDocument, _position: Position, _token: CancellationToken, _context: CompletionContext): Promise { + + const snippetItems: CompletionItem[] = []; + for (const label of Object.keys(this.snippets)) { + const snippetContent = this.snippets[label]; + if (Array.isArray(snippetContent.prefix)) { + for (const prefix of snippetContent.prefix) { + snippetItems.push(this.getCompletionItem(prefix, snippetContent)); + } + } else { + snippetItems.push(this.getCompletionItem(snippetContent.prefix, snippetContent)); + } + } + return snippetItems; + } + + private getCompletionItem(prefix: string, snippetContent: any) { + const snippetItem: CompletionItem = new CompletionItem(prefix); + snippetItem.kind = CompletionItemKind.Snippet; + snippetItem.detail = snippetContent.description; + const insertText: string = (snippetContent.body as String[]).join('\n'); + snippetItem.insertText = new SnippetString(insertText); + snippetItem.documentation = beautifyDocument(insertText); + return snippetItem; + } +} + +export function beautifyDocument(raw: string): MarkdownString { + const escapedString = raw.replace(/\$\{\d\|(.*?),.*?\}/gm, '$1') + .replace(/\$\{\d:?(.*?)\}/gm, '$1') + .replace(/\$\d/gm, '') + .replace(/\${TM_SELECTED_TEXT:}/gm, '') + .replace(/\${TM_FILENAME_BASE}/gm, ''); + return new MarkdownString().appendCodeblock(escapedString, "java"); +} + +export const snippetCompletionProvider: SnippetCompletionProvider = new SnippetCompletionProvider(); diff --git a/src/sourceAction.ts b/src/sourceAction.ts index 21f0c8b9a4..a0009a89bf 100644 --- a/src/sourceAction.ts +++ b/src/sourceAction.ts @@ -1,16 +1,37 @@ 'use strict'; -import { commands, window, ExtensionContext, Range, ViewColumn, Uri, Disposable } from 'vscode'; -import { CodeActionParams, LanguageClient } from 'vscode-languageclient'; +import { Disposable, ExtensionContext, TextEditorRevealType, Uri, ViewColumn, commands, window, workspace } from 'vscode'; +import { CodeActionParams, WorkspaceEdit } from 'vscode-languageclient'; +import { LanguageClient } from 'vscode-languageclient/node'; import { Commands } from './commands'; -import { applyWorkspaceEdit } from './extension'; -import { ListOverridableMethodsRequest, AddOverridableMethodsRequest, CheckHashCodeEqualsStatusRequest, GenerateHashCodeEqualsRequest, -OrganizeImportsRequest, ImportCandidate, ImportSelection, GenerateToStringRequest, CheckToStringStatusRequest, VariableBinding, ResolveUnimplementedAccessorsRequest, GenerateAccessorsRequest, CheckConstructorStatusRequest, GenerateConstructorsRequest, CheckDelegateMethodsStatusRequest, GenerateDelegateMethodsRequest } from './protocol'; +import { getActiveLanguageClient } from './extension'; +import { + AccessorCodeActionParams, + AccessorCodeActionRequest, + AccessorKind, + AddOverridableMethodsRequest, + CheckConstructorStatusRequest, + CheckDelegateMethodsStatusRequest, + CheckHashCodeEqualsStatusRequest, + CheckToStringStatusRequest, + CleanupRequest, + GenerateAccessorsRequest, + GenerateConstructorsRequest, + GenerateDelegateMethodsRequest, + GenerateHashCodeEqualsRequest, + GenerateToStringRequest, + ImportCandidate, ImportSelection, + ListOverridableMethodsRequest, + OrganizeImportsRequest, + VariableBinding +} from './protocol'; +import { applyWorkspaceEdit } from './standardLanguageClient'; export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) { registerOverrideMethodsCommand(languageClient, context); registerHashCodeEqualsCommand(languageClient, context); registerOrganizeImportsCommand(languageClient, context); + registerCleanupCommand(languageClient, context); registerChooseImportCommand(context); registerGenerateToStringCommand(languageClient, context); registerGenerateAccessorsCommand(languageClient, context); @@ -53,7 +74,7 @@ function registerOverrideMethodsCommand(languageClient: LanguageClient, context: canPickMany: true, placeHolder: `Select methods to override or implement in ${result.type}` }); - if (!selectedItems.length) { + if (!selectedItems || !selectedItems.length) { return; } @@ -61,7 +82,17 @@ function registerOverrideMethodsCommand(languageClient: LanguageClient, context: context: params, overridableMethods: selectedItems.map((item) => item.originalMethod), }); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); + })); +} + +function registerCleanupCommand(languageClient: LanguageClient, context: ExtensionContext): void { + // Only active when editorLangId == java + context.subscriptions.push(commands.registerCommand(Commands.MANUAL_CLEANUP, async () => { + const languageClient: LanguageClient | undefined = await getActiveLanguageClient(); + const workspaceEdit = await languageClient.sendRequest(CleanupRequest.type, languageClient.code2ProtocolConverter.asTextDocumentIdentifier(window.activeTextEditor.document)); + await applyWorkspaceEdit(workspaceEdit, languageClient); })); } @@ -95,7 +126,7 @@ function registerHashCodeEqualsCommand(languageClient: LanguageClient, context: canPickMany: true, placeHolder: 'Select the fields to include in the hashCode() and equals() methods.' }); - if (!selectedFields.length) { + if (!selectedFields || !selectedFields.length) { return; } @@ -104,19 +135,20 @@ function registerHashCodeEqualsCommand(languageClient: LanguageClient, context: fields: selectedFields.map((item) => item.originalField), regenerate }); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); })); } function registerOrganizeImportsCommand(languageClient: LanguageClient, context: ExtensionContext): void { context.subscriptions.push(commands.registerCommand(Commands.ORGANIZE_IMPORTS, async (params: CodeActionParams) => { const workspaceEdit = await languageClient.sendRequest(OrganizeImportsRequest.type, params); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); })); } function registerChooseImportCommand(context: ExtensionContext): void { - context.subscriptions.push(commands.registerCommand(Commands.CHOOSE_IMPORTS, async (uri: string, selections: ImportSelection[]) => { + context.subscriptions.push(commands.registerCommand(Commands.CHOOSE_IMPORTS, async (uri: string, selections: ImportSelection[], restoreExistingImports?: boolean) => { const chosen: ImportCandidate[] = []; const fileUri: Uri = Uri.parse(uri); for (let i = 0; i < selections.length; i++) { @@ -137,7 +169,7 @@ function registerChooseImportCommand(context: ExtensionContext): void { try { const pick = await new Promise((resolve, reject) => { const input = window.createQuickPick(); - input.title = "Organize Imports"; + input.title = restoreExistingImports ? "Add All Missing Imports" : "Organize Imports"; input.step = i + 1; input.totalSteps = selections.length; input.placeholder = `Choose type '${typeName}' to import`; @@ -183,7 +215,7 @@ function registerGenerateToStringCommand(languageClient: LanguageClient, context const fieldItems = result.fields.map((field) => { return { label: `${field.name}: ${field.type}`, - picked: true, + picked: field.isSelected, originalField: field }; }); @@ -202,45 +234,65 @@ function registerGenerateToStringCommand(languageClient: LanguageClient, context context: params, fields, }); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); })); } function registerGenerateAccessorsCommand(languageClient: LanguageClient, context: ExtensionContext): void { - context.subscriptions.push(commands.registerCommand(Commands.GENERATE_ACCESSORS_PROMPT, async (params: CodeActionParams) => { - const accessors = await languageClient.sendRequest(ResolveUnimplementedAccessorsRequest.type, params); - if (!accessors || !accessors.length) { - return; - } + context.subscriptions.push(commands.registerCommand(Commands.GENERATE_ACCESSORS_PROMPT, async (params: AccessorCodeActionParams) => { + await generateAccessors(languageClient, params); + })); +} - const accessorItems = accessors.map((accessor) => { - const description = []; - if (accessor.generateGetter) { - description.push('getter'); - } - if (accessor.generateSetter) { - description.push('setter'); - } - return { - label: accessor.fieldName, - description: (accessor.isStatic?'static ':'')+ description.join(', '), - originalField: accessor, - }; - }); - const selectedAccessors = await window.showQuickPick(accessorItems, { - canPickMany: true, - placeHolder: 'Select the fields to generate getters and setters.' - }); - if (!selectedAccessors.length) { - return; - } +async function generateAccessors(languageClient: LanguageClient, params: AccessorCodeActionParams): Promise { + const accessors = await languageClient.sendRequest(AccessorCodeActionRequest.type, params); + if (!accessors || !accessors.length) { + return; + } - const workspaceEdit = await languageClient.sendRequest(GenerateAccessorsRequest.type, { - context: params, - accessors: selectedAccessors.map((item) => item.originalField), - }); - applyWorkspaceEdit(workspaceEdit, languageClient); - })); + const accessorItems = accessors.map((accessor) => { + const description = []; + if (accessor.generateGetter) { + description.push('getter'); + } + if (accessor.generateSetter) { + description.push('setter'); + } + return { + label: `${accessor.fieldName}: ${accessor.typeName}`, + description: (accessor.isStatic ? 'static ' : '')+ description.join(', '), + originalField: accessor, + }; + }); + let accessorsKind: string; + switch (params.kind) { + case AccessorKind.both: + accessorsKind = "getters and setters"; + break; + case AccessorKind.getter: + accessorsKind = "getters"; + break; + case AccessorKind.setter: + accessorsKind = "setters"; + break; + default: + return; + } + const selectedAccessors = await window.showQuickPick(accessorItems, { + canPickMany: true, + placeHolder: `Select the fields to generate ${accessorsKind}` + }); + if (!selectedAccessors || !selectedAccessors.length) { + return; + } + + const workspaceEdit = await languageClient.sendRequest(GenerateAccessorsRequest.type, { + context: params, + accessors: selectedAccessors.map((item) => item.originalField), + }); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); } function registerGenerateConstructorsCommand(languageClient: LanguageClient, context: ExtensionContext): void { @@ -275,6 +327,7 @@ function registerGenerateConstructorsCommand(languageClient: LanguageClient, con return { label: `${field.name}: ${field.type}`, originalField: field, + picked: field.isSelected }; }); const selectedFieldItems = await window.showQuickPick(fieldItems, { @@ -293,7 +346,8 @@ function registerGenerateConstructorsCommand(languageClient: LanguageClient, con constructors: selectedConstructors, fields: selectedFields, }); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); })); } @@ -323,12 +377,12 @@ function registerGenerateDelegateMethodsCommand(languageClient: LanguageClient, selectedDelegateField = selectedFieldItem.originalField; } - let delegateEntryItems = selectedDelegateField.delegateMethods.map(delegateMethod => { + const delegateEntryItems = selectedDelegateField.delegateMethods.map(delegateMethod => { return { label: `${selectedDelegateField.field.name}.${delegateMethod.name}(${delegateMethod.parameters.join(',')})`, originalField: selectedDelegateField.field, originalMethod: delegateMethod, - } + }; }); if (!delegateEntryItems.length) { @@ -354,6 +408,22 @@ function registerGenerateDelegateMethodsCommand(languageClient: LanguageClient, context: params, delegateEntries, }); - applyWorkspaceEdit(workspaceEdit, languageClient); + await applyWorkspaceEdit(workspaceEdit, languageClient); + await revealWorkspaceEdit(workspaceEdit, languageClient); })); -} \ No newline at end of file +} + +async function revealWorkspaceEdit(workspaceEdit: WorkspaceEdit, languageClient: LanguageClient): Promise { + const codeWorkspaceEdit = await languageClient.protocol2CodeConverter.asWorkspaceEdit(workspaceEdit); + if (!codeWorkspaceEdit) { + return; + } + for (const entry of codeWorkspaceEdit.entries()) { + await workspace.openTextDocument(entry[0]); + if (entry[1].length > 0) { + // reveal first available change of the workspace edit + window.activeTextEditor.revealRange(entry[1][0].range, TextEditorRevealType.InCenter); + break; + } + } +} diff --git a/src/standardLanguageClient.ts b/src/standardLanguageClient.ts new file mode 100644 index 0000000000..7a0aae0eb3 --- /dev/null +++ b/src/standardLanguageClient.ts @@ -0,0 +1,957 @@ +'use strict'; + +import * as net from 'net'; +import * as path from 'path'; +import { CancellationToken, CodeActionKind, commands, ConfigurationTarget, DocumentSelector, EventEmitter, ExtensionContext, extensions, languages, Location, ProgressLocation, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceConfiguration } from "vscode"; +import { ConfigurationParams, ConfigurationRequest, LanguageClientOptions, Location as LSLocation, MessageType, Position as LSPosition, TextDocumentPositionParams, WorkspaceEdit, StaticFeature, ClientCapabilities, FeatureState, TelemetryEventNotification } from "vscode-languageclient"; +import { LanguageClient, StreamInfo } from "vscode-languageclient/node"; +import { apiManager } from "./apiManager"; +import * as buildPath from './buildpath'; +import { javaRefactorKinds, RefactorDocumentProvider } from "./codeActionProvider"; +import { Commands } from "./commands"; +import { ClientStatus } from "./extension.api"; +import * as fileEventHandler from './fileEventHandler'; +import { gradleCodeActionMetadata, GradleCodeActionProvider } from "./gradle/gradleCodeActionProvider"; +import { awaitServerConnection, prepareExecutable, DEBUG } from "./javaServerStarter"; +import { logger } from "./log"; +import { checkLombokDependency } from "./lombokSupport"; +import { markdownPreviewProvider } from "./markdownPreviewProvider"; +import * as pasteAction from './pasteAction'; +import { registerPasteEventHandler } from './pasteEventHandler'; +import { collectBuildFilePattern, onExtensionChange } from "./plugin"; +import { pomCodeActionMetadata, PomCodeActionProvider } from "./pom/pomCodeActionProvider"; +import { ActionableNotification, BuildProjectParams, BuildProjectRequest, CompileWorkspaceRequest, CompileWorkspaceStatus, EventNotification, EventType, ExecuteClientCommandRequest, FeatureStatus, FindLinks, GradleCompatibilityInfo, LinkLocation, ProgressKind, ProgressNotification, ServerNotification, SourceAttachmentAttribute, SourceAttachmentRequest, SourceAttachmentResult, SourceInvalidatedEvent, StatusNotification, UpgradeGradleWrapperInfo } from "./protocol"; +import * as refactorAction from './refactorAction'; +import { getJdkUrl, RequirementsData } from "./requirements"; +import { serverStatus, ServerStatusKind } from "./serverStatus"; +import { serverStatusBarProvider } from "./serverStatusBarProvider"; +import { activationProgressNotification, serverTaskPresenter } from "./serverTaskPresenter"; +import { serverTasks } from "./serverTasks"; +import { excludeProjectSettingsFiles, ServerMode, setGradleWrapperChecksum } from "./settings"; +import { snippetCompletionProvider } from "./snippetCompletionProvider"; +import * as sourceAction from './sourceAction'; +import { askForProjects, projectConfigurationUpdate, upgradeGradle } from "./standardLanguageClientUtils"; +import { TracingLanguageClient } from './TracingLanguageClient'; +import { TypeHierarchyDirection, TypeHierarchyItem } from "./typeHierarchy/protocol"; +import { typeHierarchyTree } from "./typeHierarchy/typeHierarchyTree"; +import { getAllJavaProjects, getAllProjects, getJavaConfiguration, isPrereleaseOrInsiderVersion } from "./utils"; +import { Telemetry } from "./telemetry"; +import { TelemetryEvent } from "@redhat-developer/vscode-redhat-telemetry/lib"; +import { registerDocumentValidationListener } from './diagnostic'; +import { listJdks, sortJdksBySource, sortJdksByVersion } from './jdkUtils'; +import { ClientCodeActionProvider } from './clientCodeActionProvider'; +import { BuildFileSelector } from './buildFilesSelector'; +import { extendedOutlineQuickPick } from "./outline/extendedOutlineQuickPick"; + +const extensionName = 'Language Support for Java'; +const GRADLE_CHECKSUM = "gradle/checksum/prompt"; +const GET_JDK = "Get the Java Development Kit"; +const USE_JAVA = "Use Java "; +const AS_GRADLE_JVM = " as Gradle JVM"; +const UPGRADE_GRADLE = "Upgrade Gradle to "; +const GRADLE_IMPORT_JVM = "java.import.gradle.java.home"; +export const JAVA_SELECTOR: DocumentSelector = [ + { scheme: "file", language: "java", pattern: "**/*.java" }, + { scheme: "jdt", language: "java", pattern: "**/*.class" }, + { scheme: "untitled", language: "java", pattern: "**/*.java" } +]; + +export class StandardLanguageClient { + + private languageClient: LanguageClient; + private status: ClientStatus = ClientStatus.uninitialized; + + public async initialize(context: ExtensionContext, requirements: RequirementsData, clientOptions: LanguageClientOptions, workspacePath: string, jdtEventEmitter: EventEmitter): Promise { + if (this.status !== ClientStatus.uninitialized) { + return; + } + + if (workspace.getConfiguration().get("java.showBuildStatusOnStart.enabled") === "terminal") { + commands.executeCommand(Commands.SHOW_SERVER_TASK_STATUS); + } + + context.subscriptions.push(commands.registerCommand(Commands.RUNTIME_VALIDATION_OPEN, () => { + commands.executeCommand("workbench.action.openSettings", "java.configuration.runtimes"); + })); + + serverStatus.initialize(); + serverStatus.onServerStatusChanged(status => { + if (status === ServerStatusKind.error) { + serverStatusBarProvider.setError(); + } else if (status === ServerStatusKind.warning) { + serverStatusBarProvider.setWarning(); + } else if (status === ServerStatusKind.ready) { + serverStatusBarProvider.setReady(); + } + }); + + let serverOptions; + const port = process.env['JDTLS_SERVER_PORT']; + if (!port) { + const lsPort = process.env['JDTLS_CLIENT_PORT']; + if (!lsPort) { + serverOptions = prepareExecutable(requirements, workspacePath, context, false); + } else { + serverOptions = () => { + const socket = net.connect(lsPort); + const result: StreamInfo = { + writer: socket, + reader: socket + }; + return Promise.resolve(result); + }; + } + } else { + // used during development + serverOptions = awaitServerConnection.bind(null, port); + } + + // Create the language client and start the client. + this.languageClient = new TracingLanguageClient('java', extensionName, serverOptions, clientOptions, DEBUG); + this.languageClient.registerFeature(new DisableWillRenameFeature()); + + this.registerCommandsForStandardServer(context, jdtEventEmitter); + fileEventHandler.registerFileEventHandlers(this.languageClient, context); + + collectBuildFilePattern(extensions.all); + + this.status = ClientStatus.initialized; + } + + public registerLanguageClientActions(context: ExtensionContext, hasImported: boolean, jdtEventEmitter: EventEmitter) { + activationProgressNotification.showProgress(); + this.languageClient.onNotification(StatusNotification.type, (report) => { + // Resolve serverRunning on the first status notification from the server, + // indicating the server process is alive and can accept requests. + apiManager.resolveServerRunningPromise(); + switch (report.type) { + case 'ServiceReady': + apiManager.updateServerMode(ServerMode.standard); + apiManager.fireDidServerModeChange(ServerMode.standard); + apiManager.resolveServerReadyPromise(); + + if (extensions.onDidChange) {// Theia doesn't support this API yet + extensions.onDidChange(async () => { + await onExtensionChange(extensions.all); + }); + } + try { + registerPasteEventHandler(context, this.languageClient); + } catch (error) { + // clients may not have properly configured documentPaste + logger.error(error); + } + activationProgressNotification.hide(); + if (!hasImported) { + showImportFinishNotification(context); + } + checkLombokDependency(context); + apiManager.getApiInstance().onDidClasspathUpdate((projectUri: Uri) => { + checkLombokDependency(context, projectUri); + }); + // Disable the client-side snippet provider since LS is ready. + snippetCompletionProvider.dispose(); + registerDocumentValidationListener(context, this.languageClient); + commands.executeCommand('setContext', 'javaLSReady', true); + break; + case 'Started': + this.status = ClientStatus.started; + serverStatus.updateServerStatus(ServerStatusKind.ready); + apiManager.updateStatus(ClientStatus.started); + break; + case 'Error': + this.status = ClientStatus.error; + serverStatus.updateServerStatus(ServerStatusKind.error); + apiManager.updateStatus(ClientStatus.error); + apiManager.fireTraceEvent({ + name: "java.ls.error.serviceError", + properties: { + message: report.message, + }, + }); + break; + case 'ProjectStatus': + if (report.message === "WARNING") { + serverStatus.updateServerStatus(ServerStatusKind.warning); + } else if (report.message === "OK") { + this.status = ClientStatus.started; + serverStatus.errorResolved(); + serverStatus.updateServerStatus(ServerStatusKind.ready); + } + return; + case 'Starting': + case 'Message': + // message goes to progress report instead + break; + } + }); + + this.languageClient.onNotification(ProgressNotification.type, (progress) => { + progress.complete = progress.value.kind === ProgressKind.end; + serverTasks.updateServerTask(progress); + }); + + this.languageClient.onNotification(EventNotification.type, async (notification) => { + switch (notification.eventType) { + case EventType.classpathUpdated: + apiManager.fireDidClasspathUpdate(Uri.parse(notification.data)); + break; + case EventType.projectsImported: { + const projectUris: Uri[] = []; + if (notification.data) { + for (const uriString of notification.data) { + projectUris.push(Uri.parse(uriString)); + } + } + if (projectUris.length > 0) { + apiManager.fireDidProjectsImport(projectUris); + } + break; + } + case EventType.projectsDeleted: { + const projectUris: Uri[] = []; + if (notification.data) { + for (const uriString of notification.data) { + projectUris.push(Uri.parse(uriString)); + } + } + if (projectUris.length > 0) { + apiManager.fireDidProjectsDelete(projectUris); + } + break; + } + case EventType.incompatibleGradleJdkIssue: + const options: string[] = []; + const info = notification.data as GradleCompatibilityInfo; + const highestJavaVersion = Number(info.highestJavaVersion); + let runtimes = await listJdks(true); + runtimes = runtimes.filter(runtime => { + return runtime.version.major <= highestJavaVersion; + }); + sortJdksByVersion(runtimes); + sortJdksBySource(runtimes); + options.push(UPGRADE_GRADLE + info.recommendedGradleVersion); + if (!runtimes.length) { + options.push(GET_JDK); + } else { + options.push(USE_JAVA + runtimes[0].version.major + AS_GRADLE_JVM); + } + this.showGradleCompatibilityIssueNotification(info.message, options, info.projectUri, info.recommendedGradleVersion, runtimes[0]?.homedir); + break; + case EventType.upgradeGradleWrapper: + const neverShow: boolean | undefined = context.globalState.get("java.neverShowUpgradeWrapperNotification"); + if (!neverShow) { + const upgradeInfo = notification.data as UpgradeGradleWrapperInfo; + const option = `Upgrade to ${upgradeInfo.recommendedGradleVersion}`; + window.showWarningMessage(upgradeInfo.message, option, "Don't show again").then(async (choice) => { + if (choice === option) { + await upgradeGradle(upgradeInfo.projectUri, upgradeInfo.recommendedGradleVersion); + } else if (choice === "Don't show again") { + context.globalState.update("java.neverShowUpgradeWrapperNotification", true); + } + }); + } + break; + case EventType.sourceInvalidated: + const result = notification.data as SourceInvalidatedEvent; + const triggeredByUser: string[] = []; + const triggeredByAutoDownloadedSource: string[] = []; + Object.entries(result.affectedRootPaths || {})?.forEach(([key, value]) => { + if (value) { + triggeredByAutoDownloadedSource.push(key); + } else { + triggeredByUser.push(key); + } + }); + if (triggeredByUser?.length) { + this.handleSourceInvalidatedEvent(triggeredByUser, false, jdtEventEmitter); + } + if (triggeredByAutoDownloadedSource?.length) { + this.handleSourceInvalidatedEvent(triggeredByAutoDownloadedSource, true, jdtEventEmitter); + } + default: + break; + } + }); + + this.languageClient.onNotification(ActionableNotification.type, (notification) => { + let show = null; + switch (notification.severity) { + case MessageType.Log: + show = logNotification; + break; + case MessageType.Info: + show = window.showInformationMessage; + break; + case MessageType.Warning: + show = window.showWarningMessage; + break; + case MessageType.Error: + show = window.showErrorMessage; + apiManager.fireTraceEvent({ + name: "java.ls.error.notification", + properties: { + message: notification.message, + }, + }); + break; + } + if (!show) { + return; + } + const titles = notification.commands.map(a => a.title); + show(notification.message, ...titles).then((selection) => { + for (const action of notification.commands) { + if (action.title === selection) { + const args: any[] = (action.arguments) ? action.arguments : []; + commands.executeCommand(action.command, ...args); + break; + } + } + }); + }); + + this.languageClient.onRequest(ExecuteClientCommandRequest.type, (params) => { + return commands.executeCommand(params.command, ...params.arguments); + }); + + this.languageClient.onNotification(ServerNotification.type, (params) => { + commands.executeCommand(params.command, ...params.arguments); + }); + + this.languageClient.onRequest(ConfigurationRequest.type, (params: ConfigurationParams) => { + const result: any[] = []; + const activeEditor: TextEditor | undefined = window.activeTextEditor; + for (const item of params.items) { + const scopeUri: Uri | undefined = item.scopeUri && Uri.parse(item.scopeUri); + if (scopeUri && scopeUri.toString() === activeEditor?.document.uri.toString()) { + if (item.section === "java.format.insertSpaces") { + result.push(activeEditor.options.insertSpaces); + } else if (item.section === "java.format.tabSize") { + result.push(activeEditor.options.tabSize); + } else { + result.push(null); + } + } else { + result.push(workspace.getConfiguration(null, scopeUri).get(item.section, null /* defaultValue */)); + } + } + return result; + }); + + function getJavaSettingsForTelemetry(config: WorkspaceConfiguration) { + // settings whose values we can record + const SETTINGS_BASIC = [ + "java.quickfix.showAt", "java.symbols.includeSourceMethodDeclarations", + "java.completion.collapseCompletionItems", "java.completion.guessMethodArguments", + "java.cleanup.actionsOnSave", "java.completion.postfix.enabled", + "java.sharedIndexes.enabled", "java.inlayHints.parameterNames.enabled", + "java.inlayHints.parameterNames.suppressWhenSameNameNumbered", + "java.inlayHints.variableTypes.enabled", + "java.inlayHints.parameterTypes.enabled", + "java.inlayHints.formatParameters.enabled", + "java.server.launchMode", "java.autobuild.enabled" + ]; + + // settings where we only record their existence + const SETTINGS_CUSTOM = [ + "java.settings.url", "java.format.settings.url" + ]; + + let value: any; + const properties = {}; + + for (const key of SETTINGS_CUSTOM) { + if (config.get(key)) { + properties[key] = true; + } + } + for (const key of SETTINGS_BASIC) { + value = config.get(key); + if (value !== undefined) { + properties[key] = value; + } + } + + return properties; + } + + this.languageClient.onTelemetry(async (e: TelemetryEvent) => { + apiManager.fireTraceEvent(e); + if (e.name === Telemetry.SERVER_INITIALIZED_EVT) { + const javaSettings = getJavaSettingsForTelemetry(workspace.getConfiguration()); + + const properties= { ...e.properties, ...javaSettings }; + await Telemetry.sendTelemetry(Telemetry.STARTUP_EVT, properties); + } else if (e.name === Telemetry.LS_ERROR) { + const tags = []; + const exception: string = e?.properties.exception; + const message: string = e?.properties.message; + if (exception !== undefined) { + if (exception.includes("dtree.ObjectNotFoundException")) { + tags.push("dtree.ObjectNotFoundException"); + } + } + if (message !== undefined) { + if (message.includes("workspace exited with unsaved changes")) { + tags.push("workspace-exited-unsaved-changes"); + } + } + + if (tags.length > 0 || DEBUG || isPrereleaseOrInsiderVersion(context)) { + e.properties['tags'] = tags; + await Telemetry.sendTelemetry(Telemetry.LS_ERROR, e.properties); + } + } + }); + + context.subscriptions.push(commands.registerCommand(GRADLE_CHECKSUM, (wrapper: string, sha256: string) => { + setGradleWrapperChecksum(wrapper, sha256); + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_JAVA_REFERENCES, (uri: string, position: LSPosition, locations: LSLocation[]) => { + commands.executeCommand(Commands.SHOW_REFERENCES, Uri.parse(uri), this.languageClient.protocol2CodeConverter.asPosition(position), locations.map(this.languageClient.protocol2CodeConverter.asLocation)); + })); + context.subscriptions.push(commands.registerCommand(Commands.SHOW_JAVA_IMPLEMENTATIONS, (uri: string, position: LSPosition, locations: LSLocation[]) => { + commands.executeCommand(Commands.SHOW_REFERENCES, Uri.parse(uri), this.languageClient.protocol2CodeConverter.asPosition(position), locations.map(this.languageClient.protocol2CodeConverter.asLocation)); + })); + + context.subscriptions.push(commands.registerCommand(Commands.CONFIGURATION_UPDATE, async (uri) => { + await projectConfigurationUpdate(this.languageClient, uri); + })); + + context.subscriptions.push(commands.registerCommand(Commands.IGNORE_INCOMPLETE_CLASSPATH, () => setIncompleteClasspathSeverity('ignore'))); + + context.subscriptions.push(commands.registerCommand(Commands.IGNORE_INCOMPLETE_CLASSPATH_HELP, () => { + commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse('https://github.com/redhat-developer/vscode-java/wiki/%22Classpath-is-incomplete%22-warning')); + })); + + context.subscriptions.push(commands.registerCommand(Commands.PROJECT_CONFIGURATION_STATUS, async (uri, status) => { + await setProjectConfigurationUpdate(this.languageClient, uri, status); + })); + + context.subscriptions.push(commands.registerCommand(Commands.NULL_ANALYSIS_SET_MODE, (status) => setNullAnalysisStatus(status))); + + context.subscriptions.push(commands.registerCommand(Commands.APPLY_WORKSPACE_EDIT, (obj) => { + applyWorkspaceEdit(obj, this.languageClient); + })); + + context.subscriptions.push(commands.registerCommand(Commands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND, async (location: LinkLocation | Uri) => { + let superImplLocation: Location | undefined; + + if (!location) { // comes from command palette + if (window.activeTextEditor?.document.languageId !== "java") { + return; + } + location = window.activeTextEditor.document.uri; + } + + if (location instanceof Uri) { // comes from context menu + const params: TextDocumentPositionParams = { + textDocument: { + uri: location.toString(), + }, + position: this.languageClient.code2ProtocolConverter.asPosition(window.activeTextEditor.selection.active), + }; + const response = await this.languageClient.sendRequest(FindLinks.type, { + type: 'superImplementation', + position: params, + }); + + if (response && response.length > 0) { + const superImpl = response[0]; + superImplLocation = new Location( + Uri.parse(superImpl.uri), + this.languageClient.protocol2CodeConverter.asRange(superImpl.range) + ); + } + } else { // comes from hover information + superImplLocation = new Location( + Uri.parse(decodeBase64(location.uri)), + this.languageClient.protocol2CodeConverter.asRange(location.range), + ); + } + + if (superImplLocation) { + return window.showTextDocument(superImplLocation.uri, { + preserveFocus: true, + selection: superImplLocation.range, + }); + } else { + return showNoLocationFound('No super implementation found'); + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_TYPE_HIERARCHY, (location: any) => { + if (location instanceof Uri) { + typeHierarchyTree.setTypeHierarchy(new Location(location, window.activeTextEditor.selection.active), TypeHierarchyDirection.both); + } else { + if (window.activeTextEditor?.document?.languageId !== "java") { + return; + } + typeHierarchyTree.setTypeHierarchy(new Location(window.activeTextEditor.document.uri, window.activeTextEditor.selection.active), TypeHierarchyDirection.both); + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_CLASS_HIERARCHY, () => { + typeHierarchyTree.changeDirection(TypeHierarchyDirection.both); + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_SUPERTYPE_HIERARCHY, () => { + typeHierarchyTree.changeDirection(TypeHierarchyDirection.parents); + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_SUBTYPE_HIERARCHY, () => { + typeHierarchyTree.changeDirection(TypeHierarchyDirection.children); + })); + + context.subscriptions.push(commands.registerCommand(Commands.CHANGE_BASE_TYPE, async (item: TypeHierarchyItem) => { + typeHierarchyTree.changeBaseItem(item); + })); + + context.subscriptions.push(commands.registerCommand(Commands.BUILD_PROJECT, async (uris: Uri[] | Uri, isFullBuild: boolean, token: CancellationToken) => { + let resources: Uri[] = []; + if (uris instanceof Uri) { + resources.push(uris); + } else if (Array.isArray(uris)) { + for (const uri of uris) { + if (uri instanceof Uri) { + resources.push(uri); + } + } + } + + if (!resources.length) { + resources = await askForProjects( + window.activeTextEditor?.document.uri, + "Please select the project(s) to rebuild.", + ); + if (!resources?.length) { + return; + } + } + + const params: BuildProjectParams = { + identifiers: resources.map((u => { + return { uri: u.toString() }; + })), + // we can consider expose 'isFullBuild' according to users' feedback, + // currently set it to true by default. + isFullBuild: isFullBuild === undefined ? false : isFullBuild, + }; + + return window.withProgress({ location: ProgressLocation.Window }, async p => { + p.report({ message: 'Rebuilding projects...' }); + const start = new Date().getTime(); + + let res: CompileWorkspaceStatus; + try { + res = token ? await this.languageClient.sendRequest(BuildProjectRequest.type, params, token) : + await this.languageClient.sendRequest(BuildProjectRequest.type, params); + } catch (error) { + if (error && error.code === -32800) { // Check if the request is cancelled. + res = CompileWorkspaceStatus.cancelled; + } + throw error; + } + + const elapsed = new Date().getTime() - start; + const humanVisibleDelay = elapsed < 1000 ? 1000 : 0; + return new Promise(async (resolve, reject) => { + setTimeout(() => { // set a timeout so user would still see the message when build time is short + resolve(res); + }, humanVisibleDelay); + }); + }); + })); + + context.subscriptions.push(commands.registerCommand(Commands.COMPILE_WORKSPACE, (isFullCompile: boolean, token?: CancellationToken) => { + return window.withProgress({ location: ProgressLocation.Window }, async p => { + if (typeof isFullCompile !== 'boolean') { + const selection = await window.showQuickPick(['Incremental', 'Full'], { placeHolder: 'please choose compile type:' }); + isFullCompile = selection !== 'Incremental'; + } + p.report({ message: 'Compiling workspace...' }); + const start = new Date().getTime(); + let res: CompileWorkspaceStatus; + try { + res = token ? await this.languageClient.sendRequest(CompileWorkspaceRequest.type, isFullCompile, token) + : await this.languageClient.sendRequest(CompileWorkspaceRequest.type, isFullCompile); + } catch (error) { + if (error && error.code === -32800) { // Check if the request is cancelled. + res = CompileWorkspaceStatus.cancelled; + } else { + throw error; + } + } + + const elapsed = new Date().getTime() - start; + const humanVisibleDelay = elapsed < 1000 ? 1000 : 0; + return new Promise((resolve, reject) => { + setTimeout(() => { // set a timeout so user would still see the message when build time is short + resolve(res); + }, humanVisibleDelay); + }); + }); + })); + + context.subscriptions.push(commands.registerCommand(Commands.UPDATE_SOURCE_ATTACHMENT_CMD, async (classFileUri: Uri): Promise => { + const resolveRequest: SourceAttachmentRequest = { + classFileUri: classFileUri.toString(), + }; + const resolveResult: SourceAttachmentResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_SOURCE_ATTACHMENT, JSON.stringify(resolveRequest)); + if (resolveResult.errorMessage) { + window.showErrorMessage(resolveResult.errorMessage); + return false; + } + + const attributes: SourceAttachmentAttribute = resolveResult.attributes || {}; + const defaultPath = attributes.sourceAttachmentPath || attributes.jarPath; + const sourceFileUris: Uri[] = await window.showOpenDialog({ + defaultUri: defaultPath ? Uri.file(defaultPath) : null, + openLabel: 'Select Source File', + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: false, + filters: { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'Source files': ['jar', 'zip'] + }, + }); + + if (sourceFileUris && sourceFileUris.length) { + const updateRequest: SourceAttachmentRequest = { + classFileUri: classFileUri.toString(), + attributes: { + ...attributes, + sourceAttachmentPath: sourceFileUris[0].fsPath + }, + }; + const updateResult: SourceAttachmentResult = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.UPDATE_SOURCE_ATTACHMENT, JSON.stringify(updateRequest)); + if (updateResult.errorMessage) { + window.showErrorMessage(updateResult.errorMessage); + return false; + } + + // Notify jdt content provider to rerender the classfile contents. + jdtEventEmitter.fire(classFileUri); + return true; + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_EXTEND_OUTLINE, (location: any) => { + if (location instanceof Uri) { + extendedOutlineQuickPick.open(location); + } else { + if (window.activeTextEditor?.document?.languageId !== "java") { + return; + } + extendedOutlineQuickPick.open(window.activeTextEditor.document.uri); + } + })); + + buildPath.registerCommands(context); + sourceAction.registerCommands(this.languageClient, context); + refactorAction.registerCommands(this.languageClient, context); + pasteAction.registerCommands(this.languageClient, context); + + excludeProjectSettingsFiles(); + + context.subscriptions.push(languages.registerCodeActionsProvider({ scheme: 'file', language: 'java' }, new RefactorDocumentProvider(), RefactorDocumentProvider.metadata)); + context.subscriptions.push(commands.registerCommand(Commands.LEARN_MORE_ABOUT_REFACTORING, async (kind: CodeActionKind) => { + const sectionId: string = javaRefactorKinds.get(kind) || ''; + markdownPreviewProvider.show(context.asAbsolutePath(path.join('document', `${Commands.LEARN_MORE_ABOUT_REFACTORING}.md`)), 'Java Refactoring', sectionId, context); + })); + + context.subscriptions.push(commands.registerCommand(Commands.CREATE_MODULE_INFO_COMMAND, async () => { + const uri = await askForProjects( + window.activeTextEditor?.document.uri, + "Please select the project to create module-info.java", + false, + ); + if (!uri?.length) { + return; + } + + const moduleInfoUri: string = await commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.CREATE_MODULE_INFO, + uri[0].toString(), + ); + + if (moduleInfoUri) { + await window.showTextDocument(Uri.parse(moduleInfoUri)); + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.UPGRADE_GRADLE_WRAPPER_CMD, (projectUri: string, version?: string) => { + upgradeGradle(projectUri, version); + })); + + languages.registerCodeActionsProvider({ + language: "xml", + scheme: "file", + pattern: "**/pom.xml" + }, new PomCodeActionProvider(context), pomCodeActionMetadata); + + languages.registerCodeActionsProvider({ + scheme: "file", + pattern: "**/{gradle/wrapper/gradle-wrapper.properties,build.gradle,build.gradle.kts,settings.gradle,settings.gradle.kts}" + }, new GradleCodeActionProvider(), gradleCodeActionMetadata); + + languages.registerCodeActionsProvider({ + scheme: 'file', + language: 'java' + }, new ClientCodeActionProvider(context)); + } + + private showGradleCompatibilityIssueNotification(message: string, options: string[], projectUri: string, gradleVersion: string, newJavaHome: string) { + window.showErrorMessage(`${message} [Learn More](https://docs.gradle.org/current/userguide/compatibility.html)`, ...options).then(async (choice) => { + if (choice === GET_JDK) { + commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse(getJdkUrl())); + } else if (choice.startsWith(USE_JAVA)) { + await workspace.getConfiguration().update(GRADLE_IMPORT_JVM, newJavaHome, ConfigurationTarget.Global); + commands.executeCommand("workbench.action.openSettings", GRADLE_IMPORT_JVM); + commands.executeCommand(Commands.IMPORT_PROJECTS_CMD); + } else if (choice.startsWith(UPGRADE_GRADLE)) { + await upgradeGradle(projectUri, gradleVersion); + } + }); + } + + private registerCommandsForStandardServer(context: ExtensionContext, jdtEventEmitter: EventEmitter): void { + context.subscriptions.push(commands.registerCommand(Commands.IMPORT_PROJECTS_CMD, async () => { + if (getJavaConfiguration().get("import.projectSelection") === "automatic") { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.IMPORT_PROJECTS); + } + const projectUris: string[] = await getAllProjects(true /* excludeDefaultProject */); + const buildFileSelector = new BuildFileSelector(context, projectUris, false); + const selectedBuildFiles = await buildFileSelector.selectBuildFiles(); + if (selectedBuildFiles === undefined) { + return; // cancelled by user + } + const importedFolders = projectUris.map(uri => Uri.parse(uri).fsPath); + const allFoundBuildFiles = buildFileSelector.getAllFoundBuildFiles(); + const foldersContainingBuildFiles = allFoundBuildFiles.map(uri => path.dirname(uri.fsPath)); + + const filesToImport = new Set(); + const folderToUpdate = new Set(); + selectedBuildFiles.forEach(buildFile => { + const folder = path.dirname(Uri.parse(buildFile).fsPath); + if (importedFolders.some(importedFolder => path.relative(importedFolder, folder) === "")) { + // update the project if the folder of the build file is already imported + folderToUpdate.add(Uri.file(folder).toString()); + } else { + filesToImport.add(buildFile); + } + }); + + const folderToRemove = new Set(); + foldersContainingBuildFiles.forEach(folder => { + // for those unselected folders, if the folder is imported, delete the project. + const isSelected = selectedBuildFiles.some(buildFile => path.relative(path.dirname(Uri.parse(buildFile).fsPath), folder) === ""); + const isFolderImported = importedFolders.some(importedFolder => path.relative(importedFolder, folder) === ""); + + if (!isSelected && isFolderImported) { + folderToRemove.add(Uri.file(folder).toString()); + } + }); + + if (filesToImport.size > 0 || folderToUpdate.size > 0 || folderToRemove.size > 0) { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.CHANGE_IMPORTED_PROJECTS, + Array.from(filesToImport), Array.from(folderToUpdate), Array.from(folderToRemove)); + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.OPEN_OUTPUT, () => this.languageClient.outputChannel.show(ViewColumn.Three))); + context.subscriptions.push(commands.registerCommand(Commands.SHOW_SERVER_TASK_STATUS, (preserveFocus?: boolean) => serverTaskPresenter.presentServerTaskView(preserveFocus))); + } + + public start(): Promise { + if (this.languageClient && this.status === ClientStatus.initialized) { + this.status = ClientStatus.starting; + return this.languageClient.start(); + } + } + + public stop(): Promise { + this.status = ClientStatus.stopping; + if (this.languageClient) { + try { + return this.languageClient.stop(); + } finally { + this.languageClient = null; + } + } + return Promise.resolve(); + } + + public getClient(): LanguageClient { + return this.languageClient; + } + + public getClientStatus(): ClientStatus { + return this.status; + } + + private async handleSourceInvalidatedEvent(jars: string[], isAutoDownloadSource: boolean, jdtContentProviderEventEmitter: EventEmitter): Promise { + const changedJarNames: Set = new Set(); + for (const jar of jars) { + const path = jar.split(/\/|\\/); + if (path?.length) { + changedJarNames.add(path[path.length - 1]); + } + } + + const affectedDocumentUris: Uri[] = []; + const affectedDocumentNames: string[] = []; + workspace.textDocuments.forEach(document => { + // Here is a sample jdt uri for classfile: + // jdt://contents/rt.jar/java.lang/System.class?... + if (document.uri.scheme === "jdt") { + const paths = document.uri.path?.split(/\/|\\/); + if (paths?.[1] && changedJarNames.has(paths[1])) { + affectedDocumentNames.push(paths[paths.length - 1]); + affectedDocumentUris.push(document.uri); + } + } + }); + if (affectedDocumentUris.length) { + if (isAutoDownloadSource) { + const reloadSources = workspace.getConfiguration().get("java.editor.reloadChangedSources"); + if (reloadSources === "manual") { + return; + } + + if (reloadSources === "ask") { + const choice = await window.showWarningMessage(`The following class(es): ${affectedDocumentNames.map(name => `'${name}'`).join(", ")} ` + + "have new source jar available on the local Maven repository. Do you want to reload them?", "Yes", "Always", "No"); + if (choice === "Always") { + workspace.getConfiguration().update("java.editor.reloadChangedSources", "auto", ConfigurationTarget.Global); + } else if (choice !== "Yes") { + return; + } + } + } + affectedDocumentUris.forEach(classFileUri => { + jdtContentProviderEventEmitter.fire(classFileUri); + }); + } + apiManager.fireSourceInvalidatedEvent({ + affectedRootPaths: jars, + affectedEditorDocuments: affectedDocumentUris, + }); + } +} + +async function showImportFinishNotification(context: ExtensionContext) { + const neverShow: boolean | undefined = context.globalState.get("java.neverShowImportFinishNotification"); + if (!neverShow) { + let choice: string | undefined; + const options = ["Don't show again"]; + if (serverStatus.hasErrors()) { + options.unshift("Show errors"); + choice = await window.showWarningMessage("Errors occurred during import of Java projects.", ...options); + } else { + const projectUris: string[] = await getAllJavaProjects(); + if (projectUris.length === 0) { + return; + } + + if (extensions.getExtension("vscjava.vscode-java-dependency")) { + options.unshift("View projects"); + } + + choice = await window.showInformationMessage("Projects are imported into workspace.", ...options); + } + + if (choice === "Don't show again") { + context.globalState.update("java.neverShowImportFinishNotification", true); + } else if (choice === "View projects") { + commands.executeCommand("javaProjectExplorer.focus"); + } else if (choice === "Show errors") { + commands.executeCommand("workbench.panel.markers.view.focus"); + } + } +} + +function logNotification(message: string) { + return new Promise(() => { + logger.verbose(message); + }); +} + +function setIncompleteClasspathSeverity(severity: string) { + const config = getJavaConfiguration(); + const section = 'errors.incompleteClasspath.severity'; + config.update(section, severity, true).then( + () => logger.info(`${section} globally set to ${severity}`), + (error) => logger.error(error) + ); +} + +async function setProjectConfigurationUpdate(languageClient: LanguageClient, uri: Uri, status: FeatureStatus) { + const config = getJavaConfiguration(); + const section = 'configuration.updateBuildConfiguration'; + + const st = FeatureStatus[status]; + config.update(section, st).then( + () => logger.info(`${section} set to ${st}`), + (error) => logger.error(error) + ); + if (status !== FeatureStatus.disabled) { + await projectConfigurationUpdate(languageClient, uri); + } +} + +function setNullAnalysisStatus(status: FeatureStatus) { + const config = getJavaConfiguration(); + const section = 'compile.nullAnalysis.mode'; + + const st = FeatureStatus[status]; + config.update(section, st).then( + () => logger.info(`${section} set to ${st}`), + (error) => logger.error(error) + ); +} + +function decodeBase64(text: string): string { + return Buffer.from(text, 'base64').toString('ascii'); +} + +export function showNoLocationFound(message: string): void { + commands.executeCommand( + Commands.GOTO_LOCATION, + window.activeTextEditor.document.uri, + window.activeTextEditor.selection.active, + [], + 'goto', + message + ); +} + +export async function applyWorkspaceEdit(workspaceEdit: WorkspaceEdit, languageClient: LanguageClient): Promise { + const codeEdit = await languageClient.protocol2CodeConverter.asWorkspaceEdit(workspaceEdit); + if (codeEdit) { + return await workspace.applyEdit(codeEdit); + } else { + return Promise.resolve(true); + } +} + +/** + * 'workspace/willRenameFiles' already handled so we need to disable it. + * @see fileEventHandler.registerFileEventHandlers + */ +export class DisableWillRenameFeature implements StaticFeature { + fillClientCapabilities(capabilities: ClientCapabilities): void { + capabilities.workspace.fileOperations.willRename = false; + } + getState(): FeatureState { + return null; + } + clear(): void {} + fillInitializeParams?: () => void; + preInitialize?: () => void; + initialize(): void {} +} diff --git a/src/standardLanguageClientUtils.ts b/src/standardLanguageClientUtils.ts new file mode 100644 index 0000000000..6b8723e699 --- /dev/null +++ b/src/standardLanguageClientUtils.ts @@ -0,0 +1,151 @@ +'use strict'; + +import { commands, ConfigurationTarget, Position, ProgressLocation, QuickPickItem, Range, Uri, window, workspace } from "vscode"; +import * as path from "path"; +import * as fse from "fs-extra"; +import { TextDocumentIdentifier } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { buildFilePatterns } from "./plugin"; +import { ProjectConfigurationUpdateRequest } from "./protocol"; +import { Commands } from "./commands"; +import { getAllJavaProjects } from "./utils"; + +export async function projectConfigurationUpdate(languageClient: LanguageClient, uris?: TextDocumentIdentifier | Uri | Uri[]) { + let resources = []; + if (!uris) { + const activeFileUri: Uri | undefined = window.activeTextEditor?.document.uri; + + if (activeFileUri && isJavaConfigFile(activeFileUri.fsPath)) { + resources = [activeFileUri]; + } else { + resources = await askForProjects(activeFileUri, "Please select the project(s) to update."); + } + } else if (uris instanceof Uri) { + resources.push(uris); + } else if (Array.isArray(uris)) { + for (const uri of uris) { + if (uri instanceof Uri) { + resources.push(uri); + } + } + } else if ("uri" in uris) { + resources.push(Uri.parse(uris.uri)); + } + + if (resources.length === 1) { + await languageClient.sendNotification(ProjectConfigurationUpdateRequest.type, { + uri: resources[0].toString(), + }); + } else if (resources.length > 1) { + await languageClient.sendNotification(ProjectConfigurationUpdateRequest.typeV2, { + identifiers: resources.map(r => { + return { uri: r.toString() }; + }), + }); + } +} + +function isJavaConfigFile(filePath: string) { + const fileName = path.basename(filePath); + const regEx = new RegExp(buildFilePatterns.map(r => `(${r})`).join('|'), 'i'); + return regEx.test(fileName); +} + +/** + * Ask user to select projects and return the selected projects' uris. + * @param activeFileUri the uri of the active file. + * @param placeHolder message to be shown in quick pick. + */ +export async function askForProjects(activeFileUri: Uri | undefined, placeHolder: string, canPickMany: boolean = true): Promise { + const projectPicks: QuickPickItem[] = await generateProjectPicks(activeFileUri); + if (!projectPicks?.length) { + return []; + } else if (projectPicks.length === 1) { + return [Uri.file(projectPicks[0].detail)]; + } + + const choices: QuickPickItem[] | QuickPickItem | undefined = await window.showQuickPick(projectPicks, { + matchOnDetail: true, + placeHolder: placeHolder, + ignoreFocusOut: true, + canPickMany: canPickMany, + }); + + if (!choices) { + return []; + } + + if (Array.isArray(choices)) { + return choices.map(c => Uri.file(c.detail)); + } + + return [Uri.file(choices.detail)]; +} + +/** + * Generate the quick picks for projects selection. An `undefined` value will be return if + * it's failed to generate picks. + * @param activeFileUri the uri of the active document. + */ +async function generateProjectPicks(activeFileUri: Uri | undefined): Promise { + let projectUriStrings: string[]; + try { + projectUriStrings = await getAllJavaProjects(); + } catch (e) { + return undefined; + } + + const projectPicks: QuickPickItem[] = projectUriStrings.map(uriString => { + const projectPath = Uri.parse(uriString).fsPath; + return { + label: path.basename(projectPath), + detail: projectPath, + }; + }).filter(Boolean); + + // pre-select an active project based on the uri candidate. + if (activeFileUri?.scheme === "file") { + const candidatePath = activeFileUri.fsPath; + let belongingIndex = -1; + for (let i = 0; i < projectPicks.length; i++) { + if (candidatePath.startsWith(projectPicks[i].detail)) { + if (belongingIndex < 0 + || projectPicks[i].detail.length > projectPicks[belongingIndex].detail.length) { + belongingIndex = i; + } + } + } + if (belongingIndex >= 0) { + projectPicks[belongingIndex].picked = true; + } + } + + return projectPicks; +} + +export async function upgradeGradle(projectUri: string, version?: string): Promise { + const useWrapper = workspace.getConfiguration().get("java.import.gradle.wrapper.enabled"); + if (!useWrapper) { + await workspace.getConfiguration().update("java.import.gradle.wrapper.enabled", true, ConfigurationTarget.Workspace); + } + const result = await window.withProgress({ + location: ProgressLocation.Notification, + title: "Upgrading Gradle wrapper...", + cancellable: true, + }, (_progress, token) => { + return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.UPGRADE_GRADLE_WRAPPER, projectUri, version, token); + }); + if (result) { + if (await fse.pathExists(result)) { + const content = await fse.readFile(result); + const offset = content.toString().indexOf("distributionUrl"); + if (offset >= 0) { + const document = await workspace.openTextDocument(result); + const position = document.positionAt(offset); + const distributionUrlRange = document.getWordRangeAtPosition(position); + window.showTextDocument(document, {selection: new Range(distributionUrlRange.start, new Position(distributionUrlRange.start.line + 1, 0))}); + } + } + commands.executeCommand(Commands.IMPORT_PROJECTS_CMD); + } +} diff --git a/src/syntaxLanguageClient.ts b/src/syntaxLanguageClient.ts new file mode 100644 index 0000000000..92f7d42fa0 --- /dev/null +++ b/src/syntaxLanguageClient.ts @@ -0,0 +1,127 @@ +'use strict'; + +import * as net from "net"; +import { DidChangeConfigurationNotification, LanguageClientOptions } from "vscode-languageclient"; +import { LanguageClient, ServerOptions, StreamInfo } from "vscode-languageclient/node"; +import { apiManager } from "./apiManager"; +import { ClientErrorHandler } from "./clientErrorHandler"; +import { ClientStatus } from "./extension.api"; +import { logger } from "./log"; +import { OutputInfoCollector } from "./outputInfoCollector"; +import { ExecuteClientCommandRequest, StatusNotification } from "./protocol"; +import { RequirementsData } from "./requirements"; +import { ServerMode } from "./settings"; +import { snippetCompletionProvider } from "./snippetCompletionProvider"; +import { getJavaConfig } from "./utils"; +import { DEBUG } from "./javaServerStarter"; +import { TracingLanguageClient } from "./TracingLanguageClient"; +import { commands } from "vscode"; + +const extensionName = "Language Support for Java (Syntax Server)"; + +export class SyntaxLanguageClient { + private languageClient: LanguageClient; + private status: ClientStatus = ClientStatus.uninitialized; + + public initialize(requirements: RequirementsData, clientOptions: LanguageClientOptions, serverOptions?: ServerOptions) { + const newClientOptions: LanguageClientOptions = Object.assign({}, clientOptions, { + middleware: { + workspace: { + didChangeConfiguration: async () => { + await this.languageClient.sendNotification(DidChangeConfigurationNotification.type, { + settings: { + java: await getJavaConfig(requirements.java_home), + } + }); + } + } + }, + errorHandler: new ClientErrorHandler(extensionName), + initializationFailedHandler: error => { + logger.error(`Failed to initialize ${extensionName} due to ${error && error.toString()}`); + if (error.toString().includes('Connection') && error.toString().includes('disposed')) { + return false; + } else { + return true; + } + }, + outputChannel: new OutputInfoCollector(extensionName), + outputChannelName: extensionName + }); + + const lsPort = process.env['SYNTAXLS_CLIENT_PORT']; + if (!serverOptions && lsPort) { + serverOptions = () => { + const socket = net.connect(lsPort); + const result: StreamInfo = { + writer: socket, + reader: socket + }; + return Promise.resolve(result); + }; + } + + if (serverOptions) { + this.languageClient = new TracingLanguageClient('java', extensionName, serverOptions, newClientOptions, DEBUG); + } + + this.status = ClientStatus.initialized; + } + + public registerSyntaxClientActions(serverOptions?: ServerOptions): void { + // TODO: Currently only resolve the promise when the server mode is explicitly set to lightweight. + // This is to avoid breakings + if (serverOptions) { + this.languageClient.onNotification(StatusNotification.type, (report) => { + switch (report.type) { + case 'Started': + this.status = ClientStatus.started; + apiManager.updateStatus(ClientStatus.started); + // Disable the client-side snippet provider since LS is ready. + snippetCompletionProvider.dispose(); + break; + case 'Error': + this.status = ClientStatus.error; + apiManager.updateStatus(ClientStatus.error); + break; + default: + break; + } + if (apiManager.getApiInstance().serverMode === ServerMode.lightWeight) { + apiManager.fireDidServerModeChange(ServerMode.lightWeight); + } + }); + this.languageClient.onRequest(ExecuteClientCommandRequest.type, (params) => { + return commands.executeCommand(params.command, ...params.arguments); + }); + } + } + + public start(): Promise { + if (this.languageClient) { + this.status = ClientStatus.starting; + return this.languageClient.start(); + } + } + + public stop(): Promise { + this.status = ClientStatus.stopping; + if (this.languageClient) { + try { + return this.languageClient.stop(); + } finally { + this.languageClient = null; + } + } + return Promise.resolve(); + } + + public isAlive(): boolean { + return !!this.languageClient && this.status !== ClientStatus.stopping; + } + + public getClient(): LanguageClient { + return this.languageClient; + } + +} diff --git a/src/telemetry.ts b/src/telemetry.ts new file mode 100644 index 0000000000..35f702603a --- /dev/null +++ b/src/telemetry.ts @@ -0,0 +1,63 @@ +import { TelemetryService, getRedHatService } from "@redhat-developer/vscode-redhat-telemetry"; +import { ExtensionContext, workspace, WorkspaceConfiguration } from "vscode"; +import { cyrb53 } from "./utils"; + +/** + * Wrap vscode-redhat-telemetry to suit vscode-java + */ +export namespace Telemetry { + + export const STARTUP_EVT = "startup"; + export const COMPLETION_EVENT = "textCompletion"; + export const SERVER_INITIALIZED_EVT = "java.workspace.initialized"; + export const LS_ERROR = "java.ls.error"; + + let telemetryManager: TelemetryService = null; + let workspaceHash; + + /** + * Starts the telemetry service + * + * @returns when the telemetry service has been started + * @throws Error if the telemetry service has already been started + */ + export async function startTelemetry(context: ExtensionContext): Promise { + if (!!telemetryManager) { + throw new Error("The telemetry service for vscode-java has already been started"); + } + workspaceHash = computeWorkspaceHash(); + workspace.onDidChangeWorkspaceFolders(() => { + workspaceHash = computeWorkspaceHash(); + }); + const redhatService = await getRedHatService(context); + const telemService = await redhatService.getTelemetryService(); + telemetryManager = telemService; + return telemService; + } + + function computeWorkspaceHash(): number { + if (!workspace.workspaceFolders?.length) { + return 0; + } + return cyrb53(workspace.workspaceFolders.map(f => f.uri.toString()).join('|')); + } + + /** + * Send a telemetry event with the given name and data + * + * @param eventName the name of the telemetry event + * @param data the telemetry data + * @throws Error if the telemetry service has not been started yet + */ + export async function sendTelemetry(eventName: string, data?: object): Promise { + if (!telemetryManager) { + throw new Error("The telemetry service for vscode-java has not been started yet"); + } + + const event = { + name: eventName, + properties: { workspaceHash, ...data} + }; + return telemetryManager.send(event); + } +} diff --git a/src/themeUtils.ts b/src/themeUtils.ts new file mode 100644 index 0000000000..a4634e7eb8 --- /dev/null +++ b/src/themeUtils.ts @@ -0,0 +1,20 @@ +import { SymbolKind as VSymbolKind, ThemeIcon } from "vscode"; +import { SymbolKind as LSymbolKind} from "vscode-languageclient"; + +const themeIconIds = [ + 'symbol-file', 'symbol-module', 'symbol-namespace', 'symbol-package', 'symbol-class', 'symbol-method', + 'symbol-property', 'symbol-field', 'symbol-constructor', 'symbol-enum', 'symbol-interface', + 'symbol-function', 'symbol-variable', 'symbol-constant', 'symbol-string', 'symbol-number', 'symbol-boolean', + 'symbol-array', 'symbol-object', 'symbol-key', 'symbol-null', 'symbol-enum-member', 'symbol-struct', + 'symbol-event', 'symbol-operator', 'symbol-type-parameter' +]; + +export function getLThemeIcon(kind: LSymbolKind): ThemeIcon | undefined { + const id = themeIconIds[kind - 1]; + return id ? new ThemeIcon(id) : undefined; +} + +export function getThemeIcon(kind: VSymbolKind): ThemeIcon | undefined { + const id = themeIconIds[kind]; + return id ? new ThemeIcon(id) : undefined; +} \ No newline at end of file diff --git a/src/typeHierarchy/model.ts b/src/typeHierarchy/model.ts new file mode 100644 index 0000000000..2be7037979 --- /dev/null +++ b/src/typeHierarchy/model.ts @@ -0,0 +1,252 @@ +import * as vscode from "vscode"; +import { TypeHierarchyDirection, TypeHierarchyItem } from "./protocol"; +import { SymbolItemNavigation, SymbolTreeInput, SymbolTreeModel } from "./references-view"; +import { getActiveLanguageClient } from "../extension"; +import { LanguageClient } from "vscode-languageclient/node"; +import { getRootItem, resolveTypeHierarchy, typeHierarchyDirectionToContextString } from "./util"; +import { CancellationToken, commands, workspace } from "vscode"; +import { getThemeIcon } from "../themeUtils"; + +export class TypeHierarchyTreeInput implements SymbolTreeInput { + readonly contextValue: string = "javaTypeHierarchy"; + readonly title: string; + readonly baseItem: TypeHierarchyItem; + private client: LanguageClient; + private rootItem: TypeHierarchyItem; + + constructor(readonly location: vscode.Location, readonly direction: TypeHierarchyDirection, readonly token: CancellationToken, item: TypeHierarchyItem) { + this.baseItem = item; + const isMethodHierarchy: boolean = item.data["method"] !== undefined; + let methodName: string; + if (isMethodHierarchy) { + methodName = item.data["method_name"]; + } + switch (direction) { + case TypeHierarchyDirection.both: + this.title = isMethodHierarchy ? `Method Hierarchy for ${methodName}` : "Class Hierarchy"; + break; + case TypeHierarchyDirection.parents: + this.title = isMethodHierarchy ? `Supertype (Method) Hierarchy for ${methodName}` : "Supertype Hierarchy"; + break; + case TypeHierarchyDirection.children: + this.title = isMethodHierarchy ? `Subtype (Method) Hierarchy for ${methodName}` : "Subtype Hierarchy"; + break; + default: + return; + } + + } + + async resolve(): Promise> { + if (!this.client) { + this.client = await getActiveLanguageClient(); + } + // workaround: await a second to make sure the success of reveal operation on baseItem, see: https://github.com/microsoft/vscode/issues/114989 + await new Promise((resolve) => setTimeout(() => { + resolve(); + }, 1000)); + + this.rootItem = (this.direction === TypeHierarchyDirection.both) ? await getRootItem(this.client, this.baseItem, this.token) : this.baseItem; + const model: TypeHierarchyModel = new TypeHierarchyModel(this.rootItem, this.direction, this.baseItem); + const provider = new TypeHierarchyTreeDataProvider(model, this.client, this.token); + const treeModel: SymbolTreeModel = { + provider: provider, + message: undefined, + navigation: model, + dispose() { + provider.dispose(); + } + }; + commands.executeCommand('setContext', 'typeHierarchyDirection', typeHierarchyDirectionToContextString(this.direction)); + commands.executeCommand('setContext', 'typeHierarchySymbolKind', this.baseItem.kind); + return treeModel; + } + + with(location: vscode.Location): TypeHierarchyTreeInput { + return new TypeHierarchyTreeInput(location, this.direction, this.token, this.baseItem); + } +} + +export class TypeHierarchyModel implements SymbolItemNavigation { + public readonly onDidChange = new vscode.EventEmitter(); + public readonly onDidChangeEvent = this.onDidChange.event; + + constructor(private rootItem: TypeHierarchyItem, private direction: TypeHierarchyDirection, private baseItem: TypeHierarchyItem) { } + + public getBaseItem(): TypeHierarchyItem { + return this.baseItem; + } + + public getDirection(): TypeHierarchyDirection { + return this.direction; + } + + public getRootItem(): TypeHierarchyItem { + return this.rootItem; + } + + location(item: TypeHierarchyItem) { + return new vscode.Location(vscode.Uri.parse(item.uri), item.range); + } + + nearest(uri: vscode.Uri, _position: vscode.Position): TypeHierarchyItem | undefined { + return this.baseItem; + } + + next(from: TypeHierarchyItem): TypeHierarchyItem { + return from; + } + + previous(from: TypeHierarchyItem): TypeHierarchyItem { + return from; + } +} + +class TypeHierarchyTreeDataProvider implements vscode.TreeDataProvider { + private readonly emitter: vscode.EventEmitter = new vscode.EventEmitter(); + private readonly modelListener: vscode.Disposable; + private lazyLoad: boolean; + public readonly onDidChangeTreeData: vscode.Event = this.emitter.event; + + constructor(readonly model: TypeHierarchyModel, readonly client: LanguageClient, readonly token: CancellationToken) { + this.modelListener = model.onDidChangeEvent(e => this.emitter.fire(e instanceof TypeHierarchyItem ? e : undefined)); + this.lazyLoad = workspace.getConfiguration().get("java.typeHierarchy.lazyLoad"); + } + + dispose(): void { + this.emitter.dispose(); + this.modelListener.dispose(); + } + + async getTreeItem(element: TypeHierarchyItem): Promise { + if (!element) { + return undefined; + } + const treeItem: vscode.TreeItem = (element === this.model.getBaseItem()) ? new vscode.TreeItem({ label: element.name, highlights: [[0, element.name.length]] }) : new vscode.TreeItem(element.name); + treeItem.contextValue = (element === this.model.getBaseItem() || !element.uri) ? "false" : "true"; + treeItem.description = element.detail; + treeItem.iconPath = getThemeIcon(element.kind); + treeItem.command = (element.uri) ? { + command: 'vscode.open', + title: 'Open Type Definition Location', + arguments: [ + vscode.Uri.parse(element.uri), { selection: element.selectionRange } + ] + } : undefined; + // workaround: set a specific id to refresh the collapsible state for treeItems, see: https://github.com/microsoft/vscode/issues/114614#issuecomment-763428052 + treeItem.id = `${element.data["element"]}${Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)}`; + if (element.expand) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; + } else if (this.model.getDirection() === TypeHierarchyDirection.children || this.model.getDirection() === TypeHierarchyDirection.both) { + // For an unresolved baseItem, will make it collapsed to show it early. It will be automatically expanded by model.nearest() + if (element === this.model.getBaseItem()) { + if (!element.children) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + } else if (element.children.length === 0) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.None; + } else { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; + } + } else { + if (!element.children) { + if (this.lazyLoad) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + return treeItem; + } + const resolvedItem = await resolveTypeHierarchy(this.client, element, this.model.getDirection(), this.token); + if (!resolvedItem) { + return undefined; + } + element.children = resolvedItem.children; + } + treeItem.collapsibleState = (element.children.length === 0) ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; + } + } else if (this.model.getDirection() === TypeHierarchyDirection.parents) { + if (element === this.model.getBaseItem()) { + if (!element.parents) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + } else if (element.parents.length === 0) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.None; + } else { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; + } + } else { + if (!element.parents) { + if (this.lazyLoad) { + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + return treeItem; + } + const resolvedItem = await resolveTypeHierarchy(this.client, element, this.model.getDirection(), this.token); + if (!resolvedItem) { + return undefined; + } + element.parents = resolvedItem.parents; + } + treeItem.collapsibleState = (element.parents.length === 0) ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; + } + } + return treeItem; + } + + async getChildren(element?: TypeHierarchyItem | undefined): Promise { + if (!element) { + return [this.model.getRootItem()]; + } + if (this.model.getDirection() === TypeHierarchyDirection.children || this.model.getDirection() === TypeHierarchyDirection.both) { + if (!element.children) { + if (TypeHierarchyTreeDataProvider.isAllowedType(element)) { + return [TypeHierarchyTreeDataProvider.getFakeItem(element)]; + } + const resolvedItem = await resolveTypeHierarchy(this.client, element, this.model.getDirection(), this.token); + if (!resolvedItem) { + return undefined; + } + element.children = resolvedItem.children; + if (element.children.length === 0) { + this.emitter.fire(element); + } + } + return element.children; + } else if (this.model.getDirection() === TypeHierarchyDirection.parents) { + if (!element.parents) { + const resolvedItem = await resolveTypeHierarchy(this.client, element, this.model.getDirection(), this.token); + if (!resolvedItem) { + return undefined; + } + element.parents = resolvedItem.parents; + if (element.parents.length === 0) { + this.emitter.fire(element); + } + } + return element.parents; + } + return undefined; + } + + private static isAllowedType(item: TypeHierarchyItem): boolean { + if (item.name === "Object" && item.detail === "java.lang") { + return true; + } + return false; + } + + private static getFakeItem(item: TypeHierarchyItem): TypeHierarchyItem { + let message: string; + if (item.name === "Object" && item.detail === "java.lang") { + message = "All classes are subtypes of java.lang.Object."; + } + return { + name: message, + kind: undefined, + children: [], + parents: [], + detail: undefined, + uri: undefined, + range: undefined, + selectionRange: undefined, + data: undefined, + deprecated: false, + expand: false, + }; + } +} diff --git a/src/typeHierarchy/protocol.ts b/src/typeHierarchy/protocol.ts new file mode 100644 index 0000000000..de46211472 --- /dev/null +++ b/src/typeHierarchy/protocol.ts @@ -0,0 +1,35 @@ +import * as vscode from "vscode"; +import { Range, SymbolKind } from "vscode-languageclient"; + +export enum TypeHierarchyDirection { + children, + parents, + both +} + +export class LSPTypeHierarchyItem { + name: string; + detail: string; + kind: SymbolKind; + deprecated: boolean; + uri: string; + range: Range; + selectionRange: Range; + parents: LSPTypeHierarchyItem[]; + children: LSPTypeHierarchyItem[]; + data: any; +} + +export class TypeHierarchyItem { + name: string; + detail: string; + kind: vscode.SymbolKind; + deprecated: boolean; + uri: string; + range: vscode.Range; + selectionRange: vscode.Range; + parents: TypeHierarchyItem[]; + children: TypeHierarchyItem[]; + data: any; + expand: boolean; +} diff --git a/src/typeHierarchy/references-view.d.ts b/src/typeHierarchy/references-view.d.ts new file mode 100644 index 0000000000..e61177b903 --- /dev/null +++ b/src/typeHierarchy/references-view.d.ts @@ -0,0 +1,139 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +/** + * This interface describes the shape for the references viewlet API. It consists + * of a single `setInput` function which must be called with a full implementation + * of the `SymbolTreeInput`-interface. To acquire this API use the default mechanics, e.g: + * + * ```ts + * // get references viewlet API + * const api = await vscode.extensions.getExtension('ms-vscode.references-view').activate(); + * + * // instantiate and set input which updates the view + * const myInput: SymbolTreeInput = ... + * api.setInput(myInput) + * ``` + */ +export interface SymbolTree { + + /** + * Set the contents of the references viewlet. + * + * @param input A symbol tree input object + */ + setInput(input: SymbolTreeInput): void; +} + +/** + * A symbol tree input is the entry point for populating the references viewlet. + * Inputs must be anchored at a code location, they must have a title, and they + * must resolve to a model. + */ +export interface SymbolTreeInput { + + /** + * The value of the `reference-list.source` context key. Use this to control + * input dependent commands. + */ + readonly contextValue: string; + + /** + * The (short) title of this input, like "Implementations" or "Callers Of" + */ + readonly title: string; + + /** + * The location at which this position is anchored. Locations are validated and inputs + * with "funny" locations might be ignored + */ + readonly location: vscode.Location; + + /** + * Resolve this input to a model that contains the actual data. When there are no result + * than `undefined` or `null` should be returned. + */ + resolve(): vscode.ProviderResult>; + + /** + * This function is called when re-running from history. The symbols tree has tracked + * the original location of this input and that is now passed to this input. The + * implementation of this function should return a clone where the `location`-property + * uses the provided `location` + * + * @param location The location at which the new input should be anchored. + * @returns A new input which location is anchored at the position. + */ + with(location: vscode.Location): SymbolTreeInput; +} + +/** + * A symbol tree model which is used to populate the symbols tree. + */ +export interface SymbolTreeModel { + + /** + * A tree data provider which is used to populate the symbols tree. + */ + provider: vscode.TreeDataProvider; + + /** + * An optional message that is displayed above the tree. Whenever the provider + * fires a change event this message is read again. + */ + message: string | undefined; + + /** + * Optional support for symbol navigation. When implemented, navigation commands like + * "Go to Next" and "Go to Previous" will be working with this model. + */ + navigation?: SymbolItemNavigation; + + /** + * Optional support for editor highlights. WHen implemented, the editor will highlight + * symbol ranges in the source code. + */ + highlights?: SymbolItemEditorHighlights; + + /** + * Optional dispose function which is invoked when this model is + * needed anymore + */ + dispose?(): void; +} + +/** + * Interface to support the built-in symbol navigation. + */ +export interface SymbolItemNavigation { + /** + * Return the item that is the nearest to the given location or `undefined` + */ + nearest(uri: vscode.Uri, position: vscode.Position): T | undefined; + /** + * Return the next item from the given item or the item itself. + */ + next(from: T): T; + /** + * Return the previous item from the given item or the item itself. + */ + previous(from: T): T; + /** + * Return the location of the given item. + */ + location(item: T): vscode.Location | undefined; +} + +/** + * Interface to support the built-in editor highlights. + */ +export interface SymbolItemEditorHighlights { + /** + * Given an item and an uri return an array of ranges to highlight. + */ + getEditorHighlights(item: T, uri: vscode.Uri): vscode.Range[] | undefined; +} diff --git a/src/typeHierarchy/typeHierarchyTree.ts b/src/typeHierarchy/typeHierarchyTree.ts new file mode 100644 index 0000000000..d2870de6b4 --- /dev/null +++ b/src/typeHierarchy/typeHierarchyTree.ts @@ -0,0 +1,118 @@ +import * as vscode from "vscode"; +import { Position, TextDocumentIdentifier, TextDocumentPositionParams } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { Commands } from "../commands"; +import { getActiveLanguageClient } from "../extension"; +import { showNoLocationFound } from "../standardLanguageClient"; +import { TypeHierarchyTreeInput } from "./model"; +import { LSPTypeHierarchyItem, TypeHierarchyDirection, TypeHierarchyItem } from "./protocol"; +import { SymbolTree } from "./references-view"; +import { toTypeHierarchyItem } from "./util"; + +export class TypeHierarchyTree { + private api: SymbolTree; + private direction: TypeHierarchyDirection; + private client: LanguageClient; + private cancelTokenSource: vscode.CancellationTokenSource; + private location: vscode.Location; + private baseItem: TypeHierarchyItem; + public initialized: boolean; + + constructor() { + this.initialized = false; + } + + public async initialize() { + // It uses a new publisher id in June 2022 Update, check both old/new id for compatibility + // See https://github.com/microsoft/vscode/pull/152213 + const referencesViewExt = vscode.extensions.getExtension('vscode.references-view') + ?? vscode.extensions.getExtension('ms-vscode.references-view'); + this.api = await referencesViewExt?.activate(); + this.client = await getActiveLanguageClient(); + this.initialized = true; + } + + public async setTypeHierarchy(location: vscode.Location, direction: TypeHierarchyDirection): Promise { + if (!this.initialized) { + await this.initialize(); + } + if (!this.api) { + return; + } + if (this.cancelTokenSource) { + this.cancelTokenSource.cancel(); + } + this.cancelTokenSource = new vscode.CancellationTokenSource(); + const textDocument: TextDocumentIdentifier = TextDocumentIdentifier.create(location.uri.toString()); + const position: Position = Position.create(location.range.start.line, location.range.start.character); + const params: TextDocumentPositionParams = { + textDocument: textDocument, + position: position, + }; + let lspItem: LSPTypeHierarchyItem; + try { + lspItem = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.OPEN_TYPE_HIERARCHY, JSON.stringify(params), JSON.stringify(direction), JSON.stringify(0), this.cancelTokenSource.token); + } catch (e) { + // operation cancelled + return; + } + if (!lspItem) { + showNoLocationFound('No Type Hierarchy found'); + return; + } + const symbolKind = this.client.protocol2CodeConverter.asSymbolKind(lspItem.kind); + if (direction === TypeHierarchyDirection.both && symbolKind === vscode.SymbolKind.Interface) { + direction = TypeHierarchyDirection.children; + } + const item: TypeHierarchyItem = toTypeHierarchyItem(this.client, lspItem, direction); + const input: TypeHierarchyTreeInput = new TypeHierarchyTreeInput(location, direction, this.cancelTokenSource.token, item); + this.location = location; + this.direction = direction; + this.baseItem = item; + this.api.setInput(input); + } + + public changeDirection(direction: TypeHierarchyDirection): void { + if (!this.api) { + return; + } + if (this.cancelTokenSource) { + this.cancelTokenSource.cancel(); + } + this.cancelTokenSource = new vscode.CancellationTokenSource(); + this.baseItem.children = undefined; + this.baseItem.parents = undefined; + const input: TypeHierarchyTreeInput = new TypeHierarchyTreeInput(this.location, direction, this.cancelTokenSource.token, this.baseItem); + this.direction = direction; + this.api.setInput(input); + } + + public async changeBaseItem(item: TypeHierarchyItem): Promise { + if (!this.api) { + return; + } + if (this.cancelTokenSource) { + this.cancelTokenSource.cancel(); + } + this.cancelTokenSource = new vscode.CancellationTokenSource(); + item.parents = undefined; + item.children = undefined; + const location: vscode.Location = new vscode.Location(vscode.Uri.parse(item.uri), item.selectionRange); + const newLocation: vscode.Location = (await this.isValidRequestPosition(location.uri, location.range.start)) ? location : this.location; + const input: TypeHierarchyTreeInput = new TypeHierarchyTreeInput(newLocation, this.direction, this.cancelTokenSource.token, item); + this.location = newLocation; + this.baseItem = item; + this.api.setInput(input); + } + + private async isValidRequestPosition(uri: vscode.Uri, position: vscode.Position) { + const doc = await vscode.workspace.openTextDocument(uri); + let range = doc.getWordRangeAtPosition(position); + if (!range) { + range = doc.getWordRangeAtPosition(position, /[^\s]+/); + } + return Boolean(range); + } +} + +export const typeHierarchyTree: TypeHierarchyTree = new TypeHierarchyTree(); diff --git a/src/typeHierarchy/util.ts b/src/typeHierarchy/util.ts new file mode 100644 index 0000000000..2f3463780b --- /dev/null +++ b/src/typeHierarchy/util.ts @@ -0,0 +1,121 @@ +import { CancellationToken, commands, SymbolKind } from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; +import { Commands } from "../commands"; +import { LSPTypeHierarchyItem, TypeHierarchyDirection, TypeHierarchyItem } from "./protocol"; + +export function toSingleLSPTypeHierarchyItem(client: LanguageClient, typeHierarchyItem: TypeHierarchyItem): LSPTypeHierarchyItem { + if (!typeHierarchyItem) { + return undefined; + } + return { + name: typeHierarchyItem.name, + detail: typeHierarchyItem.detail, + kind: client.code2ProtocolConverter.asSymbolKind(typeHierarchyItem.kind), + deprecated: typeHierarchyItem.deprecated, + uri: typeHierarchyItem.uri, + range: client.code2ProtocolConverter.asRange(typeHierarchyItem.range), + selectionRange: client.code2ProtocolConverter.asRange(typeHierarchyItem.selectionRange), + parents: undefined, + children: undefined, + data: typeHierarchyItem.data, + }; +} + +export function toTypeHierarchyItem(client: LanguageClient, lspTypeHierarchyItem: LSPTypeHierarchyItem, direction: TypeHierarchyDirection): TypeHierarchyItem { + if (!lspTypeHierarchyItem) { + return undefined; + } + let parents: TypeHierarchyItem[]; + let children: TypeHierarchyItem[]; + if (direction === TypeHierarchyDirection.parents || direction === TypeHierarchyDirection.both) { + if (lspTypeHierarchyItem.parents) { + parents = []; + for (const parent of lspTypeHierarchyItem.parents) { + parents.push(toTypeHierarchyItem(client, parent, TypeHierarchyDirection.parents)); + } + parents = parents.sort((a, b) => { + return (a.kind.toString() === b.kind.toString()) ? a.name.localeCompare(b.name) : b.kind.toString().localeCompare(a.kind.toString()); + }); + } + } + if (direction === TypeHierarchyDirection.children || direction === TypeHierarchyDirection.both) { + if (lspTypeHierarchyItem.children) { + children = []; + for (const child of lspTypeHierarchyItem.children) { + children.push(toTypeHierarchyItem(client, child, TypeHierarchyDirection.children)); + } + children = children.sort((a, b) => { + return (a.kind.toString() === b.kind.toString()) ? a.name.localeCompare(b.name) : b.kind.toString().localeCompare(a.kind.toString()); + }); + } + } + return { + name: lspTypeHierarchyItem.name, + detail: lspTypeHierarchyItem.detail, + kind: client.protocol2CodeConverter.asSymbolKind(lspTypeHierarchyItem.kind), + deprecated: lspTypeHierarchyItem.deprecated, + uri: lspTypeHierarchyItem.uri, + range: client.protocol2CodeConverter.asRange(lspTypeHierarchyItem.range), + selectionRange: client.protocol2CodeConverter.asRange(lspTypeHierarchyItem.selectionRange), + parents: parents, + children: children, + data: lspTypeHierarchyItem.data, + expand: false, + }; +} + +export function typeHierarchyDirectionToContextString(direction: TypeHierarchyDirection): string { + switch (direction) { + case TypeHierarchyDirection.children: + return "children"; + case TypeHierarchyDirection.parents: + return "parents"; + case TypeHierarchyDirection.both: + return "both"; + default: + return undefined; + } +} + +export async function resolveTypeHierarchy(client: LanguageClient, typeHierarchyItem: TypeHierarchyItem, direction: TypeHierarchyDirection, token: CancellationToken): Promise { + const lspTypeHierarchyItem = toSingleLSPTypeHierarchyItem(client, typeHierarchyItem); + let resolvedLSPItem: LSPTypeHierarchyItem; + try { + resolvedLSPItem = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_TYPE_HIERARCHY, JSON.stringify(lspTypeHierarchyItem), JSON.stringify(direction), JSON.stringify(1), token); + } catch (e) { + // operation cancelled + return undefined; + } + const resolvedItem = toTypeHierarchyItem(client, resolvedLSPItem, direction); + if (!resolvedItem) { + return undefined; + } + resolvedItem.expand = typeHierarchyItem.expand; + return resolvedItem; +} + +export async function getRootItem(client: LanguageClient, typeHierarchyItem: TypeHierarchyItem, token: CancellationToken): Promise { + if (!typeHierarchyItem) { + return undefined; + } + if (!typeHierarchyItem.parents) { + const resolvedItem = await resolveTypeHierarchy(client, typeHierarchyItem, TypeHierarchyDirection.parents, token); + if (!resolvedItem || !resolvedItem.parents) { + return typeHierarchyItem; + } else { + typeHierarchyItem.parents = resolvedItem.parents; + } + } + if (typeHierarchyItem.parents.length === 0) { + return typeHierarchyItem; + } else { + for (const parent of typeHierarchyItem.parents) { + if (parent.kind === SymbolKind.Class || parent.kind === SymbolKind.Null) { + parent.children = [typeHierarchyItem]; + parent.expand = true; + return getRootItem(client, parent, token); + } + } + return typeHierarchyItem; + } +} diff --git a/src/utils.ts b/src/utils.ts index 9e53cb116b..02a0becd5b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,412 @@ 'use strict'; -import { workspace, WorkspaceConfiguration } from 'vscode'; +import * as fs from 'fs'; +import * as path from 'path'; +import { workspace, WorkspaceConfiguration, commands, Uri, version, ExtensionContext } from 'vscode'; +import { Commands } from './commands'; +import { IJavaRuntime } from 'jdk-utils'; +import { getSupportedJreNames, listJdks, sortJdksBySource, sortJdksByVersion } from './jdkUtils'; +const vscodeVariables = require('vscode-variables'); export function getJavaConfiguration(): WorkspaceConfiguration { return workspace.getConfiguration('java'); } + +export function isPreferenceOverridden(section: string): boolean { + const config = workspace.getConfiguration(); + return config.inspect(section).workspaceFolderValue !== undefined || + config.inspect(section).workspaceFolderLanguageValue !== undefined || + config.inspect(section).workspaceValue !== undefined || + config.inspect(section).workspaceLanguageValue !== undefined || + config.inspect(section).globalValue !== undefined || + config.inspect(section).globalLanguageValue !== undefined; +} + +export function cleanJavaLSConfiguration(context: ExtensionContext) { + const globalStoragePath = context.globalStorageUri?.fsPath; // .../Code/User/globalStorage/redhat.java + deleteDirectory(globalStoragePath); +} + +export function deleteDirectory(dir) { + if (fs.existsSync(dir)) { + fs.readdirSync(dir).forEach((child) => { + const entry = path.join(dir, child); + if (fs.lstatSync(entry).isDirectory()) { + deleteDirectory(entry); + } else { + fs.unlinkSync(entry); + } + }); + fs.rmdirSync(dir); + } +} + +export function deleteClientLog(dir) { + if (fs.existsSync(dir)) { + fs.readdirSync(dir).forEach((child) => { + if (child.startsWith('client.log') || child.endsWith('audit.json')) { + const entry = path.join(dir, child); + if (!fs.lstatSync(entry).isDirectory()) { + fs.unlinkSync(entry); + } + } + }); + } +} + +export function getTimestamp(file) { + if (!fs.existsSync(file)) { + return -1; + } + const stat = fs.statSync(file); + return stat.mtimeMs; +} + +export function ensureExists(folder) { + if (fs.existsSync(folder)) { + return; + } + ensureExists(path.dirname(folder)); + fs.mkdirSync(folder); +} + +export function getBuildFilePatterns(): string[] { + const config = getJavaConfiguration(); + const isMavenImporterEnabled: boolean = config.get("import.maven.enabled"); + const isGradleImporterEnabled: boolean = config.get("import.gradle.enabled"); + const patterns: string[] = []; + if (isMavenImporterEnabled) { + patterns.push("**/pom.xml"); + } + if (isGradleImporterEnabled) { + patterns.push("**/*.gradle"); + patterns.push("**/*.gradle.kts"); + } + + return patterns; +} + +export function getInclusionPatternsFromNegatedExclusion(): string[] { + const config = getJavaConfiguration(); + const exclusions: string[] = config.get("import.exclusions", []); + const patterns: string[] = []; + for (const exclusion of exclusions) { + if (exclusion.startsWith("!")) { + patterns.push(exclusion.substr(1)); + } + } + return patterns; +} + +export function convertToGlob(filePatterns: string[], basePatterns?: string[]): string { + if (!filePatterns || filePatterns.length === 0) { + return ""; + } + + if (!basePatterns || basePatterns.length === 0) { + return parseToStringGlob(filePatterns); + } + + const patterns: string[] = []; + for (const basePattern of basePatterns) { + for (const filePattern of filePatterns) { + patterns.push(path.join(basePattern, `/${filePattern}`).replace(/\\/g, "/")); + } + } + return parseToStringGlob(patterns); +} + +/** + * Merge the values of setting 'java.import.exclusions' into one glob pattern. + * @param additionalExclusions Additional exclusions to be merged into the glob pattern. + */ +export function getExclusionGlob(additionalExclusions?: string[]): string { + const config = getJavaConfiguration(); + const exclusions: string[] = config.get("import.exclusions", []); + const patterns: string[] = []; + for (const exclusion of exclusions) { + if (exclusion.startsWith("!")) { + continue; + } + + patterns.push(exclusion); + } + if (additionalExclusions) { + patterns.push(...additionalExclusions); + } + return parseToStringGlob(patterns); +} + +function parseToStringGlob(patterns: string[]): string { + if (!patterns || patterns.length === 0) { + return ""; + } + + return `{${patterns.join(",")}}`; +} + +/** + * Get all Java projects from Java Language Server. + * @param excludeDefaultProject whether the default project should be excluded from the list, defaults to true. + * @returns string array for the project uris. + */ +export async function getAllJavaProjects(excludeDefaultProject: boolean = true): Promise { + const projectUris: string[] = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_ALL_JAVA_PROJECTS); + return filterDefaultProject(projectUris, excludeDefaultProject); +} + +/** + * Get all projects from Java Language Server. + * @param excludeDefaultProject whether the default project should be excluded from the list, defaults to true. + * @returns string array for the project uris. + */ +export async function getAllProjects(excludeDefaultProject: boolean = true): Promise { + const projectUris: string[] = await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_ALL_JAVA_PROJECTS, + JSON.stringify({ includeNonJava: true })); + return filterDefaultProject(projectUris, excludeDefaultProject); +} + +function filterDefaultProject(projectUris: string[], excludeDefaultProject: boolean): string[] { + if (excludeDefaultProject) { + return projectUris.filter((uriString) => { + const projectPath = Uri.parse(uriString).fsPath; + return path.basename(projectPath) !== "jdt.ls-java-project"; + }); + } + return projectUris; +} + +export async function hasBuildToolConflicts(): Promise { + const projectConfigurationUris: Uri[] = await getBuildFilesInWorkspace(); + const projectConfigurationFsPaths: string[] = projectConfigurationUris.map((uri) => uri.fsPath); + const eclipseDirectories = getDirectoriesByBuildFile(projectConfigurationFsPaths, [], ".project"); + // ignore the folders that already has .project file (already imported before) + const gradleDirectories = getDirectoriesByBuildFile(projectConfigurationFsPaths, eclipseDirectories, ".gradle"); + const gradleDirectoriesKts = getDirectoriesByBuildFile(projectConfigurationFsPaths, eclipseDirectories, ".gradle.kts"); + gradleDirectories.push(...gradleDirectoriesKts); + const mavenDirectories = getDirectoriesByBuildFile(projectConfigurationFsPaths, eclipseDirectories, "pom.xml"); + return gradleDirectories.some((gradleDir) => { + return mavenDirectories.includes(gradleDir); + }); +} + +async function getBuildFilesInWorkspace(): Promise { + const buildFiles: Uri[] = []; + const inclusionFilePatterns: string[] = getBuildFilePatterns(); + inclusionFilePatterns.push("**/.project"); + const inclusionFolderPatterns: string[] = getInclusionPatternsFromNegatedExclusion(); + // Since VS Code API does not support put negated exclusion pattern in findFiles(), + // here we first parse the negated exclusion to inclusion and do the search. + if (inclusionFilePatterns.length > 0 && inclusionFolderPatterns.length > 0) { + buildFiles.push(...await workspace.findFiles(convertToGlob(inclusionFilePatterns, inclusionFolderPatterns), null /* force not use default exclusion */)); + } + + const inclusionGlob: string = convertToGlob(inclusionFilePatterns); + const exclusionGlob: string = getExclusionGlob(); + if (inclusionGlob) { + buildFiles.push(...await workspace.findFiles(inclusionGlob, exclusionGlob)); + } + + return buildFiles; +} + +function getDirectoriesByBuildFile(inclusions: string[], exclusions: string[], fileName: string): string[] { + return inclusions.filter((fsPath) => fsPath.endsWith(fileName)).map((fsPath) => { + return path.dirname(fsPath); + }).filter((inclusion) => { + return !exclusions.includes(inclusion); + }); +} + +const detectJdksAtStart: boolean = getJavaConfiguration().get('configuration.detectJdksAtStart'); + +export async function getJavaConfig(javaHome: string) { + const origConfig = getJavaConfiguration(); + const javaConfig = JSON.parse(JSON.stringify(origConfig)); + javaConfig.home = javaHome; + // Since source & output path are project specific settings. To avoid pollute other project, + // we avoid reading the value from the global scope. + javaConfig.project.outputPath = origConfig.inspect("project.outputPath").workspaceValue; + javaConfig.project.sourcePaths = origConfig.inspect("project.sourcePaths").workspaceValue; + + const editorConfig = workspace.getConfiguration('editor'); + javaConfig.format.insertSpaces = editorConfig.get('insertSpaces'); + javaConfig.format.tabSize = editorConfig.get('tabSize'); + const filesConfig = workspace.getConfiguration('files'); + javaConfig.associations = filesConfig.get('associations'); + const isInsider: boolean = isInsiderEditor(); + const androidSupport = javaConfig.jdt.ls.androidSupport.enabled; + switch (androidSupport) { + case "auto": + javaConfig.jdt.ls.androidSupport.enabled = isInsider; + break; + case "on": + javaConfig.jdt.ls.androidSupport.enabled = true; + break; + case "off": + javaConfig.jdt.ls.androidSupport.enabled = false; + break; + default: + javaConfig.jdt.ls.androidSupport.enabled = false; + break; + } + + const javacSupport = javaConfig.jdt.ls.javac.enabled; + switch (javacSupport) { + case "on": + javaConfig.jdt.ls.javac.enabled = true; + break; + case "off": + javaConfig.jdt.ls.javac.enabled = false; + break; + default: + javaConfig.jdt.ls.javac.enabled = false; + break; + } + + if (javaConfig.completion.matchCase === "auto") { + javaConfig.completion.matchCase = "firstLetter"; + } + + const guessMethodArguments = javaConfig.completion.guessMethodArguments; + if (guessMethodArguments === "auto") { + javaConfig.completion.guessMethodArguments = isInsider ? "off" : "insertBestGuessedArguments"; + } + + javaConfig.telemetry = { enabled: workspace.getConfiguration('redhat.telemetry').get('enabled', false) }; + if (detectJdksAtStart) { + const userConfiguredJREs: any[] = javaConfig.configuration.runtimes; + javaConfig.configuration.runtimes = await addAutoDetectedJdks(userConfiguredJREs); + } + + if (!isPreferenceOverridden("java.implementationCodeLens") && typeof javaConfig.implementationsCodeLens?.enabled === 'boolean'){ + const deprecatedImplementations = javaConfig.implementationsCodeLens.enabled; + javaConfig.implementationCodeLens = deprecatedImplementations ? "types" : "none"; + } + + return javaConfig; +} + +async function addAutoDetectedJdks(configuredJREs: any[]): Promise { + // search valid JDKs from env.JAVA_HOME, env.PATH, SDKMAN, jEnv, jabba, Common directories + const autoDetectedJREs: IJavaRuntime[] = await listJdks(); + sortJdksByVersion(autoDetectedJREs); + sortJdksBySource(autoDetectedJREs); + const addedJreNames: Set = new Set(); + const supportedJreNames: string[] = getSupportedJreNames(); + for (const jre of configuredJREs) { + if (jre.name) { + addedJreNames.add(jre.name); + } + } + for (const jre of autoDetectedJREs) { + const majorVersion: number = jre.version?.major ?? 0; + if (!majorVersion) { + continue; + } + + let jreName: string = `JavaSE-${majorVersion}`; + if (majorVersion <= 5) { + jreName = `J2SE-1.${majorVersion}`; + } else if (majorVersion <= 8) { + jreName = `JavaSE-1.${majorVersion}`; + } + + if (addedJreNames.has(jreName) || !supportedJreNames?.includes(jreName)) { + continue; + } + + configuredJREs.push({ + name: jreName, + path: jre.homedir, + }); + + addedJreNames.add(jreName); + } + + return configuredJREs; +} + +export function resolveActualCause(callstack: any): any { + if (!callstack) { + return; + } + + const callstacks = callstack.split(/\r?\n/); + if (callstacks?.length) { + for (let i = callstacks.length - 1; i >= 0; i--) { + if (callstacks[i]?.startsWith("Caused by:")) { + return callstacks.slice(i).join("\n"); + } + } + } + + return callstack; +} + +export function getVersion(extensionPath: string): string { + const packagePath = path.resolve(extensionPath, "package.json"); + const packageFile = JSON.parse(fs.readFileSync(packagePath, 'utf8')); + if (packageFile) { + return packageFile.version; + } + + return '0.0.0'; +} + +export function getVSCodeVariablesMap(): any { + const keys = [ + "userHome", "workspaceFolder", "workspaceFolderBasename" + ]; + const res = {}; + keys.forEach(key => res[key] = vscodeVariables(`\${${key}}`)); + return res; +} + +/** + * Check if the extension version is a pre-release version or running an insider editor. + * @param context The extension context or extension path + * @returns true if the version is a pre-release version or running an insider editor + */ +export function isPrereleaseOrInsiderVersion(context: ExtensionContext | string): boolean { + return isInsiderEditor() || isPreReleaseVersion(context); +} + +/** + * Check if the extension version is a pre-release version. + * Pre-release versions follow the pattern: major.minor.timestamp (e.g., 1.47.1234567890) + * @param context The extension context or extension path + * @returns true if the version is a pre-release version + */ +export function isPreReleaseVersion(context: ExtensionContext | string): boolean { + const extensionPath = typeof context === 'string' ? context : context.extensionPath; + const extVersion = getVersion(extensionPath); + return /^\d+\.\d+\.\d{10}/.test(extVersion); +} + +/** + * Check if the editor is an insider release. + * @returns true if the editor is an insider release + */ +export function isInsiderEditor(): boolean { + return version.includes("insider"); +} +/* +* cyrb53 (c) 2018 bryc (github.com/bryc) +* Public domain (or MIT if needed). Attribution appreciated. +* A fast and simple 53-bit string hash function with decent collision resistance. +* Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity. +*/ +export function cyrb53 (str, seed = 0) { + let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; + for (let i = 0, ch; i < str.length; i++) { + ch = str.charCodeAt(i); + h1 = Math.imul(h1 ^ ch, 2654435761); + h2 = Math.imul(h2 ^ ch, 1597334677); + } + h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507); + h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909); + h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507); + h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909); + return 4294967296 * (2097151 & h2) + (h1 >>> 0); +}; diff --git a/src/webview/changeSignature/App.css b/src/webview/changeSignature/App.css new file mode 100644 index 0000000000..2feef25eaa --- /dev/null +++ b/src/webview/changeSignature/App.css @@ -0,0 +1,157 @@ +@import "../../../node_modules/@vscode/codicons/dist/codicon.css"; + +main { + max-width: 600px; + margin-left: auto; + margin-right: auto; +} + +.section { + margin-bottom: 0; +} + +.section-columns { + display: flex; + width: 100%; + padding-left: calc(var(--design-unit) * 1px); +} + +.text-title { + margin: 0; + height: calc(var(--input-height) * 0.8px); +} + +.text-title-content { + padding: 0 0 0 calc(var(--design-unit) * 1px); + margin: 0.5rem 0 0 0; + height: calc(var(--input-height) * 0.8px); +} + +.header-left { + flex-direction: column; + display: flex; + padding: 0.5rem 0.5rem 0.5rem 0; + flex: 0 0 33%; + box-sizing: border-box; +} + +.header { + flex-direction: column; + display: flex; + padding: 0.5rem; + flex: 0 0 33%; + box-sizing: border-box; +} + +.header-right { + flex-direction: column; + display: flex; + padding: 0.5rem 0 0.5rem 0.5rem; + flex: 0 0 33%; + box-sizing: border-box; +} + +.vsc-button-left { + float: left; + margin: 0 0.5rem 0.5rem 0; +} + +.vsc-button { + float: left; + margin: 0 0.5rem 0.5rem 0.5rem; +} + +.add-button { + margin: 0.5rem 0 0 0; +} + +.bottom-buttons { + padding: 0 0 0 calc(var(--design-unit) * 1px); + margin: 0.5rem 0 0 0; +} + +.preview { + padding: 0 0 0 calc(var(--design-unit) * 1px); + margin: 0 0 0.5rem 0; + width: 99%; +} + +.parameters-panel { + margin: 0; + width: calc(99% + 4px); +} + +.parameters-view { + padding: 0 0 0 calc(var(--design-unit) * 1px); + flex-direction: column; +} + +.parameter-cell { + padding-left: 0; + pointer-events: none; +} + +.parameter-cell-title { + padding-left: 0; +} + +.parameter-cell-title:focus { + border-color: var(--vscode-keybindingTable-headerBackground); + background-color: inherit; + color: inherit; +} + +.parameter-cell-header { + background-color: var(--vscode-keybindingTable-headerBackground); +} + +.parameter-cell-edit { + padding-left: 0; + background-color: var(--vscode-input-background); +} + +.parameter-cell-edit-button { + padding: 0; + border: 0; + display: flex; + justify-content: right; + background-color: var(--vscode-input-background); +} + +.parameter-cell-button { + padding: 0; + border: 0; + display: flex; + justify-content: right; +} + +.parameter-cell-button:focus { + background-color: inherit; +} + +.parameter-cell-button:active { + background-color: inherit; +} + +.table-buttons { + display: inline-flex; +} + +.table-buttons-edit { + display: inline-flex; + background-color: var(--vscode-editor-background); +} + +.table-buttons-edit-ok { + margin-left: 0.2rem; + margin-right: 0.2rem; +} + +.table-buttons-edit-cancel { + margin: 0; +} + +.delegate { + padding: 0 0 0 calc(var(--design-unit) * 1px); + margin: 0.5rem 0 0.5rem 0; +} diff --git a/src/webview/changeSignature/App.tsx b/src/webview/changeSignature/App.tsx new file mode 100644 index 0000000000..1531efeda2 --- /dev/null +++ b/src/webview/changeSignature/App.tsx @@ -0,0 +1,594 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/* eslint-disable @typescript-eslint/prefer-for-of */ +import { VSCodeButton, VSCodeTextField, VSCodeDropdown, VSCodeOption, VSCodeCheckbox, VSCodePanels, VSCodePanelTab, VSCodePanelView, VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow, VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"; +import "./App.css"; +import React from "react"; +import { vscode } from "../vscodeApiWrapper"; +import cloneDeep from "lodash/cloneDeep"; + +type State = UIState & Metadata; + +interface UIState { + focusRow: number; + editParameterRow: number; + editExceptionRow: number; +} + +interface Metadata { + methodIdentifier: string | undefined; + isDelegate: boolean; + methodName: string | undefined; + accessType: string | undefined; + returnType: string | undefined; + parameters: MethodParameter[]; + exceptions: MethodException[]; +} + +interface MethodParameter { + type: string; + name: string; + defaultValue: string; + originalIndex: number; +} + +interface MethodException { + type: string; + typeHandleIdentifier: string | undefined; +} + +export class App extends React.Component<{}, State> { + + private initialMetadata: Metadata; + private static TOOLTIP_RETURN_TYPE: string = "The method return type, can be either name or fully qualified name of the type."; + private static TOOLTIP_PARAMETER_TYPE: string = "The parameter type, can be either name or fully qualified name of the type."; + private static TOOLTIP_PARAMETER_DEFAULT: string = "The parameter default value, used when replacing the occurrences for an added parameter."; + private static TOOLTIP_EXCEPTION_TYPE: string = "The exception type, can be either name or fully qualified name of the type."; + + constructor(props: any) { + super(props); + this.state = { + focusRow: -1, + editParameterRow: -1, + editExceptionRow: -1, + methodIdentifier: undefined, + isDelegate: false, + methodName: undefined, + accessType: undefined, + returnType: undefined, + parameters: [], + exceptions: [] + }; + } + + doRefactor = (preview: boolean) => { + vscode.postMessage({ + preview: preview, + command: "doRefactor", + methodIdentifier: this.state.methodIdentifier, + isDelegate: this.state.isDelegate, + accessType: this.getModifierString(this.state.accessType), + methodName: this.state.methodName, + returnType: this.state.returnType, + parameters: this.state.parameters, + exceptions: this.state.exceptions, + }); + }; + + onChange = (event: any) => { + const id = event.target.id as string; + if (!id) { + return; + } + if (id === "access-modifier") { + this.setState({ + accessType: event.target.value + }); + } else if (id === "returnType") { + this.setState({ + returnType: event.target.value + }); + } else if (id === "methodName") { + this.setState({ + methodName: event.target.value + }); + } + return; + }; + + getPreview = () => { + let parameters = ""; + for (let i = 0; i < this.state.parameters.length; i++) { + parameters += `${this.state.parameters[i].type} ${this.state.parameters[i].name}, `; + } + parameters = parameters.substring(0, parameters.length - 2); + let exceptions = ""; + if (this.state.exceptions.length) { + exceptions = " throws "; + for (let i = 0; i < this.state.exceptions.length; i++) { + exceptions += `${this.state.exceptions[i].type}, `; + } + exceptions = exceptions.substring(0, exceptions.length - 2); + } + let accessTypeString = this.getModifierString(this.state.accessType); + if (accessTypeString?.length) { + accessTypeString += " "; + } + return `${accessTypeString}${this.state.returnType} ${this.state.methodName}(${parameters})${exceptions}`; + }; + + onClick = (event: any) => { + const id = event.target.id as string; + if (!id) { + return; + } + if (id === "refactor") { + this.doRefactor(false); + } else if (id === "preview") { + this.doRefactor(true); + } else if (id === "reset") { + this.setState({ + methodIdentifier: this.initialMetadata.methodIdentifier, + isDelegate: this.initialMetadata.isDelegate, + accessType: this.initialMetadata.accessType, + methodName: this.initialMetadata.methodName, + returnType: this.initialMetadata.returnType, + parameters: cloneDeep(this.initialMetadata.parameters), + exceptions: cloneDeep(this.initialMetadata.exceptions), + focusRow: -1, + editParameterRow: -1, + editExceptionRow: -1, + }); + } else if (id === "addParameter") { + const parameterNames = this.state.parameters.map(e => { + return e.name; + }); + let newParameterName: string = "newParam"; + let i = 1; + while (parameterNames.includes(newParameterName)) { + i++; + newParameterName = `newParam${i}`; + } + this.setState({ + parameters: [...this.state.parameters, { + type: "Object", + name: newParameterName, + defaultValue: "null", + originalIndex: -1 + }] + }); + } else if (id.startsWith("removeParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + this.setState({ + parameters: this.state.parameters.filter((e, i) => { + return i !== selectedRowNumber; + }) + }); + } else if (id.startsWith("editParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + this.setState({ + editParameterRow: selectedRowNumber, + editExceptionRow: -1, + focusRow: -1, + }); + const elementToSelect = document.getElementById(`parameterType-${selectedRowNumber}`); + if (elementToSelect) { + elementToSelect.focus(); + } + } else if (id.startsWith("editException")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + this.setState({ + editParameterRow: -1, + editExceptionRow: selectedRowNumber, + focusRow: -1, + }); + const elementToSelect = document.getElementById(`exceptionType-${selectedRowNumber}`); + if (elementToSelect) { + elementToSelect.focus(); + } + } else if (id.startsWith("upParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const currentParameters = this.state.parameters; + const temp = currentParameters[selectedRowNumber - 1]; + currentParameters[selectedRowNumber - 1] = currentParameters[selectedRowNumber]; + currentParameters[selectedRowNumber] = temp; + this.setState({ + parameters: currentParameters + }); + } else if (id.startsWith("downParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const currentParameters = this.state.parameters; + const temp = currentParameters[selectedRowNumber + 1]; + currentParameters[selectedRowNumber + 1] = currentParameters[selectedRowNumber]; + currentParameters[selectedRowNumber] = temp; + this.setState({ + parameters: currentParameters + }); + } else if (id === "addException") { + const exceptionNames = this.state.exceptions.map(e => { + return e.type; + }); + let newExceptionName: string = "Exception"; + let i = 1; + while (exceptionNames.includes(newExceptionName)) { + i++; + newExceptionName = `Exception${i}`; + } + this.setState({ + exceptions: [...this.state.exceptions, { + type: newExceptionName, + typeHandleIdentifier: undefined, + }] + }); + } else if (id.startsWith("removeException")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + this.setState({ + exceptions: this.state.exceptions.filter((e, i) => { + return i !== selectedRowNumber; + }) + }); + } else if (id === "delegate") { + this.setState({ + isDelegate: event.target.checked + }); + } else if (id.startsWith("confirmParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const parameterType = document.getElementById(`parameterType-${selectedRowNumber}`); + const parameterName = document.getElementById(`parameterName-${selectedRowNumber}`); + const parameterDefault = this.isDefaultValueEditable(selectedRowNumber) ? document.getElementById(`parameterDefault-${selectedRowNumber}`) : undefined; + this.setState({ + parameters: this.state.parameters.map((e, i) => { + if (i === selectedRowNumber) { + if (parameterType?.outerText) { + e.type = parameterType.outerText; + } + if (parameterName?.outerText) { + e.name = parameterName.outerText; + } + if (parameterDefault?.outerText) { + e.defaultValue = parameterDefault.outerText; + } + } + return e; + }), + editParameterRow: -1, + editExceptionRow: -1, + focusRow: -1 + }); + } else if (id.startsWith("cancelParameter")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const parameterType = document.getElementById(`parameterType-${selectedRowNumber}`); + if (parameterType) { + parameterType.textContent = this.state.parameters[selectedRowNumber].type; + } + const parameterName = document.getElementById(`parameterName-${selectedRowNumber}`); + if (parameterName) { + parameterName.textContent = this.state.parameters[selectedRowNumber].name; + } + if (this.isDefaultValueEditable(selectedRowNumber)) { + const parameterDefault = document.getElementById(`parameterDefault-${selectedRowNumber}`); + if (parameterDefault) { + parameterDefault.textContent = this.state.parameters[selectedRowNumber].defaultValue; + } + } + this.setState({ + editParameterRow: -1, + editExceptionRow: -1, + focusRow: -1 + }); + } else if (id.startsWith("confirmException")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const exceptionType = document.getElementById(`exceptionType-${selectedRowNumber}`); + this.setState({ + exceptions: this.state.exceptions.map((e, i) => { + if (i === selectedRowNumber) { + if (exceptionType?.outerText) { + e.type = exceptionType.outerText; + } + } + return e; + }), + editParameterRow: -1, + editExceptionRow: -1, + focusRow: -1 + }); + } else if (id.startsWith("cancelException")) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber === undefined) { + return; + } + const exceptionType = document.getElementById(`exceptionType-${selectedRowNumber}`); + if (exceptionType) { + exceptionType.textContent = this.state.exceptions[selectedRowNumber].type; + } + this.setState({ + editParameterRow: -1, + editExceptionRow: -1, + focusRow: -1 + }); + } + }; + + handleMessage = (event: any) => { + const { data } = event; + const command = data.command as string; + if (command === "setInitialState") { + this.initialMetadata = { + methodIdentifier: data.methodIdentifier, + isDelegate: false, + accessType: this.getAccessTypeString(data.modifier), + methodName: data.methodName, + returnType: data.returnType, + parameters: data.parameters, + exceptions: data.exceptions, + }; + this.setState({ + methodIdentifier: this.initialMetadata.methodIdentifier, + isDelegate: this.initialMetadata.isDelegate, + accessType: this.initialMetadata.accessType, + methodName: this.initialMetadata.methodName, + returnType: this.initialMetadata.returnType, + parameters: cloneDeep(this.initialMetadata.parameters), + exceptions: cloneDeep(this.initialMetadata.exceptions), + }); + } + }; + + onMouseEnter = (event: any) => { + const id = event.target.id as string; + if (id.includes("Header")) { + this.setState({ + focusRow: -1 + }); + } else if (id) { + const selectedRowNumber: number | undefined = this.getSelectedRowNumber(id); + if (selectedRowNumber !== undefined) { + this.setState({ + focusRow: selectedRowNumber + }); + } + } + }; + + onMouseLeave = (event: any) => { + this.setState({ + focusRow: -1 + }); + }; + + componentDidMount(): void { + this.setTextAreaCursorStyle(); + window.addEventListener("message", this.handleMessage); + vscode.postMessage({ + command: "webviewReady" + }); + } + + isUnchanged = () => { + return this.state.isDelegate === this.initialMetadata?.isDelegate + && this.state.accessType === this.initialMetadata?.accessType + && this.state.methodName === this.initialMetadata?.methodName + && this.state.returnType === this.initialMetadata?.returnType + && this.isArrayEqual(this.state.parameters, this.initialMetadata?.parameters) + && this.isArrayEqual(this.state.exceptions, this.initialMetadata?.exceptions); + }; + + isArrayEqual = (a: any[], b: any[]) => { + return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((e, i) => this.objectsEqual(e, b[i])); + }; + + objectsEqual = (o1, o2) => { + return typeof o1 === 'object' && Object.keys(o1).length > 0 + ? Object.keys(o1).length === Object.keys(o2).length + && Object.keys(o1).every(p => this.objectsEqual(o1[p], o2[p])) + : o1 === o2; + }; + + /** + * Set the cursor style of the text area to text. Since the text area is + * inside a shadow DOM, we need to add a style element to the shadow DOM. + */ + setTextAreaCursorStyle(): void { + const host = document.getElementById("textArea"); + if (host?.shadowRoot) { + const style = document.createElement('style'); + style.innerHTML = '.control { cursor: text !important; }'; + host.shadowRoot.appendChild(style); + } + } + + isDefaultValueEditable = (row: number) => { + return this.state.parameters[row].originalIndex === -1; + }; + + getDefaultValue = (row: number) => { + return this.isDefaultValueEditable(row) ? this.state.parameters[row].defaultValue : "-"; + }; + + generateParameterDataGridRow = (row: number) => { + return + {this.state.parameters[row].type} + {this.state.parameters[row].name} + {this.getDefaultValue(row)} + + {row === this.state.editParameterRow ? +
+ OK + Cancel +
: row === this.state.focusRow ?
+ {row === 0 ? <> : + + } + {row === this.state.parameters.length - 1 ? <> : + + } + + + + + + +
:
+ } +
+
; + }; + + generateExceptionDataGridRow = (row: number) => { + return + {this.state.exceptions[row].type} + + {row === this.state.editExceptionRow ? +
+ OK + Cancel +
: row === this.state.focusRow ?
+ + + + + + +
:
+ } +
+
; + }; + + render = () => { + return ( +
+

Change Method Signature

+
+
+
+
Access modifier:
+ + public + protected + package-private + private + +
+
+
Return type:
+ +
+
+
Method name:
+ +
+
+
+ + Parameters + Exceptions + + + + Type + Name + Default value + + + { + (() => { + const options: JSX.Element[] = []; + for (let row = 0; row < this.state.parameters.length; row++) { + options.push(this.generateParameterDataGridRow(row)); + } + return options; + })() + } + +
+ Add +
+
+ + + + Type + + + { + (() => { + const options: JSX.Element[] = []; + for (let row = 0; row < this.state.exceptions.length; row++) { + options.push(this.generateExceptionDataGridRow(row)); + } + return options; + })() + } + +
+ Add +
+
+
+
Method signature:
+ + Keep original method as delegate to changed method +
+ Refactor + Preview + Reset +
+
+ ); + }; + + /** + * get the row number of the item id. The format is `${description}-${rowNumber}`. + * @param id the item id + * @returns the row number, or undefined if the id is not in the correct format + */ + private getSelectedRowNumber(id: string): number | undefined { + const idSplit: string[] = id.split("-"); + if (idSplit.length !== 2) { + return undefined; + } + return Number(idSplit[1]); + } + + private getModifierString(accessType: string | undefined): string { + if (!accessType || accessType === "package-private") { + return ""; + } + return accessType; + } + + private getAccessTypeString(visibility: string): string { + if (visibility === "") { + return "package-private"; + } + return visibility; + } + +} diff --git a/src/webview/changeSignature/index.tsx b/src/webview/changeSignature/index.tsx new file mode 100644 index 0000000000..16e0258412 --- /dev/null +++ b/src/webview/changeSignature/index.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { App } from "./App"; + +ReactDOM.render( + + + , + document.getElementById("root") +); diff --git a/src/webview/dashboard/dashboard.css b/src/webview/dashboard/dashboard.css new file mode 100644 index 0000000000..96ed2d3637 --- /dev/null +++ b/src/webview/dashboard/dashboard.css @@ -0,0 +1,14 @@ +@import "../../../node_modules/@vscode/codicons/dist/codicon.css"; + +.toolbar { + margin: 8px; + width: 100%; + display: flex; + flex-flow: row nowrap; + gap: 4px; + justify-content: flex-end; +} + +.toolbarItem { + color: var(--vscode-sideBarSectionHeader-foreground); +} \ No newline at end of file diff --git a/src/webview/dashboard/dashboard.tsx b/src/webview/dashboard/dashboard.tsx new file mode 100644 index 0000000000..699157f21e --- /dev/null +++ b/src/webview/dashboard/dashboard.tsx @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/* eslint-disable @typescript-eslint/prefer-for-of */ +import React from "react"; +import { vscode } from "../vscodeApiWrapper"; +import { Jvms } from "./jvms"; +import { DiagnosticInfo, JVM, ToDashboardMessage, ToDashboardMessageType, UpdateMessage } from "../../webviewProtocol/toDashboard"; +import './dashboard.css'; + +type State = { + workspacePath: string; + jvms: JVM[]; + lombokEnabled: boolean; + activeLombokPath: string | undefined; + diagnosticInfo: DiagnosticInfo | undefined; +}; + +export interface AppProps { +} + +function openSettingsLink(settingId: string): string { + const args = { + query: settingId + }; + return `command:workbench.action.openSettings?${encodeURIComponent(JSON.stringify(args))}`; +} + +export class Dashboard extends React.Component { + + constructor(props: AppProps) { + super(props); + this.state = { + workspacePath: 'unknown', + jvms: [], + lombokEnabled: false, + activeLombokPath: 'unknown', + diagnosticInfo: { + mavenUserSettings: 'unknown', + mavenGlobalSettings: 'unknown', + activeImporters: [], + gradleUserHome: 'unknown', + gradleJavaHome: 'unknown' + } + }; + } + + handleMessage = (event: MessageEvent) => { + const message = event.data as ToDashboardMessage; + switch (message.type) { + case "update": { + for (const [key, value] of Object.entries(message as UpdateMessage)) { + this.setState({ [key]: value } as Pick); + } + } + break; + } + }; + + componentDidMount(): void { + window.addEventListener("message", this.handleMessage); + vscode.postMessage({ + command: "webviewReady" + }); + } + + + render = () => { + + const args = [ { + path: this.state.workspacePath + }]; + return ( +
+
+ + +
+

Workspace

+
Language Server Workspace: {this.state.workspacePath || 'undefined'}
+ +

Detected Java Installations

+ + configure... +
+

Lombok Support

+
+ enabled + + configure... +
+
Using Lombok at: {this.state.activeLombokPath || ''}
+

Maven

+
User Settings: {this.state.diagnosticInfo?.mavenUserSettings || 'undefined'} configure...
+
Global Settings: {this.state.diagnosticInfo?.mavenGlobalSettings || 'undefined'} configure...
+

Gradle

+
User Home: {this.state.diagnosticInfo?.gradleUserHome || 'undefined'} configure...
+
Java Home: {this.state.diagnosticInfo?.gradleJavaHome || 'undefined'} configure...
+

Registered Project Importers

+ {this.state.diagnosticInfo?.activeImporters.map((clazz, index) => ( +
{clazz}
+ ))} +
+ ); + }; +} diff --git a/src/webview/dashboard/index.tsx b/src/webview/dashboard/index.tsx new file mode 100644 index 0000000000..ee2cd1ea56 --- /dev/null +++ b/src/webview/dashboard/index.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { Dashboard } from "./dashboard"; + + +ReactDOM.render( + + + , + document.getElementById('root') +); \ No newline at end of file diff --git a/src/webview/dashboard/jvms.css b/src/webview/dashboard/jvms.css new file mode 100644 index 0000000000..0748e852ff --- /dev/null +++ b/src/webview/dashboard/jvms.css @@ -0,0 +1,22 @@ +.jvm-table { + text-align: left; + width: 100%; + border-collapse: collapse; + border: 1px solid var(--vscode-panel-border); +} + +.jvm-table td{ + border-left: 1px solid var(--vscode-panel-border); +} + +.jvm-table th{ + border-bottom: 1px solid var(--vscode-panel-border); +} + +.jvm-table th>td { + background-color: var(--vscode-sideBarSectionHeader-background); +} + +.jvm-table tbody tr.odd { + background-color: var(--vscode-tree-tableOddRowsBackground); +} \ No newline at end of file diff --git a/src/webview/dashboard/jvms.tsx b/src/webview/dashboard/jvms.tsx new file mode 100644 index 0000000000..7802197705 --- /dev/null +++ b/src/webview/dashboard/jvms.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { JVM } from "../../webviewProtocol/toDashboard"; +import path from "path"; +import './jvms.css'; + +export interface JvmsProps { + jvms: JVM[]; +} + +export class Jvms extends React.Component { + constructor(props: any) { + super(props); + this.state = { + }; + } + + render = () => { + return ( + + + + + + + + + {this.props.jvms.map((jvm, index) => ( + + + + + ))} + +
NamePath
{jvm.name}{jvm.path}
+ ); + }; +} \ No newline at end of file diff --git a/src/webview/vscodeApiWrapper.ts b/src/webview/vscodeApiWrapper.ts new file mode 100644 index 0000000000..0b0eaa0113 --- /dev/null +++ b/src/webview/vscodeApiWrapper.ts @@ -0,0 +1,41 @@ +import type { WebviewApi } from "vscode-webview"; + +/** + * A utility wrapper around the acquireVsCodeApi() function, which enables + * message passing and state management between the webview and extension + * contexts. + * + * This utility also enables webview code to be run in a web browser-based + * dev server by using native web browser features that mock the functionality + * enabled by acquireVsCodeApi. + */ +class VSCodeAPIWrapper { + private readonly vsCodeApi: WebviewApi | undefined; + + constructor() { + // Check if the acquireVsCodeApi function exists in the current development + // context (i.e. VS Code development window or web browser) + if (typeof acquireVsCodeApi === "function") { + this.vsCodeApi = acquireVsCodeApi(); + } + } + + /** + * Post a message (i.e. send arbitrary data) to the owner of the webview. + * + * @remarks When running webview code inside a web browser, postMessage will instead + * log the given message to the console. + * + * @param message Abitrary data (must be JSON serializable) to send to the extension context. + */ + public postMessage(message: unknown) { + if (this.vsCodeApi) { + this.vsCodeApi.postMessage(message); + } else { + console.log(`VS Code API not available, raw message: ${message}`); + } + } +} + +// Exports class singleton to prevent multiple invocations of acquireVsCodeApi. +export const vscode = new VSCodeAPIWrapper(); diff --git a/src/webviewProtocol/common.ts b/src/webviewProtocol/common.ts new file mode 100644 index 0000000000..efb51cd9fb --- /dev/null +++ b/src/webviewProtocol/common.ts @@ -0,0 +1,6 @@ +export interface WebviewMessage { + type: T; +} + +export type FromWebviewMessageType = "webviewReady"; +export type ToWebviewMessageType = "update"; \ No newline at end of file diff --git a/src/webviewProtocol/fromDashboard.ts b/src/webviewProtocol/fromDashboard.ts new file mode 100644 index 0000000000..f1d0ace2d0 --- /dev/null +++ b/src/webviewProtocol/fromDashboard.ts @@ -0,0 +1,8 @@ +import { FromWebviewMessageType, WebviewMessage } from "./common"; + +export type FromDashboardMessageType = FromWebviewMessageType; + +export interface DashboardMessage extends WebviewMessage { + message: FromDashboardMessageType; +} + diff --git a/src/webviewProtocol/toDashboard.ts b/src/webviewProtocol/toDashboard.ts new file mode 100644 index 0000000000..df4133284e --- /dev/null +++ b/src/webviewProtocol/toDashboard.ts @@ -0,0 +1,32 @@ +import { Diagnostic } from "vscode"; +import { ToWebviewMessageType, WebviewMessage } from "./common"; + +export type ToDashboardMessageType = ToWebviewMessageType; + +export interface ToDashboardMessage extends WebviewMessage { +} + +export interface JVM { + name: string; + path: string; +} + +export interface DashboardState { + jvms?: JVM[]; + workspacePath?: string; + lombokEnabled?: boolean; + activeLombokPath?: string | undefined; + diagnosticInfo?: DiagnosticInfo; +} + +export interface DiagnosticInfo { + readonly mavenUserSettings: string; + readonly mavenGlobalSettings: string; + readonly activeImporters: string[]; + readonly gradleUserHome: string; + readonly gradleJavaHome: string; +} + +export interface UpdateMessage extends ToDashboardMessage, DashboardState { + type: "update"; +} \ No newline at end of file diff --git a/src/webviewUtils.ts b/src/webviewUtils.ts new file mode 100644 index 0000000000..3d79f13d40 --- /dev/null +++ b/src/webviewUtils.ts @@ -0,0 +1,14 @@ +import { Uri, Webview } from "vscode"; + +export function getUri(webview: Webview, extensionUri: Uri, ...pathList: string[]) { + return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)); +} + +export function getNonce() { + let text = ""; + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 32; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} diff --git a/test/common.ts b/test/common.ts new file mode 100644 index 0000000000..b0c47f994f --- /dev/null +++ b/test/common.ts @@ -0,0 +1,5 @@ +import * as path from 'path'; + +export namespace constants { + export const projectFsPath: string = path.join(__dirname, '..', '..', 'test-temp'); +} \ No newline at end of file diff --git a/test/extension.test.ts b/test/extension.test.ts deleted file mode 100644 index 79bb155c8b..0000000000 --- a/test/extension.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import * as assert from 'assert'; -import * as vscode from 'vscode'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as plugin from '../src/plugin'; -import * as java from '../src/javaServerStarter'; -import * as requirements from '../src/requirements'; -import { Commands } from '../src/commands'; - -suite('Java Language Extension', () => { - - test('Extension should be present', () => { - assert.ok(vscode.extensions.getExtension('redhat.java')); - }); - - test('should activate', function () { - this.timeout(1 * 60 * 1000); - return vscode.extensions.getExtension('redhat.java').activate().then((api) => { - assert.ok(true); - }); - }); - - test('should register all java commands', function () { - return vscode.commands.getCommands(true).then((commands) => - { - const JAVA_COMMANDS = [ - Commands.OPEN_OUTPUT, - Commands.SHOW_JAVA_REFERENCES, - Commands.SHOW_JAVA_IMPLEMENTATIONS, - Commands.CONFIGURATION_UPDATE, - Commands.IGNORE_INCOMPLETE_CLASSPATH, - Commands.IGNORE_INCOMPLETE_CLASSPATH_HELP, - Commands.PROJECT_CONFIGURATION_STATUS, - Commands.APPLY_WORKSPACE_EDIT, - Commands.EXECUTE_WORKSPACE_COMMAND, - Commands.OPEN_SERVER_LOG, - Commands.COMPILE_WORKSPACE, - Commands.OPEN_FORMATTER, - Commands.CLEAN_WORKSPACE, - Commands.UPDATE_SOURCE_ATTACHMENT, - Commands.ADD_TO_SOURCEPATH, - Commands.REMOVE_FROM_SOURCEPATH, - Commands.LIST_SOURCEPATHS, - Commands.OVERRIDE_METHODS_PROMPT, - Commands.HASHCODE_EQUALS_PROMPT, - Commands.OPEN_JSON_SETTINGS, - Commands.ORGANIZE_IMPORTS, - Commands.CHOOSE_IMPORTS, - Commands.GENERATE_TOSTRING_PROMPT, - Commands.GENERATE_ACCESSORS_PROMPT, - Commands.GENERATE_CONSTRUCTORS_PROMPT, - Commands.GENERATE_DELEGATE_METHODS_PROMPT, - Commands.APPLY_REFACTORING_COMMAND, - Commands.RENAME_COMMAND - ]; - const foundJavaCommands = commands.filter(function(value) { - return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.'); - }); - assert.equal(foundJavaCommands.length , JAVA_COMMANDS.length, 'Some Java commands are not registered properly or a new command is not added to the test'); - }); - }); - - test('should parse VM arguments', function () { - const userArgs = '-Xmx512m -noverify -Dfoo=\"something with blank\" '; - const vmArgs = ['-noverify', 'foo']; - - java.parseVMargs(vmArgs, userArgs); - - assert.equal(4, vmArgs.length); - assert.equal('-noverify', vmArgs[0]); - assert.equal('foo', vmArgs[1]); - assert.equal('-Xmx512m', vmArgs[2]); - assert.equal('-Dfoo=something with blank', vmArgs[3]); - }); - - test('should parse VM arguments with spaces', function () { - const userArgs = '-javaagent:"C:\\Program Files\\Java\\lombok.jar" -Xbootclasspath/a:"C:\\Program Files\\Java\\lombok.jar" -Dfoo="Some \\"crazy\\" stuff"'; - const vmArgs = []; - - java.parseVMargs(vmArgs, userArgs); - - assert.equal(vmArgs.length, 3); - assert.equal(vmArgs[0], '-javaagent:C:\\Program Files\\Java\\lombok.jar'); - assert.equal(vmArgs[1], '-Xbootclasspath/a:C:\\Program Files\\Java\\lombok.jar'); - assert.equal(vmArgs[2], '-Dfoo=Some "crazy" stuff'); - }); - - test('should collect java extensions', function () { - const packageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, '../../test/resources/packageExample.json'), 'utf8')); - const fakedExtension = { - id: 'test', - extensionPath: '', - isActive: true, - packageJSON, - exports: '', - activate: null - }; - - const extensions = [fakedExtension]; - const result = plugin.collectJavaExtensions(extensions); - assert(result.length === 1); - assert(result[0].endsWith(path.normalize('./bin/java.extend.jar'))); - }); - - test('should parse Java version', function () { - // Test boundaries - assert.equal(requirements.parseMajorVersion(null), 0); - assert.equal(requirements.parseMajorVersion(''), 0); - assert.equal(requirements.parseMajorVersion('foo'), 0); - assert.equal(requirements.parseMajorVersion('version'), 0); - assert.equal(requirements.parseMajorVersion('version ""'), 0); - assert.equal(requirements.parseMajorVersion('version "NaN"'), 0); - - // Test the real stuff - assert.equal(requirements.parseMajorVersion('version "1.7"'), 7); - assert.equal(requirements.parseMajorVersion('version "1.8.0_151"'), 8); - assert.equal(requirements.parseMajorVersion('version "9"'), 9); - assert.equal(requirements.parseMajorVersion('version "9.0.1"'), 9); - assert.equal(requirements.parseMajorVersion('version "10-ea"'), 10); - }); -}); diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index f38dc9ddd6..0000000000 --- a/test/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -// tslint:disable-next-line:no-require-imports -let testRunner = require('vscode/lib/testrunner'); - -// You can directly control Mocha options by uncommenting the following lines -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info -testRunner.configure({ - ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results -}); - -module.exports = testRunner; \ No newline at end of file diff --git a/test/lightweight-mode-suite/extension.test.ts b/test/lightweight-mode-suite/extension.test.ts new file mode 100644 index 0000000000..bb65dd02ef --- /dev/null +++ b/test/lightweight-mode-suite/extension.test.ts @@ -0,0 +1,42 @@ +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { extensions } from 'vscode'; +import { Commands } from '../../src/commands'; +import { getJavaConfiguration } from '../../src/utils'; + +suite('Java Language Extension - LightWeight', () => { + + suiteSetup(async function() { + getJavaConfiguration().update('server.launchMode', 'LightWeight'); + await extensions.getExtension('redhat.java').activate(); + }); + + test('should register syntax-only java commands', () => { + return vscode.commands.getCommands(true).then((commands) => + { + const JAVA_COMMANDS = [ + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.OPEN_SERVER_LOG, + Commands.OPEN_SERVER_STDOUT_LOG, + Commands.OPEN_SERVER_STDERR_LOG, + Commands.OPEN_CLIENT_LOG, + Commands.OPEN_LOGS, + Commands.OPEN_FORMATTER, + Commands.CLEAN_WORKSPACE, + Commands.SWITCH_SERVER_MODE, + Commands.OPEN_FILE, + Commands.CLEAN_SHARED_INDEXES, + Commands.RESTART_LANGUAGE_SERVER, + Commands.FILESEXPLORER_ONPASTE, + Commands.CHANGE_JAVA_SEARCH_SCOPE, + Commands.OPEN_JAVA_DASHBOARD, + Commands.ADD_JAVA_RUNTIME, + Commands.COPY_FULLY_QUALIFIED_NAME + ].sort(); + const foundJavaCommands = commands.filter((value) => { + return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.'); + }).sort(); + assert.deepEqual(foundJavaCommands, JAVA_COMMANDS, `Some Java commands are not registered properly or a new command is not added to the test.\nActual: ${foundJavaCommands}\nExpected: ${JAVA_COMMANDS}`); + }); + }); +}); diff --git a/test/lightweight-mode-suite/index.ts b/test/lightweight-mode-suite/index.ts new file mode 100644 index 0000000000..a32edaa0c0 --- /dev/null +++ b/test/lightweight-mode-suite/index.ts @@ -0,0 +1,57 @@ +// +// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING +// +// This file is providing the test runner to use when running extension tests. +// By default the test runner in use is Mocha based. +// +// You can provide your own test runner if you want to override it by exporting +// a function run(testRoot: string, clb: (error:Error) => void) that the extension +// host can call to run the tests. The test runner is expected to use console.log +// to report the results back to the caller. When the tests are finished, return +// a possible error to the callback or null if none. + +import * as path from 'path'; +import * as Mocha from 'mocha'; +import { glob } from 'glob'; + +export async function run(testsRoot: string): Promise { + const mocha = new Mocha({ + ui: 'tdd', + useColors: true, + timeout: 1 * 60 * 1000, /* ms*/ + }); + + try { + const files = await glob('**/**.test.js', { cwd: testsRoot }); + // make sure publicApi.test.ts is added last + files.sort((a, b) => { + if (a === 'publicApi.test.ts') { + return 1; + } + return -1; + }); + // Add files to the test suite + files.forEach(f => { + const filePath = path.resolve(testsRoot, f); + console.log("Adding file", filePath); + mocha.addFile(filePath); + }); + + return new Promise((c, e) => { + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + e(err); + } + }); + } catch (err) { + throw err; + } +} diff --git a/test/lightweight-mode-suite/publicApi.test.ts b/test/lightweight-mode-suite/publicApi.test.ts new file mode 100644 index 0000000000..3a67f7bba0 --- /dev/null +++ b/test/lightweight-mode-suite/publicApi.test.ts @@ -0,0 +1,156 @@ +'use strict'; + +import * as assert from 'assert'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import { commands, DocumentSymbol, extensions, Uri } from 'vscode'; +import { Commands } from '../../src/commands'; +import { ClasspathResult, ExtensionAPI, extensionApiVersion } from '../../src/extension.api'; +import { ServerMode } from '../../src/settings'; +import { getJavaConfiguration } from '../../src/utils'; +import { constants } from '../common'; + +const pomPath: string = path.join(constants.projectFsPath, 'pom.xml'); + +suite('Public APIs - LightWeight', () => { + + suiteSetup(async function() { + getJavaConfiguration().update('server.launchMode', 'LightWeight'); + await extensions.getExtension('redhat.java').activate(); + }); + + test('version should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.equal(api.apiVersion, extensionApiVersion); + }); + + test('requirement should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.javaRequirement); + }); + + test('status should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.equal(api.status, 'Starting'); + }); + + test('registerHoverCommand should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.registerHoverCommand); + // TODO: figure out a way to test this API + }); + + test('getDocumentSymbols should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const symbols = await api.getDocumentSymbols({ + textDocument: { + uri: Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')).toString(), + }, + }); + let symbolDetected: boolean = false; + for (const symbol of symbols) { + if (symbol.name !== 'Foo3') { + continue; + } + symbolDetected = true; + // @ts-ignore + assert.equal((symbol as DocumentSymbol).children.length, 4); + } + if (!symbolDetected) { + assert.fail('Failed to get document symbols'); + } + }); + + test('getProjectSettings should not work in lightweight mode', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const projectSetting: {} = await api.getProjectSettings( + Uri.file(constants.projectFsPath).toString(), + ['org.eclipse.jdt.core.compiler.compliance', 'org.eclipse.jdt.core.compiler.source'], + ); + assert.ok(projectSetting === undefined); + }); + + test('getClasspaths should not work in lightweight mode', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const classpathResult: ClasspathResult = await api.getClasspaths(Uri.file(constants.projectFsPath).toString(), {scope: 'runtime'}); + assert.ok(classpathResult === undefined); + }); + + test('isTestFile should not work in lightweight mode', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const isTest: boolean = await api.isTestFile(Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo.java')).toString()); + assert.ok(isTest === undefined); + }); + + test('onDidClasspathUpdate should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.onDidClasspathUpdate); + }); + + test('goToDefinition should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const definition = await api.goToDefinition({ + textDocument: { + uri: Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')).toString(), + }, + position: { + line: 17, + character: 34 + }, + }); + assert.ok(Uri.parse(definition[0].uri).fsPath, path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')); + assert.deepEqual(definition[0].range, { + start: { + character: 21, + line: 9, + }, + end: { + character: 31, + line: 9, + }, + }); + }); + + test('server mode should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.equal(api.serverMode, ServerMode.lightWeight); + }); + + test('onDidProjectsImport should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.onDidProjectsImport); + }); + + /** + * Note: This case will switch the server mode to standard. Please make sure it is run + * as the last one whenever you want to add new cases for the lightweight mode. + */ + test('onDidServerModeChange should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + let onDidChangeServerModeCount: number = 0; + + await new Promise(async (resolve) => { + + api.onDidServerModeChange((mode) => { + onDidChangeServerModeCount++; + if (onDidChangeServerModeCount === 1) { + assert.equal(mode, ServerMode.hybrid); + } else if (onDidChangeServerModeCount === 2) { + assert.equal(mode, ServerMode.standard); + return resolve(); + } + }); + + await commands.executeCommand(Commands.SWITCH_SERVER_MODE, "Standard", true/* force */); + }); + + assert.equal(onDidChangeServerModeCount, 2); + }); + + suiteTeardown(async function() { + // revert the pom content + const pomContent: string = await fse.readFile(pomPath, 'utf-8'); + await fse.writeFile(pomPath, + pomContent.replace('3.4', '3.5'), {encoding: 'utf-8'}); + }); +}); diff --git a/test/resources/packageExample.json b/test/resources/packageExample.json index d1513f1451..f392367bca 100644 --- a/test/resources/packageExample.json +++ b/test/resources/packageExample.json @@ -14,6 +14,9 @@ "contributes": { "javaExtensions": [ "./bin/java.extend.jar" + ], + "javaBuildFilePatterns": [ + "^pom.xml$", ".*\\.gradle(\\.kts)?$" ] }, "extensionDependencies": [ diff --git a/test/resources/projects/maven/salut-java11/pom.xml b/test/resources/projects/maven/salut-java11/pom.xml index e5f8453761..b57ccc6c0c 100644 --- a/test/resources/projects/maven/salut-java11/pom.xml +++ b/test/resources/projects/maven/salut-java11/pom.xml @@ -19,7 +19,7 @@ org.apache.commons commons-lang3 - 3.5 + 3.18.0 \ No newline at end of file diff --git a/test/resources/projects/maven/salut/src/main/java/java/Foo3.java b/test/resources/projects/maven/salut/src/main/java/java/Foo3.java index 7f92770e5f..0c9ee2dfc0 100644 --- a/test/resources/projects/maven/salut/src/main/java/java/Foo3.java +++ b/test/resources/projects/maven/salut/src/main/java/java/Foo3.java @@ -18,4 +18,9 @@ public void localVariable() { System.out.println(this.properties); System.out.println(util); } + + @Override + public String toString() { + return "Foo3 [properties=" + properties + "]"; + } } diff --git a/test/runtest.ts b/test/runtest.ts new file mode 100644 index 0000000000..7f264237e6 --- /dev/null +++ b/test/runtest.ts @@ -0,0 +1,66 @@ +import * as path from 'path'; +import * as fse from 'fs-extra'; +import { runTests } from '@vscode/test-electron'; + +async function main() { + const testProjectOriginPath: string = path.join(__dirname, '..', '..', 'test', 'resources', 'projects', 'maven', 'salut'); + const testProjectPath: string = path.join(__dirname, '..', '..', 'test-temp'); + const settingsJsonPath: string = path.join(testProjectPath, '.vscode', 'settings.json'); + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, '../..'); + await fse.copy(testProjectOriginPath, testProjectPath); + await fse.ensureDir(path.join(testProjectPath, '.vscode')); + + // run tests for lightweight mode + console.log("setup settings.json for lightweight mode..."); + /* eslint-disable @typescript-eslint/naming-convention */ + await fse.writeJSON(settingsJsonPath, { + "java.server.launchMode": "LightWeight", + }); + + console.log("running lightweight cases..."); + /* eslint-enable @typescript-eslint/naming-convention */ + await runTests({ + extensionDevelopmentPath, + extensionTestsPath: path.resolve(__dirname, './lightweight-mode-suite'), + launchArgs: [ + testProjectPath, + '--disable-extensions', + '--disable-workspace-trust' + ] + }); + + + // run tests for standard mode + + console.log("setup settings.json for standard mode..."); + /* eslint-disable @typescript-eslint/naming-convention */ + await fse.writeJSON(settingsJsonPath, { + "java.server.launchMode": "Standard", + "java.configuration.updateBuildConfiguration": "automatic" + }); + + console.log("running standard cases..."); + /* eslint-enable @typescript-eslint/naming-convention */ + await runTests({ + extensionDevelopmentPath, + extensionTestsPath: path.resolve(__dirname, './standard-mode-suite'), + launchArgs: [ + testProjectPath, + '--disable-extensions', + '--disable-workspace-trust' + ] + }); + + + } catch (err) { + console.error(`Failed to run tests: ${err}`); + process.exit(1); + } finally { + await fse.remove(testProjectPath); + } +} + +main(); diff --git a/test/standard-mode-suite/codeActionProvider.test.ts b/test/standard-mode-suite/codeActionProvider.test.ts new file mode 100644 index 0000000000..d856ab86ae --- /dev/null +++ b/test/standard-mode-suite/codeActionProvider.test.ts @@ -0,0 +1,60 @@ +'use strict'; + +import * as assert from 'assert'; +import * as path from 'path'; +import * as sinon from 'sinon'; +import { CodeAction, CodeActionContext, CodeActionKind, CodeActionTriggerKind, DiagnosticSeverity, ExtensionContext, Position, Range, Uri, window } from "vscode"; +import { Commands } from '../../src/commands'; +import { GradleCodeActionProvider } from '../../src/gradle/gradleCodeActionProvider'; +import { PomCodeActionProvider } from "../../src/pom/pomCodeActionProvider"; + +// tslint:disable: only-arrow-functions +const mavenProjectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'maven', 'salut'); +const gradleProjectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'gradle', 'simple-gradle'); + +suite('Code Action Provider Test', () => { + + test('Provide reload project action on demand for pom file', async function () { + const provider = sinon.createStubInstance(PomCodeActionProvider); + provider.provideCodeActions.restore(); + provider.getNewTextIndentation.restore(); + provider.collectCodeActions.restore(); + + const codeActionContext: CodeActionContext = { + triggerKind: CodeActionTriggerKind.Invoke, + diagnostics: [{ + range: new Range(new Position(0, 0), new Position(0, 0)), + message: 'The build file has been changed and may need reload to make it effective.', + severity: DiagnosticSeverity.Information, + source: 'Java' + }], + only: CodeActionKind.QuickFix + }; + const editor = await window.showTextDocument(Uri.file(path.join(mavenProjectFsPath, 'pom.xml'))); + const codeActions = provider.provideCodeActions(editor.document, null, codeActionContext, null) as CodeAction[]; + assert.equal(codeActions.length, 1); + assert.equal(codeActions[0].command.command, Commands.CONFIGURATION_UPDATE); + }); + + test('Provide reload project action on demand for gradle file', async function () { + const provider = sinon.createStubInstance(GradleCodeActionProvider); + provider.provideCodeActions.restore(); + provider.provideGradleCodeActions.restore(); + + const codeActionContext: CodeActionContext = { + triggerKind: CodeActionTriggerKind.Invoke, + diagnostics: [{ + range: new Range(new Position(0, 0), new Position(0, 0)), + message: 'The build file has been changed and may need reload to make it effective.', + severity: DiagnosticSeverity.Information, + source: 'Java' + }], + only: CodeActionKind.QuickFix + }; + const editor = await window.showTextDocument(Uri.file(path.join(gradleProjectFsPath, 'build.gradle'))); + const codeActions = (await provider.provideCodeActions(editor.document, null, codeActionContext, null)) as CodeAction[]; + assert.equal(codeActions.length, 1); + assert.equal(codeActions[0].command.command, Commands.CONFIGURATION_UPDATE); + }); + +}); diff --git a/test/standard-mode-suite/extension.test.ts b/test/standard-mode-suite/extension.test.ts new file mode 100644 index 0000000000..3b23a654ab --- /dev/null +++ b/test/standard-mode-suite/extension.test.ts @@ -0,0 +1,236 @@ +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as path from 'path'; +import { env } from 'process'; +import * as vscode from 'vscode'; +import { Commands } from '../../src/commands'; +import * as java from '../../src/javaServerStarter'; +import * as plugin from '../../src/plugin'; +import * as requirements from '../../src/requirements'; + +suite('Java Language Extension - Standard', () => { + + test('Extension should be present', () => { + assert.ok(vscode.extensions.getExtension('redhat.java')); + }); + + test('should activate', async function () { + this.timeout(60000 * 2); + const ext = vscode.extensions.getExtension('redhat.java'); + while (true) { + await new Promise(resolve => { + setTimeout(resolve, 5000); + }); + if (ext.isActive) { + break; + } + } + }); + + test('should return api after activation', function () { + return vscode.extensions.getExtension('redhat.java').activate().then((api) => { + assert.ok(!!api); + }); + }); + + test('should register all java commands', () => { + if (env['SKIP_COMMANDS_TEST'] === 'true') { + console.log('Skipping "should register all java commands"'); + return; + } + + return vscode.commands.getCommands(true).then((commands) => + { + const JAVA_COMMANDS = [ + Commands.ADD_TO_SOURCEPATH, + Commands.ADD_TO_SOURCEPATH_CMD, + Commands.APPLY_REFACTORING_COMMAND, + Commands.APPLY_WORKSPACE_EDIT, + Commands.BUILD_PROJECT, + Commands.CHANGE_BASE_TYPE, + Commands.CHOOSE_IMPORTS, + Commands.CLEAN_SHARED_INDEXES, + Commands.CLEAN_WORKSPACE, + Commands.CLIPBOARD_ONPASTE, + Commands.COMPILE_WORKSPACE, + Commands.CONFIGURATION_UPDATE, + "java.action.configureFavoriteStaticMembers", + Commands.MANUAL_CLEANUP, + Commands.CREATE_MODULE_INFO, + Commands.CREATE_MODULE_INFO_COMMAND, + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.GENERATE_ACCESSORS_PROMPT, + Commands.GENERATE_CONSTRUCTORS_PROMPT, + Commands.GENERATE_DELEGATE_METHODS_PROMPT, + Commands.GENERATE_TOSTRING_PROMPT, + Commands.GET_CLASSPATHS, + "java.project.updateClassPaths", + "java.project.updateJdk", + "java.vm.getAllInstalls", + Commands.GET_PROJECT_SETTINGS, + "java.project.updateSettings", + Commands.GET_ALL_JAVA_PROJECTS, + Commands.HANDLE_PASTE_EVENT, + Commands.HASHCODE_EQUALS_PROMPT, + Commands.IGNORE_INCOMPLETE_CLASSPATH, + Commands.IGNORE_INCOMPLETE_CLASSPATH_HELP, + Commands.IMPORT_PROJECTS, + Commands.IMPORT_PROJECTS_CMD, + Commands.CHANGE_IMPORTED_PROJECTS, + Commands.IS_TEST_FILE, + Commands.LIST_SOURCEPATHS, + Commands.LIST_SOURCEPATHS_CMD, + Commands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND, + Commands.NULL_ANALYSIS_SET_MODE, + Commands.OPEN_CLIENT_LOG, + Commands.OPEN_FORMATTER, + Commands.OPEN_JSON_SETTINGS, + Commands.OPEN_FILE, + Commands.OPEN_LOGS, + Commands.OPEN_OUTPUT, + Commands.OPEN_SERVER_LOG, + Commands.OPEN_SERVER_STDOUT_LOG, + Commands.OPEN_SERVER_STDERR_LOG, + Commands.OPEN_TYPE_HIERARCHY, + Commands.ORGANIZE_IMPORTS, + Commands.ORGANIZE_IMPORTS_SILENTLY, + Commands.OVERRIDE_METHODS_PROMPT, + Commands.PROJECT_CONFIGURATION_STATUS, + Commands.REFRESH_BUNDLES, + "java.project.refreshDiagnostics", + Commands.REMOVE_FROM_SOURCEPATH, + Commands.REMOVE_FROM_SOURCEPATH_CMD, + Commands.RENAME_COMMAND, + "java.project.resolveStackTraceLocation", + Commands.RESOLVE_TYPE_HIERARCHY, + Commands.RESOLVE_WORKSPACE_SYMBOL, + Commands.RUNTIME_VALIDATION_OPEN, + Commands.RESTART_LANGUAGE_SERVER, + Commands.SHOW_JAVA_IMPLEMENTATIONS, + Commands.SHOW_JAVA_REFERENCES, + Commands.SHOW_SERVER_TASK_STATUS, + Commands.SWITCH_SERVER_MODE, + "java.edit.stringFormatting", + "java.completion.onDidSelect", + "java.decompile", + "java.protobuf.generateSources", + Commands.SHOW_TYPE_HIERARCHY, + Commands.SHOW_SUBTYPE_HIERARCHY, + Commands.SHOW_SUPERTYPE_HIERARCHY, + Commands.SHOW_CLASS_HIERARCHY, + Commands.SHOW_EXTEND_OUTLINE, + Commands.UPGRADE_GRADLE_WRAPPER, + Commands.UPGRADE_GRADLE_WRAPPER_CMD, + Commands.UPDATE_SOURCE_ATTACHMENT, + Commands.UPDATE_SOURCE_ATTACHMENT_CMD, + Commands.SMARTSEMICOLON_DETECTION, + Commands.RESOLVE_SOURCE_ATTACHMENT, + Commands.FILESEXPLORER_ONPASTE, + Commands.RESOLVE_PASTED_TEXT, + Commands.CHANGE_JAVA_SEARCH_SCOPE, + Commands.COPY_FULLY_QUALIFIED_NAME, + Commands.GET_FULLY_QUALIFIED_NAME, + Commands.GET_TROUBLESHOOTING_INFO, + Commands.OPEN_JAVA_DASHBOARD, + Commands.ADD_JAVA_RUNTIME + ].sort(); + const foundJavaCommands = commands.filter((value) => { + return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.'); + }).sort(); + assert.deepEqual(foundJavaCommands, JAVA_COMMANDS, `Some Java commands are not registered properly or a new command is not added to the test.\nActual: ${foundJavaCommands}\nExpected: ${JAVA_COMMANDS}`); + }); + }); + + test('should parse VM arguments', () => { + const userArgs = '-Xmx512m -noverify -Dfoo=\"something with blank\" '; + const vmArgs = ['-noverify', 'foo']; + + java.parseVMargs(vmArgs, userArgs); + + assert.equal(5, vmArgs.length); + assert.equal('-noverify', vmArgs[0]); + assert.equal('foo', vmArgs[1]); + assert.equal('-Xmx512m', vmArgs[2]); + assert.equal('-Dfoo=something with blank', vmArgs[4]); + }); + + test('should parse VM arguments with spaces', () => { + const userArgs = '-javaagent:"C:\\Program Files\\Java\\lombok.jar" -Xbootclasspath/a:"C:\\Program Files\\Java\\lombok.jar" -Dfoo="Some \\"crazy\\" stuff"'; + const vmArgs = []; + + java.parseVMargs(vmArgs, userArgs); + + assert.equal(vmArgs.length, 3); + assert.equal(vmArgs[0], '-javaagent:C:\\Program Files\\Java\\lombok.jar'); + assert.equal(vmArgs[1], '-Xbootclasspath/a:C:\\Program Files\\Java\\lombok.jar'); + assert.equal(vmArgs[2], '-Dfoo=Some "crazy" stuff'); + }); + + test('should collect build file pattenrs extensions', () => { + const packageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../test/resources/packageExample.json'), 'utf8')); + const fakedExtension = { + id: 'test', + extensionUri: null, + extensionPath: '', + isActive: true, + packageJSON, + exports: '', + activate: null, + extensionKind: vscode.ExtensionKind.Workspace + }; + + const extensions = [fakedExtension]; + const result = plugin.collectBuildFilePattern(extensions); + assert(result.length === 2); + assert(result[0].endsWith("^pom.xml$")); + assert(result[1].endsWith(".*\\.gradle(\\.kts)?$")); + }); + + test('should collect java extensions', () => { + const packageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../test/resources/packageExample.json'), 'utf8')); + const fakedExtension = { + id: 'test', + extensionUri: null, + extensionPath: '', + isActive: true, + packageJSON, + exports: '', + activate: null, + extensionKind: vscode.ExtensionKind.Workspace + }; + + const extensions = [fakedExtension]; + const result = plugin.collectJavaExtensions(extensions); + assert(result.length === 1); + assert(result[0].endsWith(path.normalize('./bin/java.extend.jar'))); + }); + + test('should parse Java version', () => { + // Test boundaries + assert.equal(requirements.parseMajorVersion(null), 0); + assert.equal(requirements.parseMajorVersion(undefined), 0); + assert.equal(requirements.parseMajorVersion(''), 0); + assert.equal(requirements.parseMajorVersion('foo'), 0); + assert.equal(requirements.parseMajorVersion('version'), 0); + assert.equal(requirements.parseMajorVersion('version ""'), 0); + assert.equal(requirements.parseMajorVersion('version "NaN"'), 0); + + // Test the real stuff + assert.equal(requirements.parseMajorVersion('1.7'), 7); + assert.equal(requirements.parseMajorVersion('1.8.0_151'), 8); + assert.equal(requirements.parseMajorVersion('9'), 9); + assert.equal(requirements.parseMajorVersion('9.0.1'), 9); + assert.equal(requirements.parseMajorVersion('10-ea'), 10); + }); + + test('should detect debug flag', () => { + assert(!java.hasDebugFlag(['debug', '-debug'])); + assert(java.hasDebugFlag(['foo', '--inspect'])); + assert(java.hasDebugFlag(['foo', '--inspect=127.0.0.1:1234'])); + assert(java.hasDebugFlag(['foo', '--inspect-brk'])); + assert(java.hasDebugFlag(['foo', '--inspect-brk=127.0.0.1:1234'])); + // deprecated flags + assert(java.hasDebugFlag(['foo', '--debug=1234'])); + assert(java.hasDebugFlag(['foo', '--debug-brk=1234'])); + }); +}); diff --git a/test/standard-mode-suite/gotoSuperImplementation.test.ts b/test/standard-mode-suite/gotoSuperImplementation.test.ts new file mode 100644 index 0000000000..7d00fd5ebf --- /dev/null +++ b/test/standard-mode-suite/gotoSuperImplementation.test.ts @@ -0,0 +1,31 @@ +'use strict'; + +import * as assert from 'assert'; +import * as path from 'path'; +import { commands, extensions, Position, Selection, TextDocument, Uri, window, workspace } from 'vscode'; +import { Commands } from '../../src/commands'; +import { ExtensionAPI } from '../../src/extension.api'; + +const projectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'maven', 'salut'); +const fileFsPath: string = path.join(projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java'); + +suite('Goto Super Implementation', () => { + + suiteSetup(async function() { + const api: ExtensionAPI = await extensions.getExtension('redhat.java').activate(); + await api.serverReady(); + }); + + test('go to super implementation should work', async function () { + const document: TextDocument = await workspace.openTextDocument(Uri.file(path.join(fileFsPath))); + await window.showTextDocument(document); + window.activeTextEditor.selection = new Selection( + new Position(22, 18), + new Position(22, 18), + ); + + await commands.executeCommand(Commands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND); + + assert.equal(path.basename(window.activeTextEditor.document.fileName), "Object.java"); + }); +}); diff --git a/test/standard-mode-suite/index.ts b/test/standard-mode-suite/index.ts new file mode 100644 index 0000000000..479c5eedfd --- /dev/null +++ b/test/standard-mode-suite/index.ts @@ -0,0 +1,46 @@ +// +// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING +// +// This file is providing the test runner to use when running extension tests. +// By default the test runner in use is Mocha based. +// +// You can provide your own test runner if you want to override it by exporting +// a function run(testRoot: string, clb: (error:Error) => void) that the extension +// host can call to run the tests. The test runner is expected to use console.log +// to report the results back to the caller. When the tests are finished, return +// a possible error to the callback or null if none. + +import * as path from 'path'; +import * as Mocha from 'mocha'; +import { glob } from 'glob'; + +export async function run(testsRoot: string): Promise { + const mocha = new Mocha({ + ui: 'tdd', + useColors: true, + timeout: 1 * 60 * 1000, /* ms*/ + }); + + try { + const files = await glob('**/**.test.js', { cwd: testsRoot }); + // Add files to the test suite + files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); + + return new Promise((c, e) => { + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + e(err); + } + }); + } catch (err) { + throw err; + } +} diff --git a/test/standard-mode-suite/projects.test.ts b/test/standard-mode-suite/projects.test.ts new file mode 100644 index 0000000000..dca5196be9 --- /dev/null +++ b/test/standard-mode-suite/projects.test.ts @@ -0,0 +1,51 @@ +'use strict'; + +import * as assert from 'assert'; +import * as path from 'path'; +import * as sinon from 'sinon'; +import { Uri } from 'vscode'; +import { TextDocumentIdentifier } from 'vscode-languageclient'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { projectConfigurationUpdate } from '../../src/standardLanguageClientUtils'; + +const projectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'maven', 'salut'); + +suite('Project Operations Test', () => { + + test('Reload project by test document identifier', async function () { + const client = new LanguageClient('mock client', null, null); + const sendNotificationStub = sinon.stub(client, 'sendNotification'); + + const pomPath = path.join(projectFsPath, 'pom.xml'); + const identifier: TextDocumentIdentifier = { + uri: Uri.file(pomPath).toString(), + }; + + await projectConfigurationUpdate(client, identifier); + + assert.ok(sendNotificationStub.calledOnce); + }); + + test('Reload project by Uri instance', async function () { + const client = new LanguageClient('mock client', null, null); + const sendNotificationStub = sinon.stub(client, 'sendNotification'); + + const pomPath = path.join(projectFsPath, 'pom.xml'); + + await projectConfigurationUpdate(client, Uri.file(pomPath)); + + assert.ok(sendNotificationStub.calledOnce); + }); + + test('Reload project by Uri array', async function () { + const client = new LanguageClient('mock client', null, null); + const sendNotificationStub = sinon.stub(client, 'sendNotification'); + + const pomPath = path.join(projectFsPath, 'pom.xml'); + + await projectConfigurationUpdate(client, [Uri.file(pomPath)]); + + assert.ok(sendNotificationStub.calledOnce); + }); + +}); diff --git a/test/standard-mode-suite/publicApi.test.ts b/test/standard-mode-suite/publicApi.test.ts new file mode 100644 index 0000000000..2141aa4863 --- /dev/null +++ b/test/standard-mode-suite/publicApi.test.ts @@ -0,0 +1,180 @@ +'use strict'; + +import * as assert from 'assert'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import { env } from 'process'; +import { commands, DocumentSymbol, extensions, Uri } from 'vscode'; +import { Commands } from '../../src/commands'; +import { ClasspathResult, ExtensionAPI, extensionApiVersion } from '../../src/extension.api'; +import { ServerMode } from '../../src/settings'; +import { getJavaConfiguration } from '../../src/utils'; +import { constants } from '../common'; + +const pomPath: string = path.join(constants.projectFsPath, 'pom.xml'); +const gradleTestFolder: string = path.join(constants.projectFsPath, 'testGradle'); + +suite('Public APIs - Standard', () => { + + suiteSetup(async function() { + getJavaConfiguration().update('configuration.updateBuildConfiguration', 'automatic'); + getJavaConfiguration().update('server.launchMode', 'Standard'); + await extensions.getExtension('redhat.java').activate(); + }); + + test('version should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.equal(api.apiVersion, extensionApiVersion); + }); + + test('requirement should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.javaRequirement); + }); + + test('status should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + await api.serverReady(); + assert.equal(api.status, 'Started'); + }); + + test('registerHoverCommand should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + // TODO: To test this API, we need to import hoverProvider and trigger hoverProvider.provideHover(). + // Since the main entry is dist/extension, import hoverProvider from 'out/' won't work because of the + // different context scope. + assert.ok(api.registerHoverCommand); + }); + + test('getDocumentSymbols should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const symbols = await api.getDocumentSymbols({ + textDocument: { + uri: Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')).toString(), + }, + }); + let symbolDetected: boolean = false; + for (const symbol of symbols) { + if (symbol.name !== 'Foo3') { + continue; + } + symbolDetected = true; + // @ts-ignore + assert.equal((symbol as DocumentSymbol).children.length, 4); + } + if (!symbolDetected) { + assert.fail('Failed to get document symbols'); + } + }); + + test('getProjectSettings should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const projectSetting: {} = await api.getProjectSettings( + Uri.file(constants.projectFsPath).toString(), + ['org.eclipse.jdt.core.compiler.compliance', 'org.eclipse.jdt.core.compiler.source'], + ); + assert.equal(projectSetting['org.eclipse.jdt.core.compiler.compliance'], '1.7'); + assert.equal(projectSetting['org.eclipse.jdt.core.compiler.source'], '1.7'); + }); + + test('getClasspaths should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + let classpathResult: ClasspathResult = await api.getClasspaths(Uri.file(constants.projectFsPath).toString(), {scope: 'runtime'}); + assert.equal(classpathResult.classpaths.length, 2); + for (const classpath of classpathResult.classpaths) { + if (classpath.endsWith('test-classes')) { + assert.fail('Classpath with runtime scope should not containing tests'); + } + } + + classpathResult = await api.getClasspaths(Uri.file(constants.projectFsPath).toString(), {scope: 'test'}); + assert.equal(classpathResult.classpaths.length, 3); + }); + + test('isTestFile should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const isTest: boolean = await api.isTestFile(Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo.java')).toString()); + assert.ok(!isTest); + }); + + test('onDidClasspathUpdate should work', async function () { + if (env['SKIP_CLASSPATH_TEST'] === 'true') { + console.log('Skipping "onDidClasspathUpdate should work"'); + return; + } + const pomContent: string = await fse.readFile(pomPath, 'utf-8'); + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + + await new Promise(async (resolve) => { + api.onDidClasspathUpdate((uri) => { + assert.equal(path.relative(uri.fsPath, constants.projectFsPath), ''); + return resolve(); + }); + await fse.writeFile(pomPath, + pomContent.replace('3.5', '3.4'), {encoding: 'utf-8'}); + }); + }); + + test('goToDefinition should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + const definition = await api.goToDefinition({ + textDocument: { + uri: Uri.file(path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')).toString(), + }, + position: { + line: 17, + character: 34 + }, + }); + assert.ok(Uri.parse(definition[0].uri).fsPath, path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo3.java')); + assert.deepEqual(definition[0].range, { + start: { + character: 21, + line: 9, + }, + end: { + character: 31, + line: 9, + }, + }); + }); + + test('server mode should be correct', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.equal(api.serverMode, ServerMode.standard); + }); + + test('onDidServerModeChange should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + assert.ok(api.onDidServerModeChange); + }); + + test('onDidProjectsImport should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + + await fse.ensureDir(gradleTestFolder); + await fse.createFile(path.join(gradleTestFolder, 'build.gradle')); + + await new Promise(async (resolve) => { + api.onDidProjectsImport(() => { + return resolve(); + }); + await commands.executeCommand(Commands.IMPORT_PROJECTS_CMD); + }); + }); + + test('serverReady() should work', async function () { + const api: ExtensionAPI = extensions.getExtension('redhat.java').exports; + await api.serverReady(); + }); + + suiteTeardown(async function() { + // revert the pom content + const pomContent: string = await fse.readFile(pomPath, 'utf-8'); + await fse.writeFile(pomPath, + pomContent.replace('3.4', '3.5'), {encoding: 'utf-8'}); + + // delete the generated temp folder + await fse.remove(gradleTestFolder); + }); +}); diff --git a/test/standard-mode-suite/rename.test.ts b/test/standard-mode-suite/rename.test.ts new file mode 100644 index 0000000000..80d69ccabc --- /dev/null +++ b/test/standard-mode-suite/rename.test.ts @@ -0,0 +1,56 @@ +'use strict'; + +import * as path from 'path'; +import * as fse from "fs-extra"; +import { Uri, extensions, TextDocument, workspace, WorkspaceEdit } from 'vscode'; +import { constants } from '../common'; + +const originFilePath: string = path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo.java'); +const newFilePath: string = path.join(constants.projectFsPath, 'src', 'main', 'java', 'java', 'Foo1.java'); + +// Rename refactoring will pop up a dialog for confirm, didn't find a way to bypass it. So skip this test case. +suite.skip('Rename tests', () => { + + suiteSetup(async function() { + await extensions.getExtension('redhat.java').activate(); + }); + + test('rename on file will update the class name', async function () { + const workspaceEdit: WorkspaceEdit = new WorkspaceEdit(); + workspaceEdit.renameFile(Uri.file(originFilePath), Uri.file(newFilePath)); + await workspace.applyEdit(workspaceEdit); + + const document: TextDocument = await workspace.openTextDocument(Uri.file(path.join(newFilePath))); + // wait for the extension to update the class name, + // if it's not updated, this case will fail on timeout - 60s. + while (true) { + await sleep(5 * 1000 /* ms */); + if (document.getText().includes("public class Foo1")) { + break; + } + } + }); + + suiteTeardown(async function() { + // revert the rename changes + if (await fse.pathExists(newFilePath)) { + const workspaceEdit: WorkspaceEdit = new WorkspaceEdit(); + workspaceEdit.renameFile(Uri.file(newFilePath), Uri.file(originFilePath)); + await workspace.applyEdit(workspaceEdit); + + const document: TextDocument = await workspace.openTextDocument(Uri.file(path.join(originFilePath))); + while (true) { + await sleep(5 * 1000 /* ms */); + if (document.getText().includes("public class Foo")) { + break; + } + } + } + }); +}); + +async function sleep(ms: number): Promise { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} \ No newline at end of file diff --git a/test/standard-mode-suite/snippetCompletionProvider.test.ts b/test/standard-mode-suite/snippetCompletionProvider.test.ts new file mode 100644 index 0000000000..7e96af28c7 --- /dev/null +++ b/test/standard-mode-suite/snippetCompletionProvider.test.ts @@ -0,0 +1,14 @@ +import * as assert from 'assert'; +import { beautifyDocument } from '../../src/snippetCompletionProvider'; +import { MarkdownString } from 'vscode'; + +suite('Snippet Completion Provider', () => { + + test('should render document correctly', () => { + // /* eslint-disable prefer-arrow-callback, prefer-arrow/prefer-arrow-functions */:disable: prefer-template + const raw = "for (${1:int} ${2:i} = ${3:0}; ${2:i} < ${4:max}; ${2:i}++) {\n" + "\t$0\n" + "}"; + const markdownString: MarkdownString = beautifyDocument(raw); + const expected: string = "\n```java\n" + "for (int i = 0; i < max; i++) {\n" + "\t\n" + "}\n" + "```\n"; + assert.equal(markdownString.value, expected); + }); +}); diff --git a/test/standard-mode-suite/utils.test.ts b/test/standard-mode-suite/utils.test.ts new file mode 100644 index 0000000000..8ec72f1b8a --- /dev/null +++ b/test/standard-mode-suite/utils.test.ts @@ -0,0 +1,141 @@ +'use strict'; + +import * as assert from 'assert'; +import { getJavaConfiguration, getBuildFilePatterns, getInclusionPatternsFromNegatedExclusion, getExclusionGlob, convertToGlob } from '../../src/utils'; +import { WorkspaceConfiguration } from 'vscode'; +import { listJdks } from '../../src/jdkUtils'; +import { platform } from 'os'; + +let exclusion: string[]; +let isMavenImporterEnabled: boolean; +let isGradleImporterEnabled: boolean; + +const config: WorkspaceConfiguration = getJavaConfiguration(); +const IMPORT_EXCLUSION: string = "import.exclusions"; +const IMPORT_MAVEN_ENABLED: string = "import.maven.enabled"; +const IMPORT_GRADLE_ENABLED: string = "import.gradle.enabled"; + +suite('Utils Test', () => { + + suiteSetup(async function() { + exclusion = config.get(IMPORT_EXCLUSION, []); + isMavenImporterEnabled = config.get(IMPORT_MAVEN_ENABLED, true); + isGradleImporterEnabled = config.get(IMPORT_GRADLE_ENABLED, true); + }); + + test('getBuildFilePatterns() - Maven importer is enabled', async function () { + await config.update(IMPORT_MAVEN_ENABLED, true); + await config.update(IMPORT_GRADLE_ENABLED, false); + + const result: string[] = getBuildFilePatterns(); + + assert.deepEqual(result, ["**/pom.xml"]); + }); + + test('getBuildFilePatterns() - all importers are enabled', async function () { + await config.update(IMPORT_MAVEN_ENABLED, true); + await config.update(IMPORT_GRADLE_ENABLED, true); + + const result: string[] = getBuildFilePatterns(); + + assert.deepEqual(result, ["**/pom.xml", "**/*.gradle", "**/*.gradle.kts"]); + }); + + test('getBuildFilePatterns() - no importers is enabled', async function () { + await config.update(IMPORT_MAVEN_ENABLED, false); + await config.update(IMPORT_GRADLE_ENABLED, false); + + const result: string[] = getBuildFilePatterns(); + + assert.deepEqual(result, []); + }); + + test('getInclusionPatternsFromNegatedExclusion() - no negated exclusions', async function () { + await config.update(IMPORT_EXCLUSION, [ + "**/node_modules/**", + "**/.metadata/**", + "**/archetype-resources/**", + "**/META-INF/maven/**" + ]); + + const result: string[] = getInclusionPatternsFromNegatedExclusion(); + + assert.deepEqual(result, []); + }); + + test('getInclusionPatternsFromNegatedExclusion() - has negated exclusions', async function () { + await config.update(IMPORT_EXCLUSION, [ + "**/node_modules/**", + "!**/node_modules/test/**", + "**/.metadata/**", + "**/archetype-resources/**", + "**/META-INF/maven/**" + ]); + + const result: string[] = getInclusionPatternsFromNegatedExclusion(); + + assert.deepEqual(result, ["**/node_modules/test/**"]); + }); + + test('getExclusionGlob() - no negated exclusions', async function () { + await config.update(IMPORT_EXCLUSION, [ + "**/node_modules/**", + "**/.metadata/**", + "**/archetype-resources/**", + "**/META-INF/maven/**" + ]); + + const result: string = getExclusionGlob(); + + assert.equal(result, "{**/node_modules/**,**/.metadata/**,**/archetype-resources/**,**/META-INF/maven/**}"); + }); + + test('getExclusionGlob() - has negated exclusions', async function () { + await config.update(IMPORT_EXCLUSION, [ + "**/node_modules/**", + "!**/node_modules/test/**", + "**/.metadata/**", + "**/archetype-resources/**", + "**/META-INF/maven/**" + ]); + + const result: string = getExclusionGlob(); + + assert.equal(result, "{**/node_modules/**,**/.metadata/**,**/archetype-resources/**,**/META-INF/maven/**}"); + }); + + test('convertToGlob() - no file patterns', async function () { + const result: string = convertToGlob([]); + assert.equal(result, ""); + }); + + test('convertToGlob() - no base patterns', async function () { + const result: string = convertToGlob(["**/pom.xml", "**/build.gradle"]); + assert.equal(result, "{**/pom.xml,**/build.gradle}"); + }); + + test('convertToGlob() - has base patterns', async function () { + const result: string = convertToGlob(["**/pom.xml"], ["**/node_modules/test/**"]); + assert.equal(result, "{**/node_modules/test/**/**/pom.xml}"); + }); + + test('listJdks() - no /usr as Java home on macOS', async function () { + // Skip this test if it's not macOS. + if (platform() !== "darwin") { + this.skip(); + } + + const jdks = await listJdks(); + assert.ok(jdks.every(jdk => jdk.homedir !== "/usr")); + }); + + teardown(async function() { + await recover(); + }); +}); + +async function recover(): Promise { + await config.update(IMPORT_EXCLUSION, exclusion); + await config.update(IMPORT_MAVEN_ENABLED, isMavenImporterEnabled); + await config.update(IMPORT_GRADLE_ENABLED, isGradleImporterEnabled); +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000000..17c7bc77a7 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es6", + "moduleResolution": "node", + "outDir": "out", + "sourceMap": true, + "skipLibCheck": true, + "plugins": [ + { + "name": "eslint" + } + ], + } +} diff --git a/tsconfig.json b/tsconfig.json index e3f76fb10c..6b133b6278 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,16 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "target": "es6", "lib": [ - "es6" - ], + "es6" + ], "module": "commonjs", - "moduleResolution": "node", - "outDir": "out", - "sourceMap": true, - "plugins": [{ "name": "typescript-tslint-plugin" }] }, "exclude": [ "node_modules", "server", - ".vscode-test" + ".vscode-test", + "src/webview", + "test/resources/projects" ] } diff --git a/tsconfig.webview.json b/tsconfig.webview.json new file mode 100644 index 0000000000..0c78cb638e --- /dev/null +++ b/tsconfig.webview.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "lib": [ + "DOM", "ES6" + ], + "module": "ES6", + /* Enabled for React */ + "jsx": "react-jsx", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + }, + "include": [ + "src/webview", + "src/webviewProtocol" + ] +} diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 7898c21829..0000000000 --- a/tslint.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "rules": { - "encoding": true, - "only-arrow-functions": [ - true, "allow-declarations", "allow-named-functions" - ], - "no-var-keyword": true, - "object-literal-key-quotes": [ - true, "as-needed" - ], - "comment-format": [true, "check-space"], - "curly": [true, "ignore-same-line"], - "triple-equals": true, - "prefer-const": true, - "prefer-for-of": true, - "variable-name": [ - true, - "allow-leading-underscore", - "allow-pascal-case", - "ban-keywords", - "check-format" - ], - "switch-final-break": [true, "always"], - "prefer-template": [true, "allow-single-concat"], - "semicolon": [true, "always"], - "no-consecutive-blank-lines": true, - "no-boolean-literal-compare": true, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-module", - "check-separator", - "check-type", - "check-preblock" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" - } - ], - "no-trailing-whitespace": true, - "no-debugger": true - } -} diff --git a/vscode.proposed.documentPaste.d.ts b/vscode.proposed.documentPaste.d.ts new file mode 100644 index 0000000000..627c8dcc1c --- /dev/null +++ b/vscode.proposed.documentPaste.d.ts @@ -0,0 +1,196 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/30066/ + + /** + * The reason why paste edits were requested. + */ + export enum DocumentPasteTriggerKind { + /** + * Pasting was requested as part of a normal paste operation. + */ + Automatic = 0, + + /** + * Pasting was requested by the user with the `paste as` command. + */ + PasteAs = 1, + } + + /** + * Additional information about the paste operation. + */ + + export interface DocumentPasteEditContext { + /** + * Requested kind of paste edits to return. + */ + readonly only: DocumentPasteEditKind | undefined; + + /** + * The reason why paste edits were requested. + */ + readonly triggerKind: DocumentPasteTriggerKind; + } + + /** + * Provider invoked when the user copies or pastes in a {@linkcode TextDocument}. + */ + interface DocumentPasteEditProvider { + + /** + * Optional method invoked after the user copies text in a file. + * + * This allows the provider to attach copy metadata to the {@link DataTransfer} + * which is then passed back to providers in {@linkcode provideDocumentPasteEdits}. + * + * Note that currently any changes to the {@linkcode DataTransfer} are isolated to the current editor session. + * This means that added metadata cannot be seen by other applications. + * + * @param document Document where the copy took place. + * @param ranges Ranges being copied in {@linkcode document}. + * @param dataTransfer The data transfer associated with the copy. You can store additional values on this for later use in {@linkcode provideDocumentPasteEdits}. + * This object is only valid for the duration of this method. + * @param token A cancellation token. + * + * @return Optional thenable that resolves when all changes to the `dataTransfer` are complete. + */ + prepareDocumentPaste?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, token: CancellationToken): void | Thenable; + + /** + * Invoked before the user pastes into a document. + * + * Returned edits can replace the standard pasting behavior. + * + * @param document Document being pasted into + * @param ranges Range in the {@linkcode document} to paste into. + * @param dataTransfer The {@link DataTransfer data transfer} associated with the paste. This object is only valid for the duration of the paste operation. + * @param context Additional context for the paste. + * @param token A cancellation token. + * + * @return Set of potential {@link DocumentPasteEdit edits} that apply the paste. Return `undefined` to use standard pasting. + */ + provideDocumentPasteEdits?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, context: DocumentPasteEditContext, token: CancellationToken): ProviderResult; + + /** + * Optional method which fills in the {@linkcode DocumentPasteEdit.additionalEdit} before the edit is applied. + * + * This is called once per edit and should be used if generating the complete edit may take a long time. + * Resolve can only be used to change {@link DocumentPasteEdit.additionalEdit}. + * + * @param pasteEdit The {@linkcode DocumentPasteEdit} to resolve. + * @param token A cancellation token. + * + * @returns The resolved paste edit or a thenable that resolves to such. It is OK to return the given + * `pasteEdit`. If no result is returned, the given `pasteEdit` is used. + */ + resolveDocumentPasteEdit?(pasteEdit: T, token: CancellationToken): ProviderResult; + } + + /** + * An edit applied on paste. + */ + class DocumentPasteEdit { + + /** + * Human readable label that describes the edit. + */ + title: string; + + /** + * {@link DocumentPasteEditKind Kind} of the edit. + * + * Used to identify specific types of edits. + */ + kind: DocumentPasteEditKind; + + /** + * The text or snippet to insert at the pasted locations. + */ + insertText: string | SnippetString; + + /** + * An optional additional edit to apply on paste. + */ + additionalEdit?: WorkspaceEdit; + + /** + * Controls the ordering of paste edits provided by multiple providers. + * + * If this edit yields to another, it will be shown lower in the list of paste edit. + */ + yieldTo?: readonly DocumentPasteEditKind[]; + + /** + * Create a new paste edit. + * + * @param insertText The text or snippet to insert at the pasted locations. + * @param title Human readable label that describes the edit. + * @param kind {@link DocumentPasteEditKind Kind} of the edit. + */ + constructor(insertText: string | SnippetString, title: string, kind: DocumentPasteEditKind); + } + + + /** + * TODO: Share with code action kind? + */ + class DocumentPasteEditKind { + static readonly Empty: DocumentPasteEditKind; + + // TODO: Add `Text` any others? + + private constructor(value: string); + + readonly value: string; + + append(...parts: string[]): CodeActionKind; + intersects(other: CodeActionKind): boolean; + contains(other: CodeActionKind): boolean; + } + + interface DocumentPasteProviderMetadata { + /** + * List of {@link DocumentPasteEditKind kinds} that the provider may return in {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits}. + * + * The provider will only be invoked when one of these kinds is being requested. For normal pasting, all providers will be invoked. + */ + readonly providedPasteEditKinds: readonly DocumentPasteEditKind[]; + + /** + * Mime types that {@linkcode DocumentPasteEditProvider.prepareDocumentPaste prepareDocumentPaste} may add on copy. + */ + readonly copyMimeTypes?: readonly string[]; + + /** + * Mime types that {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits} should be invoked for. + * + * This can either be an exact mime type such as `image/png`, or a wildcard pattern such as `image/*`. + * + * Use `text/uri-list` for resources dropped from the explorer or other tree views in the workbench. + * + * Use `files` to indicate that the provider should be invoked if any {@link DataTransferFile files} are present in the {@linkcode DataTransfer}. + * Note that {@linkcode DataTransferFile} entries are only created when dropping content from outside the editor, such as + * from the operating system. + */ + readonly pasteMimeTypes?: readonly string[]; + } + + namespace languages { + /** + * Registers a new {@linkcode DocumentPasteEditProvider}. + * + * @param selector A selector that defines the documents this provider applies to. + * @param provider A paste editor provider. + * @param metadata Additional metadata about the provider. + * + * @returns A {@link Disposable} that unregisters this provider when disposed of. + */ + export function registerDocumentPasteEditProvider(selector: DocumentSelector, provider: DocumentPasteEditProvider, metadata: DocumentPasteProviderMetadata): Disposable; + } +} diff --git a/webpack.config.js b/webpack.config.js index 733da6f21f..ae13213241 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,37 +2,148 @@ // Licensed under the MIT license. //@ts-check +const ESLintWebpackPlugin = require('eslint-webpack-plugin'); +const webpack = require('webpack'); const path = require('path'); /**@type {import('webpack').Configuration}*/ const config = { - target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ - node: { - __dirname: false, - __filename: false, - }, - entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ - output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ - path: path.resolve(__dirname, 'dist'), - filename: 'extension.js', - libraryTarget: "commonjs2", - devtoolModuleFilenameTemplate: "../[resource-path]", - }, - externals: { - vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ - }, - devtool: 'source-map', - resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader - extensions: ['.ts', '.js'], - }, - module: { - rules: [{ - test: /\.ts$/, - exclude: /node_modules/, - use: [{ - loader: 'ts-loader', - }] - }] - }, + watchOptions: { + ignored: /node_modules/ + }, + target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ + node: { + __dirname: false, + __filename: false, + }, + entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ + output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ + path: path.resolve(__dirname, 'dist'), + filename: 'extension.js', + libraryTarget: "commonjs2", + devtoolModuleFilenameTemplate: "../[resource-path]", + }, + externals: { + vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ + fsevents: "require('fsevents')", // https://github.com/yan-foto/electron-reload/issues/71#issuecomment-588988382 + }, + devtool: 'source-map', + resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader + extensions: ['.ts', '.js'], + }, + module: { + rules: [{ + test: /\.ts$/, + exclude: /node_modules/, + use: [{ + loader: 'ts-loader', + }] + }] + }, + plugins: [ + new ESLintWebpackPlugin({ + extensions: [ + ".ts", + ".js" + ] + }) + ], + infrastructureLogging: { + level: 'log', + }, } -module.exports = config; + +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); + +const configChangeSignature = { + name: 'changeSignature', + mode: 'none', + entry: { + changeSignature: './src/webview/changeSignature/index.tsx', + }, + module: { + rules: [{ + test: /\.ts(x?)$/, + exclude: /node_modules/, + loader: 'ts-loader', + options: { + configFile: 'tsconfig.webview.json' + } + }, { + test: /\.(css)$/, + use: [{ + loader: MiniCssExtractPlugin.loader, + }, { + loader: 'css-loader' + }] + }, { + test: /\.(ttf)$/, + type: 'asset/inline', + }] + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'dist'), + publicPath: '/', + devtoolModuleFilenameTemplate: "../[resource-path]" + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: 'changeSignature.css' + }), + new webpack.ProvidePlugin({ + process: 'process/browser', + }), + ], + devtool: 'source-map', + resolve: { + extensions: ['.js', '.ts', '.tsx'] + } +} + +const configDashboard = { + name: 'dashboard', + mode: 'none', + entry: { + dashboard: './src/webview/dashboard/index.tsx', + }, + module: { + rules: [{ + test: /\.ts(x?)$/, + exclude: /node_modules/, + loader: 'ts-loader', + options: { + configFile: 'tsconfig.webview.json' + } + }, { + test: /\.(css)$/, + use: [{ + loader: MiniCssExtractPlugin.loader, + }, { + loader: 'css-loader' + }] + }, { + test: /\.(ttf)$/, + type: 'asset/inline', + }] + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'dist'), + publicPath: '/', + devtoolModuleFilenameTemplate: "../[resource-path]" + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: 'dashboard.css' + }), + new webpack.ProvidePlugin({ + process: 'process/browser', + }), + ], + devtool: 'source-map', + resolve: { + extensions: ['.js', '.ts', '.tsx'] + } +} +module.exports = [config, configChangeSignature, configDashboard]; diff --git a/webview-resources/button.css b/webview-resources/button.css new file mode 100644 index 0000000000..54e437988d --- /dev/null +++ b/webview-resources/button.css @@ -0,0 +1,34 @@ +/* https://css-tricks.com/overriding-default-button-styles/ */ + +button { + display: inline-block; + border: none; + padding: 12px 16px; + margin: 0; + text-decoration: none; + background: var(--vscode-button-background); + color: #ffffff; + font-family: sans-serif; + font-size: 14px; + cursor: pointer; + text-align: center; +} + +button:hover, +button:focus { + background: var(--vscode-button-hoverBackground); +} +button:focus { + outline: 1px solid var(--vscode-button-hoverBackground); + /* outline-offset: -4px; */ +} + +.center { + text-align: center; + margin: 0; + position: absolute; + top: 50%; + left: 50%; + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} \ No newline at end of file diff --git a/webview-resources/dashboard.css b/webview-resources/dashboard.css new file mode 100644 index 0000000000..bbe7b64244 --- /dev/null +++ b/webview-resources/dashboard.css @@ -0,0 +1,13 @@ +.title { + font-weight: bold; + font-size: large; +}; + +.label { + font-weight: bold; + width: 30%; +}; + +.row { + width: 100%; +}; \ No newline at end of file diff --git a/webview-resources/document.css b/webview-resources/document.css new file mode 100644 index 0000000000..316f8642ab --- /dev/null +++ b/webview-resources/document.css @@ -0,0 +1,19 @@ +.btn { + border: 0; + color: var(--vscode-button-foreground); + background-color: var(--vscode-button-background); +} + +.btn svg { + fill: var(--vscode-button-foreground); +} + +.btn:hover { + background-color: var(--vscode-button-hoverBackground); +} + +.floating-bottom-right { + position: fixed; + bottom: 1rem; + right: 1rem; +} \ No newline at end of file diff --git a/webview-resources/highlight.css b/webview-resources/highlight.css new file mode 100644 index 0000000000..8744f24604 --- /dev/null +++ b/webview-resources/highlight.css @@ -0,0 +1,191 @@ +/* +https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs2015.css +*/ +/* + * Visual Studio 2015 dark style + * Author: Nicolas LLOBERA + */ + + + .hljs-keyword, + .hljs-literal, + .hljs-symbol, + .hljs-name { + color: #569CD6; + } + .hljs-link { + color: #569CD6; + text-decoration: underline; + } + + .hljs-built_in, + .hljs-type { + color: #4EC9B0; + } + + .hljs-number, + .hljs-class { + color: #B8D7A3; + } + + .hljs-string, + .hljs-meta-string { + color: #D69D85; + } + + .hljs-regexp, + .hljs-template-tag { + color: #9A5334; + } + + .hljs-subst, + .hljs-function, + .hljs-title, + .hljs-params, + .hljs-formula { + color: #DCDCDC; + } + + .hljs-comment, + .hljs-quote { + color: #57A64A; + font-style: italic; + } + + .hljs-doctag { + color: #608B4E; + } + + .hljs-meta, + .hljs-meta-keyword, + .hljs-tag { + color: #9B9B9B; + } + + .hljs-variable, + .hljs-template-variable { + color: #BD63C5; + } + + .hljs-attr, + .hljs-attribute, + .hljs-builtin-name { + color: #9CDCFE; + } + + .hljs-section { + color: gold; + } + + .hljs-emphasis { + font-style: italic; + } + + .hljs-strong { + font-weight: bold; + } + + /*.hljs-code { + font-family:'Monospace'; + }*/ + + .hljs-bullet, + .hljs-selector-tag, + .hljs-selector-id, + .hljs-selector-class, + .hljs-selector-attr, + .hljs-selector-pseudo { + color: #D7BA7D; + } + + .hljs-addition { + background-color: var(--vscode-diffEditor-insertedTextBackground, rgba(155, 185, 85, 0.2)); + color: rgb(155, 185, 85); + display: inline-block; + width: 100%; + } + + .hljs-deletion { + background: var(--vscode-diffEditor-removedTextBackground, rgba(255, 0, 0, 0.2)); + color: rgb(255, 0, 0); + display: inline-block; + width: 100%; + } + + + /* + From https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs.css + */ + /* + + Visual Studio-like style based on original C# coloring by Jason Diamond + + */ + + .vscode-light .hljs-function, + .vscode-light .hljs-params, + .vscode-light .hljs-number, + .vscode-light .hljs-class { + color: inherit; + } + + .vscode-light .hljs-comment, + .vscode-light .hljs-quote, + .vscode-light .hljs-number, + .vscode-light .hljs-class, + .vscode-light .hljs-variable { + color: #008000; + } + + .vscode-light .hljs-keyword, + .vscode-light .hljs-selector-tag, + .vscode-light .hljs-name, + .vscode-light .hljs-tag { + color: #00f; + } + + .vscode-light .hljs-built_in, + .vscode-light .hljs-builtin-name { + color: #007acc; + } + + .vscode-light .hljs-string, + .vscode-light .hljs-section, + .vscode-light .hljs-attribute, + .vscode-light .hljs-literal, + .vscode-light .hljs-template-tag, + .vscode-light .hljs-template-variable, + .vscode-light .hljs-type { + color: #a31515; + } + + .vscode-light .hljs-selector-attr, + .vscode-light .hljs-selector-pseudo, + .vscode-light .hljs-meta, + .vscode-light .hljs-meta-keyword { + color: #2b91af; + } + + .vscode-light .hljs-title, + .vscode-light .hljs-doctag { + color: #808080; + } + + .vscode-light .hljs-attr { + color: #f00; + } + + .vscode-light .hljs-symbol, + .vscode-light .hljs-bullet, + .vscode-light .hljs-link { + color: #00b0e8; + } + + + .vscode-light .hljs-emphasis { + font-style: italic; + } + + .vscode-light .hljs-strong { + font-weight: bold; + } \ No newline at end of file diff --git a/webview-resources/markdown.css b/webview-resources/markdown.css new file mode 100644 index 0000000000..b9a106931c --- /dev/null +++ b/webview-resources/markdown.css @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +/*https://raw.githubusercontent.com/microsoft/vscode/master/extensions/markdown-language-features/media/markdown.css*/ + + html, body { + font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif); + font-size: var(--vscode-markdown-font-size, 14px); + padding: 0 26px; + line-height: var(--vscode-markdown-line-height, 22px); + word-wrap: break-word; +} + +#code-csp-warning { + position: fixed; + top: 0; + right: 0; + color: white; + margin: 16px; + text-align: center; + font-size: 12px; + font-family: sans-serif; + background-color:#444444; + cursor: pointer; + padding: 6px; + box-shadow: 1px 1px 1px rgba(0,0,0,.25); +} + +#code-csp-warning:hover { + text-decoration: none; + background-color:#007acc; + box-shadow: 2px 2px 2px rgba(0,0,0,.25); +} + +body.scrollBeyondLastLine { + margin-bottom: calc(100vh - 22px); +} + +body.showEditorSelection .code-line { + position: relative; +} + +body.showEditorSelection .code-active-line:before, +body.showEditorSelection .code-line:hover:before { + content: ""; + display: block; + position: absolute; + top: 0; + left: -12px; + height: 100%; +} + +body.showEditorSelection li.code-active-line:before, +body.showEditorSelection li.code-line:hover:before { + left: -30px; +} + +.vscode-light.showEditorSelection .code-active-line:before { + border-left: 3px solid rgba(0, 0, 0, 0.15); +} + +.vscode-light.showEditorSelection .code-line:hover:before { + border-left: 3px solid rgba(0, 0, 0, 0.40); +} + +.vscode-light.showEditorSelection .code-line .code-line:hover:before { + border-left: none; +} + +.vscode-dark.showEditorSelection .code-active-line:before { + border-left: 3px solid rgba(255, 255, 255, 0.4); +} + +.vscode-dark.showEditorSelection .code-line:hover:before { + border-left: 3px solid rgba(255, 255, 255, 0.60); +} + +.vscode-dark.showEditorSelection .code-line .code-line:hover:before { + border-left: none; +} + +.vscode-high-contrast.showEditorSelection .code-active-line:before { + border-left: 3px solid rgba(255, 160, 0, 0.7); +} + +.vscode-high-contrast.showEditorSelection .code-line:hover:before { + border-left: 3px solid rgba(255, 160, 0, 1); +} + +.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before { + border-left: none; +} + +img { + max-width: 100%; + max-height: 100%; +} + +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:focus, +input:focus, +select:focus, +textarea:focus { + outline: 1px solid -webkit-focus-ring-color; + outline-offset: -1px; +} + +hr { + border: 0; + height: 2px; + border-bottom: 2px solid; +} + +h1 { + padding-bottom: 0.3em; + line-height: 1.2; + border-bottom-width: 1px; + border-bottom-style: solid; +} + +h1, h2, h3 { + font-weight: normal; +} + +table { + border-collapse: collapse; +} + +table > thead > tr > th { + text-align: left; + border-bottom: 1px solid; +} + +table > thead > tr > th, +table > thead > tr > td, +table > tbody > tr > th, +table > tbody > tr > td { + padding: 5px 10px; +} + +table > tbody > tr + tr > td { + border-top: 1px solid; +} + +blockquote { + margin: 0 7px 0 5px; + padding: 0 16px 0 10px; + border-left-width: 5px; + border-left-style: solid; +} + +code { + font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"; + font-size: 1em; + line-height: 1.357em; +} + +body.wordWrap pre { + white-space: pre-wrap; +} + +pre:not(.hljs), +pre.hljs code > div { + padding: 16px; + border-radius: 3px; + overflow: auto; +} + +pre code { + color: var(--vscode-editor-foreground); + tab-size: 4; +} + +/** Theming */ + +.vscode-light pre { + background-color: rgba(220, 220, 220, 0.4); +} + +.vscode-dark pre { + background-color: rgba(10, 10, 10, 0.4); +} + +.vscode-high-contrast pre { + background-color: rgb(0, 0, 0); +} + +.vscode-high-contrast h1 { + border-color: rgb(0, 0, 0); +} + +.vscode-light table > thead > tr > th { + border-color: rgba(0, 0, 0, 0.69); +} + +.vscode-dark table > thead > tr > th { + border-color: rgba(255, 255, 255, 0.69); +} + +.vscode-light h1, +.vscode-light hr, +.vscode-light table > tbody > tr + tr > td { + border-color: rgba(0, 0, 0, 0.18); +} + +.vscode-dark h1, +.vscode-dark hr, +.vscode-dark table > tbody > tr + tr > td { + border-color: rgba(255, 255, 255, 0.18); +} \ No newline at end of file