diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml new file mode 100644 index 00000000..7602a73e --- /dev/null +++ b/.azure-pipelines/ci.yml @@ -0,0 +1,70 @@ +name: $(Date:yyyyMMdd).$(Rev:r) +variables: + - name: Codeql.Enabled + value: true +resources: + repositories: + - repository: self + type: git + ref: refs/heads/main + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +trigger: + branches: + include: + - main +extends: + template: v1/1ES.Unofficial.PipelineTemplate.yml@1esPipelines + parameters: + pool: + os: linux + name: 1ES_JavaTooling_Pool + image: 1ES_JavaTooling_Ubuntu-2004 + sdl: + sourceAnalysisPool: + name: 1ES_JavaTooling_Pool + image: 1ES_JavaTooling_Windows_2022 + os: windows + customBuildTags: + - MigrationTooling-mseng-VSJava-9181-Tool + stages: + - stage: Build + jobs: + - job: Job_1 + displayName: VSCode-Java-Debug-CI + templateContext: + outputs: + - output: pipelineArtifact + artifactName: vsix + targetPath: $(Build.ArtifactStagingDirectory)/vsix + displayName: "Publish Artifact: vsix" + steps: + - checkout: self + fetchTags: true + - task: JavaToolInstaller@0 + displayName: Use Java 17 + inputs: + versionSpec: "17" + jdkArchitectureOption: x64 + jdkSourceOption: PreInstalled + - task: Npm@1 + displayName: npm install + inputs: + verbose: false + - task: CmdLine@2 + displayName: build server + inputs: + script: |- + git clone https://github.com/microsoft/java-debug ../java-debug + npm run build-server + - task: CmdLine@2 + displayName: vsce package + inputs: + script: npx @vscode/vsce@latest package + - task: CopyFiles@2 + displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)/vsix" + inputs: + Contents: "*.vsix" + TargetFolder: $(Build.ArtifactStagingDirectory)/vsix diff --git a/.azure-pipelines/nightly.yml b/.azure-pipelines/nightly.yml new file mode 100644 index 00000000..c3bde437 --- /dev/null +++ b/.azure-pipelines/nightly.yml @@ -0,0 +1,125 @@ +name: $(Date:yyyyMMdd).$(Rev:r) +variables: + - name: Codeql.Enabled + value: true +schedules: + - cron: 0 7 * * 1,2,3,4,5 + branches: + include: + - refs/heads/main +resources: + pipelines: + - pipeline: microsoft.java-debug.signjars.nightly + source: microsoft.java-debug.signjars.nightly + trigger: + branches: + include: + - refs/heads/main + repositories: + - repository: self + type: git + ref: refs/heads/main + - repository: CustomPipelineTemplates + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release +trigger: none +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@CustomPipelineTemplates + parameters: + pool: + name: VSEng-MicroBuildVSStable + stages: + - stage: Build + jobs: + - job: Job_1 + displayName: VSCode-Java-Debug-Nightly + templateContext: + mb: + signing: + enabled: true + signType: real + signWithProd: true + zipSources: false + feedSource: 'https://mseng.pkgs.visualstudio.com/DefaultCollection/_packaging/MicroBuildToolset/nuget/v3/index.json' + outputs: + - output: pipelineArtifact + artifactName: vsix + targetPath: $(Build.ArtifactStagingDirectory)/vsix + displayName: "Publish Artifact: vsix" + steps: + - checkout: self + fetchTags: false + - task: NodeTool@0 + displayName: Use Node 20.x + inputs: + versionSpec: 20.x + - task: DownloadBuildArtifacts@1 + displayName: Download Build Artifacts + inputs: + buildType: specific + project: a4d27ce2-a42d-4b71-8eef-78cee9a9728e + definition: "16485" + specificBuildWithTriggering: true + downloadType: specific + itemPattern: plugin/jars/com.microsoft.java.debug.plugin-*.jar + extractTars: false + - task: CopyFiles@2 + displayName: 'cp plugin.jar to server' + inputs: + SourceFolder: '$(System.ArtifactsDirectory)/plugin/jars' + Contents: 'com.microsoft.java.debug.plugin-*.jar' + TargetFolder: $(Build.SourcesDirectory)/server + - task: Npm@1 + displayName: npm install + inputs: + verbose: false + - task: CmdLine@2 + displayName: Update nightly vsix version + inputs: + script: node scripts/build/prepare-nightly-build.js + - task: CmdLine@2 + displayName: Replace AI key + inputs: + script: npx json@9.0.6 -I -f package.json -e "this.aiKey=\"%AI_KEY%\"" + - task: CmdLine@2 + displayName: vsce package --pre-release -o extension.vsix + inputs: + script: npx @vscode/vsce@latest package --pre-release -o extension.vsix + ### Copy files for APIScan + - task: CopyFiles@2 + displayName: "Copy Files for APIScan" + inputs: + Contents: "*.vsix" + TargetFolder: $(Agent.TempDirectory)/APIScanFiles + condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) + ### Run latest version of APIScan listed at https://www.1eswiki.com/wiki/APIScan_Build_Task + - task: APIScan@2 + displayName: Run APIScan + inputs: + softwareFolder: $(Agent.TempDirectory)/APIScanFiles + softwareName: "vscode-java-debug" + softwareVersionNum: "$(Build.BuildId)" + isLargeApp: false + toolVersion: "Latest" + condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) + env: + AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret) + - script: npx @vscode/vsce@latest generate-manifest -i extension.vsix -o extension.manifest + displayName: 'Generate extension manifest' + - script: copy extension.manifest extension.signature.p7s + displayName: 'Prepare manifest for signing' + - task: CmdLine@2 + displayName: Sign extension + inputs: + script: dotnet %MBSIGN_APPFOLDER%/ddsignfiles.dll /file:extension.signature.p7s /certs:4014052 + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + - task: CopyFiles@2 + displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)/vsix" + inputs: + Contents: | + extension.vsix + extension.manifest + extension.signature.p7s + TargetFolder: $(Build.ArtifactStagingDirectory)/vsix \ No newline at end of file diff --git a/.azure-pipelines/rc.yml b/.azure-pipelines/rc.yml new file mode 100644 index 00000000..38c0c188 --- /dev/null +++ b/.azure-pipelines/rc.yml @@ -0,0 +1,123 @@ +name: $(Date:yyyyMMdd).$(Rev:r) +variables: + - name: Codeql.Enabled + value: true +resources: + pipelines: + - pipeline: microsoft.java-debug.signjars.rc + source: microsoft.java-debug.signjars.rc + trigger: + branches: + include: + - main + repositories: + - repository: self + type: git + ref: refs/heads/main + - repository: CustomPipelineTemplates + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release +trigger: none +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@CustomPipelineTemplates + parameters: + pool: + name: VSEng-MicroBuildVSStable + stages: + - stage: Build + jobs: + - job: Job_1 + displayName: VSCode-Java-Debug-RC + templateContext: + mb: + signing: + enabled: true + signType: real + signWithProd: true + zipSources: false + feedSource: 'https://mseng.pkgs.visualstudio.com/DefaultCollection/_packaging/MicroBuildToolset/nuget/v3/index.json' + outputs: + - output: pipelineArtifact + artifactName: vsix + targetPath: $(Build.ArtifactStagingDirectory)/vsix + displayName: "Publish Artifact: vsix" + steps: + - checkout: self + fetchTags: true + - task: NodeTool@0 + displayName: Use Node 20.x + inputs: + versionSpec: 20.x + - task: DownloadBuildArtifacts@1 + displayName: Download Build Artifacts + inputs: + buildType: specific + project: a4d27ce2-a42d-4b71-8eef-78cee9a9728e + definition: "16486" + specificBuildWithTriggering: true + downloadType: specific + itemPattern: m2/com.microsoft.java.debug.plugin/com.microsoft.java.debug.plugin-*.jar + extractTars: false + - task: CopyFiles@2 + displayName: 'cp plugin.jar to server' + inputs: + SourceFolder: '$(System.ArtifactsDirectory)/m2/com.microsoft.java.debug.plugin' + Contents: | + com.microsoft.java.debug.plugin-*.jar + TargetFolder: $(Build.SourcesDirectory)/server + - task: CmdLine@2 + displayName: Delete sources.jar and javadoc.jar from server + inputs: + script: | + del server\com.microsoft.java.debug.plugin-*-sources.jar + del server\com.microsoft.java.debug.plugin-*-javadoc.jar + - task: Npm@1 + displayName: npm install + inputs: + verbose: false + - task: CmdLine@2 + displayName: Replace AI key + inputs: + script: npx json@9.0.6 -I -f package.json -e "this.aiKey=\"%AI_KEY%\"" + - task: CmdLine@2 + displayName: vsce package + inputs: + script: npx @vscode/vsce@latest package -o extension.vsix + ### Copy files for APIScan + - task: CopyFiles@2 + displayName: "Copy Files for APIScan" + inputs: + Contents: "*.vsix" + TargetFolder: $(Agent.TempDirectory)/APIScanFiles + condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) + ### Run latest version of APIScan listed at https://www.1eswiki.com/wiki/APIScan_Build_Task + - task: APIScan@2 + displayName: Run APIScan + inputs: + softwareFolder: $(Agent.TempDirectory)/APIScanFiles + softwareName: "vscode-java-debug" + softwareVersionNum: "$(Build.BuildId)" + isLargeApp: false + toolVersion: "Latest" + condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) + env: + AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret) + - script: npx @vscode/vsce@latest generate-manifest -i extension.vsix -o extension.manifest + displayName: 'Generate extension manifest' + - script: copy extension.manifest extension.signature.p7s + displayName: 'Prepare manifest for signing' + - task: CmdLine@2 + displayName: Sign extension + inputs: + script: dotnet %MBSIGN_APPFOLDER%/ddsignfiles.dll /file:extension.signature.p7s /certs:4014052 + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + - task: CopyFiles@2 + displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)/vsix" + inputs: + Contents: | + extension.vsix + extension.manifest + extension.signature.p7s + TargetFolder: $(Build.ArtifactStagingDirectory)/vsix diff --git a/.azure-pipelines/release-nightly.yml b/.azure-pipelines/release-nightly.yml new file mode 100644 index 00000000..119d9e1f --- /dev/null +++ b/.azure-pipelines/release-nightly.yml @@ -0,0 +1,55 @@ +# This pipeline is used to release the VS Code Java Debug extension from the nightly/stable build. +# It contains following steps: +# 1. Download the plugin artifact from the nightly/stable build pipeline. +# 2. Publish the plugin to the marketplace. + +name: $(Date:yyyyMMdd).$(Rev:r) # Use the current date and a revision number for the build name. + +variables: + - name: Codeql.Enabled + value: true +resources: + repositories: + - repository: self + type: git + ref: refs/heads/main + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +trigger: none +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + pool: + os: linux + name: 1ES_JavaTooling_Pool + image: 1ES_JavaTooling_Ubuntu-2004 + stages: + - stage: Release + jobs: + - job: Job + displayName: Release VS Code Java Debug Extension + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + buildType: specific + project: $(AzDo.ProjectId) # Azure DevOps project ID + definition: $(AzDo.BuildPipelineId) # artifact build pipeline ID + artifactName: vsix + downloadType: specific + targetPath: '$(Build.SourcesDirectory)' + steps: + - task: UseNode@1 + displayName: 'Use Node.js 20.x' + inputs: + version: '20.x' + - task: AzureCLI@2 + displayName: 'Publish Extension' + inputs: + azureSubscription: 'VSCode-Ext-Publishing' + scriptType: pscore + scriptLocation: inlineScript + inlineScript: 'npx @vscode/vsce@latest publish -i ''$(Build.SourcesDirectory)/extension.vsix'' --manifestPath ''$(Build.SourcesDirectory)/extension.manifest'' --signaturePath ''$(Build.SourcesDirectory)/extension.signature.p7s'' --azure-credential' \ No newline at end of file diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml new file mode 100644 index 00000000..119d9e1f --- /dev/null +++ b/.azure-pipelines/release.yml @@ -0,0 +1,55 @@ +# This pipeline is used to release the VS Code Java Debug extension from the nightly/stable build. +# It contains following steps: +# 1. Download the plugin artifact from the nightly/stable build pipeline. +# 2. Publish the plugin to the marketplace. + +name: $(Date:yyyyMMdd).$(Rev:r) # Use the current date and a revision number for the build name. + +variables: + - name: Codeql.Enabled + value: true +resources: + repositories: + - repository: self + type: git + ref: refs/heads/main + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +trigger: none +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + pool: + os: linux + name: 1ES_JavaTooling_Pool + image: 1ES_JavaTooling_Ubuntu-2004 + stages: + - stage: Release + jobs: + - job: Job + displayName: Release VS Code Java Debug Extension + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + buildType: specific + project: $(AzDo.ProjectId) # Azure DevOps project ID + definition: $(AzDo.BuildPipelineId) # artifact build pipeline ID + artifactName: vsix + downloadType: specific + targetPath: '$(Build.SourcesDirectory)' + steps: + - task: UseNode@1 + displayName: 'Use Node.js 20.x' + inputs: + version: '20.x' + - task: AzureCLI@2 + displayName: 'Publish Extension' + inputs: + azureSubscription: 'VSCode-Ext-Publishing' + scriptType: pscore + scriptLocation: inlineScript + inlineScript: 'npx @vscode/vsce@latest publish -i ''$(Build.SourcesDirectory)/extension.vsix'' --manifestPath ''$(Build.SourcesDirectory)/extension.manifest'' --signaturePath ''$(Build.SourcesDirectory)/extension.signature.p7s'' --azure-credential' \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index d24a06ef..d1be8048 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,7 +10,7 @@ indent_size = 4 # The indent size used in the `package.json` file cannot be changed # https://github.com/npm/npm/pull/3180#issuecomment-16336516 -[{.travis.yml,npm-shrinkwrap.json,package.json}] +[{.github/workflows/build.yml,npm-shrinkwrap.json,package.json}] indent_size = 2 [vendor/**.js] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..0fffee03 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @testforstephen @jdneo @wenytang-ms @chagong \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..b4c75bf9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,21 @@ +[provide a description of the issue] + +##### Environment +- Operating System: +- JDK version: +- Visual Studio Code version: +- Java extension version: +- Java Debugger 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/llms.md b/.github/llms.md new file mode 100644 index 00000000..f0c0521e --- /dev/null +++ b/.github/llms.md @@ -0,0 +1,43 @@ +# Extension Pack for Java + +Extension Pack for Java is a collection of popular extensions that can help write, test and debug Java applications in Visual Studio Code. By installing Extension Pack for Java, the following extensions are installed: + +- [📦 Language Support for Java™ by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) + - Code Navigation + - Auto Completion + - Refactoring + - Code Snippets +- [📦 Debugger for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug) + - Debugging +- [📦 Test Runner for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-test) + - Run & Debug JUnit/TestNG Test Cases +- [📦 Maven for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-maven) + - Project Scaffolding + - Custom Goals +- [📦 Gradle for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-gradle) + - View Gradle tasks and project dependencies + - Gradle file authoring + - Import Gradle projects via [Gradle Build Server](https://github.com/microsoft/build-server-for-gradle) +- [📦 Project Manager for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-dependency) + - Manage Java projects, referenced libraries, resource files, packages, classes, and class members +- [📦 Visual Studio IntelliCode](https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode) + - AI-assisted development + - Completion list ranked by AI + +## Label + +When labeling an issue, follow the rules below per label category: + +### General Rules + +- Analyze if the issue is related with the scope of using extensions for Java development. If not, STOP labelling IMMEDIATELY. +- Assign label per category. +- If a category is not applicable or you're unsure, you may skip it. +- Do not assign multiple labels within the same category, unless explicitly allowed as an exception. + +### Issue Type Labels + +- [bug]: Primary label for real bug issues +- [enhancement]: Primary label for enhancement issues +- [documentation]: Primary label for documentation issues +- [question]: Primary label for question issues diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..e5747134 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,126 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + linux: + name: Linux + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v5 + + - name: Setup Build Environment + run: | + sudo apt-get update + sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 + sudo /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + sleep 3 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@v5 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Install build tools + run: npm install -g @vscode/vsce typescript + + - name: Lint + run: npm run tslint + + - name: Package + run: vsce package + + - name: Test extension + run: DISPLAY=:99 npm test + + - name: Print language server Log if job failed + if: ${{ failure() }} + run: find $HOME/.config/Code/User/workspaceStorage/*/redhat.java/jdt_ws/.metadata/.log -print -exec cat '{}' \;; + + windows: + name: Windows + runs-on: windows-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v5 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@v5 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Install build tools + run: npm install -g @vscode/vsce typescript --force + + - name: Lint + run: npm run tslint + + - name: Package + run: vsce package + + - name: Test extension + run: npm test + + - name: Print language server Log if job failed + if: ${{ failure() }} + run: Get-ChildItem -Path $env:APPDATA/Code/User/workspaceStorage/*/redhat.java/jdt_ws/.metadata/.log | cat + + darwin: + name: macOS + runs-on: macos-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v5 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@v5 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Install build tools + run: npm install -g @vscode/vsce typescript + + - name: Lint + run: npm run tslint + + - name: Package + run: vsce package + + - name: Test extension + run: npm test + + - name: Print language server Log if job failed + if: ${{ failure() }} + run: find $HOME/Library/Application\ Support/Code/User/workspaceStorage/*/redhat.java/jdt_ws/.metadata/.log -print -exec cat '{}' \;; diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml new file mode 100644 index 00000000..4cc4c9fc --- /dev/null +++ b/.github/workflows/no-response.yml @@ -0,0 +1,26 @@ +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. +# **Who does it impact**: Everyone that works on docs or docs-internal. + +on: + issue_comment: + types: [created] + schedule: + # every morning at 00:00 am + - cron: '0 0 * * *' + +jobs: + noResponse: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: lee-dohm/no-response@9bb0a4b5e6a45046f00353d5de7d90fb8bd773bb #v0.5.0 + with: + token: ${{ github.token }} + daysUntilClose: 14 # Number of days of inactivity before an Issue is closed for lack of response + responseRequiredLabel: "needs more 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/triage-agent.yml b/.github/workflows/triage-agent.yml new file mode 100644 index 00000000..0e0cb45e --- /dev/null +++ b/.github/workflows/triage-agent.yml @@ -0,0 +1,126 @@ +name: AI Triage + +on: + issues: + types: [opened] + workflow_dispatch: + inputs: + issue_number: + description: 'Issue number to triage (manual run). e.g. 123' + required: true + +run-name: >- + AI Triage for Issue #${{ github.event.issue.number || github.event.inputs.issue_number }} + +permissions: + issues: write + contents: read + +jobs: + label_and_comment: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Get issue data + id: get_issue + uses: actions/github-script@v6 + with: + script: | + const eventName = context.eventName; + let issue; + if (eventName === 'workflow_dispatch') { + const inputs = context.payload.inputs || {}; + const issueNumber = inputs.issue_number || inputs.issueNumber; + if (!issueNumber) core.setFailed('Input issue_number is required for manual run.'); + const { data } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: parseInt(issueNumber, 10), + }); + issue = data; + } else if (context.payload.issue) { + issue = context.payload.issue; + } else { + core.setFailed('No issue information found in the event payload.'); + } + core.setOutput('id', String(issue.number)); + core.setOutput('user', String((issue.user && issue.user.login) || '')); + core.setOutput('title', String(issue.title || '')); + core.setOutput('body', String(issue.body || '')); + const labelNames = (issue.labels || []).map(label => label.name); + core.setOutput('labels', JSON.stringify(labelNames)); + + - name: Call Azure Function + id: call_azure_function + env: + PAYLOAD: >- + { + "authToken": "${{ secrets.GITHUB_TOKEN }}", + "repoId": "microsoft/vscode-java-debug", + "issueData": { + "id": ${{ steps.get_issue.outputs.id }}, + "user": ${{ toJson(steps.get_issue.outputs.user) }}, + "title": ${{ toJson(steps.get_issue.outputs.title) }}, + "body": ${{ toJson(steps.get_issue.outputs.body) }}, + "labels": ${{ steps.get_issue.outputs.labels }} + }, + "mode": "DirectUpdate" + } + + run: | + # Make the HTTP request with improved error handling and timeouts + echo "Making request to triage agent..." + + # Add timeout handling and better error detection + set +e # Don't exit on curl failure + response=$(timeout ${{ vars.TRIAGE_AGENT_TIMEOUT }} curl \ + --max-time 0 \ + --connect-timeout 30 \ + --fail-with-body \ + --silent \ + --show-error \ + --write-out "HTTPSTATUS:%{http_code}" \ + --header "Content-Type: application/json" \ + --request POST \ + --data "$PAYLOAD" \ + ${{ secrets.TRIAGE_FUNCTION_LINK }} 2>&1) + + curl_exit_code=$? + set -e # Re-enable exit on error + + echo "Curl exit code: $curl_exit_code" + + # Check if curl command timed out or failed + if [ $curl_exit_code -eq 124 ]; then + echo "❌ Request timed out after 650 seconds" + exit 1 + elif [ $curl_exit_code -ne 0 ]; then + echo "❌ Curl command failed with exit code: $curl_exit_code" + echo "Response: $response" + exit 1 + fi + + # Extract HTTP status code and response body + http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + response_body=$(echo "$response" | sed 's/HTTPSTATUS:[0-9]*$//') + + echo "HTTP Status Code: $http_code" + + # Validate HTTP status code + if [ -z "$http_code" ]; then + echo "❌ Failed to extract HTTP status code from response" + echo "Raw response: $response" + exit 1 + fi + + # Check if the request was successful + if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then + echo "✅ Azure Function call succeeded" + else + echo "❌ Azure Function call failed with status code: $http_code" + echo "Response: $response_body" + exit 1 + fi diff --git a/.github/workflows/triage-all-open-issues.yml b/.github/workflows/triage-all-open-issues.yml new file mode 100644 index 00000000..f2600deb --- /dev/null +++ b/.github/workflows/triage-all-open-issues.yml @@ -0,0 +1,145 @@ +name: AI Triage - Process All Open Issues +on: + workflow_dispatch: + inputs: + dry_run: + description: 'Dry run mode - only list issues without processing' + required: false + default: false + type: boolean + max_issues: + description: 'Maximum number of issues to process (0 = all)' + required: false + default: '0' + type: string + +permissions: + issues: write + contents: read + actions: write + +jobs: + get_open_issues: + runs-on: ubuntu-latest + outputs: + issue_numbers: ${{ steps.get_issues.outputs.issue_numbers }} + total_count: ${{ steps.get_issues.outputs.total_count }} + + steps: + - name: Get all open issues + id: get_issues + uses: actions/github-script@v6 + with: + script: | + // Use Search API to filter issues at API level + const { data } = await github.rest.search.issuesAndPullRequests({ + q: `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open -label:ai-triaged -label:invalid`, + sort: 'created', + order: 'desc', + per_page: 100 + }); + + const actualIssues = data.items; + + let issuesToProcess = actualIssues; + const maxIssues = parseInt('${{ inputs.max_issues }}' || '0'); + + if (maxIssues > 0 && actualIssues.length > maxIssues) { + issuesToProcess = actualIssues.slice(0, maxIssues); + console.log(`Limiting to first ${maxIssues} issues out of ${actualIssues.length} total`); + } + + const issueNumbers = issuesToProcess.map(issue => issue.number); + const totalCount = issuesToProcess.length; + + console.log(`Found ${actualIssues.length} open issues, processing ${totalCount}:`); + issuesToProcess.forEach(issue => { + console.log(` #${issue.number}: ${issue.title}`); + }); + + core.setOutput('issue_numbers', JSON.stringify(issueNumbers)); + core.setOutput('total_count', totalCount); + + process_issues: + runs-on: ubuntu-latest + needs: get_open_issues + if: needs.get_open_issues.outputs.total_count > 0 + + strategy: + # Process issues one by one (max-parallel: 1) + max-parallel: 1 + matrix: + issue_number: ${{ fromJSON(needs.get_open_issues.outputs.issue_numbers) }} + + steps: + - name: Log current issue being processed + run: | + echo "🔄 Processing issue #${{ matrix.issue_number }}" + echo "Total issues to process: ${{ needs.get_open_issues.outputs.total_count }}" + + - name: Check if dry run mode + if: inputs.dry_run == true + run: | + echo "🔍 DRY RUN MODE: Would process issue #${{ matrix.issue_number }}" + echo "Skipping actual triage processing" + + - name: Trigger triage workflow for issue + if: inputs.dry_run != true + uses: actions/github-script@v6 + with: + script: | + const issueNumber = '${{ matrix.issue_number }}'; + + try { + console.log(`Triggering triage workflow for issue #${issueNumber}`); + + const response = await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'triage-agent.yml', + ref: 'main', + inputs: { + issue_number: issueNumber + } + }); + + console.log(`✅ Successfully triggered triage workflow for issue #${issueNumber}`); + + } catch (error) { + console.error(`❌ Failed to trigger triage workflow for issue #${issueNumber}:`, error); + core.setFailed(`Failed to process issue #${issueNumber}: ${error.message}`); + } + + - name: Wait for workflow completion + if: inputs.dry_run != true + run: | + echo "⏳ Waiting for triage workflow to complete for issue #${{ matrix.issue_number }}..." + echo "Timeout: ${{ vars.TRIAGE_AGENT_TIMEOUT }} seconds" + sleep ${{ vars.TRIAGE_AGENT_TIMEOUT }} # Wait for triage workflow completion + + summary: + runs-on: ubuntu-latest + needs: [get_open_issues, process_issues] + if: always() + + steps: + - name: Print summary + run: | + echo "## Triage Processing Summary" + echo "Total open issues found: ${{ needs.get_open_issues.outputs.total_count }}" + + if [ "${{ inputs.dry_run }}" == "true" ]; then + echo "Mode: DRY RUN (no actual processing performed)" + else + echo "Mode: FULL PROCESSING" + fi + + if [ "${{ needs.process_issues.result }}" == "success" ]; then + echo "✅ All issues processed successfully" + elif [ "${{ needs.process_issues.result }}" == "failure" ]; then + echo "❌ Some issues failed to process" + elif [ "${{ needs.process_issues.result }}" == "skipped" ]; then + echo "⏭️ Processing was skipped (no open issues found)" + else + echo "⚠️ Processing completed with status: ${{ needs.process_issues.result }}" + fi diff --git a/.gitignore b/.gitignore index 2d53e090..98790543 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,8 @@ out bin server node_modules -.vscode-test -vscode-java-debug-*.vsix \ No newline at end of file +.vscode-test/ +vscode-java-debug-*.vsix +packages/ +dist +.DS_Store \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5864edcc..00000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: node_js - -node_js: -- '6' - -os: -- linux -- 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 - -install: -- npm install -g vsce -- npm install -g typescript -- npm install -g gulp -- npm install - -script: -- gulp tslint -- vsce package -- npm test --silent \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index cd6b87bd..0ac35d26 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,19 +10,24 @@ "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], "stopOnEntry": false, "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], - "preLaunchTask": "npm" + "outFiles": [ "${workspaceRoot}/dist/**/*.js" ], + "preLaunchTask": "npm: watch", + "env": { + "DEBUG_VSCODE_JAVA":"true" + } }, { - "name": "Launch Tests", + "name": "Extension Tests", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], - "stopOnEntry": false, + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" + ], "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], - "preLaunchTask": "npm" - } + "outFiles": ["${workspaceFolder}/out/test/**/*.js"], + "preLaunchTask": "npm: compile" + } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1e37eb7b..114cae50 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,23 +8,35 @@ // A task runner that calls a custom npm script that compiles the extension. { - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isBackground": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" + "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": "Compiler '[^']+' starting", + "endsPattern": "Compiler '[^']+' finished" + } + }, + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] } \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore index cdeca6b8..9c5a198b 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,9 +1,21 @@ .vscode/** .vscode-test/** -out/test/** +out/** test/** src/** **/*.map tsconfig.json -gulpfile.js +scripts/build/** .gitignore +images/docs/** +testprojects/** +TestPlan.md +.github/** +tsconfig.json +tslint.json +packages +package-lock.json +node_modules +webpack.config.js +.DS_Store +.azure-pipelines/** \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 92180c72..c2638cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,670 @@ # Change Log All notable changes to the "vscode-java-debugger" extension will be documented in this file. -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## 0.58.5 - 2026-01-06 +### Fixed +- Fix `lspFrame.source.path` is null. [java-debug#618](https://github.com/microsoft/java-debug/pull/618). + +## 0.58.4 - 2025-12-09 +### Added +- Add command to manage breakpoint exception types in command palette. [#1566](https://github.com/microsoft/vscode-java-debug/pull/1566). Thanks to [Roland Schaer](https://github.com/roele) for contribution. + +### Fixed +- Fix `lspFrame.source` NPE on stackTrace request. [java-debug#616](https://github.com/microsoft/java-debug/pull/616). Thanks to [Mathias Fußenegger](https://github.com/mfussenegger) for contribution. +- Handle unavailable sources in compliance with DAP spec. [java-debug#609](https://github.com/microsoft/java-debug/pull/609), [java-debug#614](https://github.com/microsoft/java-debug/pull/614). Thanks to [Karl-Erik Enkelmann](https://github.com/playdohface) for contribution. + + +## 0.58.3 - 2025-11-03 +### Added +- No config debug [[#1530](https://github.com/microsoft/vscode-java-debug/issues/1530)] + +## 0.58.2 - 2025-04-28 +### Fixed +- Provide graceful shutdown on debug stop action. [#1274](https://github.com/microsoft/vscode-java-debug/issues/1274). Thanks to [Dave Syer](https://github.com/dsyer) for contribution. + +### Changed +- Update Apache Commons IO from 2.11.0 to 2.19.0. [java-debug#585](https://github.com/microsoft/java-debug/pull/585). Thanks to [Roland Grunberg](https://github.com/rgrunber) for contribution. + +## 0.58.1 - 2024-10-31 +### Added +- The launch config `envFile` now supports an array of env files. [#1505](https://github.com/microsoft/vscode-java-debug/issues/1505). Thanks to [Ed Hillmann](https://github.com/hildo) for contribution. + +### Fixed +- Fail to debug with java 23 - Unrecognized option: -Xnoagent. [java-debug#561](https://github.com/microsoft/java-debug/issues/561). + +## 0.58.0 - 2024-06-27 +### Fixed +- Latest Gradle Language Support extension cause hot code replace to fail. [#1402](https://github.com/microsoft/vscode-java-debug/issues/1402). +- Hot Code Replace returns "Cannot find any changed classes for hot replace!" message. [#1481](https://github.com/microsoft/vscode-java-debug/issues/1481). + +## 0.57.0 - 2024-03-26 +### Added +- Add support for running Java 21 "Unnamed classes and Instance main method". [#1444](https://github.com/microsoft/vscode-java-debug/issues/1444). + +## 0.56.2 - 2024-02-28 +### Changed +- Move 'Run/Debug Java' menus to the same group as the other Java menus within File Explorer. [#1447](https://github.com/microsoft/vscode-java-debug/pull/1447). + +## 0.56.1 - 2024-02-19 +### Fixed +- Fix the java.lang.NoClassDefFoundError when triggering code completion in DEBUG CONSOLE. See [java-debug#534](https://github.com/microsoft/java-debug/issues/534). + +## 0.56.0 - 2024-01-31 +### Fixed +- Breakpoint doesn't work on lambdas which returns a generic type. See [java-debug#498](https://github.com/microsoft/java-debug/issues/498), [#1413](https://github.com/microsoft/vscode-java-debug/issues/1413) and [#1414](https://github.com/microsoft/vscode-java-debug/issues/1414). +- Breakpoint with inline lambdas work only with last one. See [#1410](https://github.com/microsoft/vscode-java-debug/issues/1410). +- StepInto method target doesn't work if the method is part of wrapped expression. See [java-debug#519](https://github.com/microsoft/java-debug/issues/519). + + Thanks to [Gayan Perera](https://github.com/gayanper) for contribution in fixing multiple bugs. + +## 0.55.0 - 2023-11-01 +### Changed +- Don't duplicate build reference projects when building a Gradle project managed by Build Server. [java-debug#511](https://github.com/microsoft/java-debug/pull/511). + +### Fixed +- Cannot find Java process when using "Attach by Process ID". [#1388](https://github.com/microsoft/vscode-java-debug/issues/1388). Thanks to [owl-from-hogvarts](https://github.com/owl-from-hogvarts) for contribution. + +## 0.54.0 - 2023-08-29 +### Added +- Code completion in DEBUG CONSOLE now adds fully qualified names for unimported classes. See [#1246](https://github.com/microsoft/vscode-java-debug/issues/1246). +- Code completion in DEBUG CONSOLE now displays package names for suggested types. See [java-debug#505](https://github.com/microsoft/java-debug/pull/505). +- Integrate the build support for Gradle build server project. See [#1372](https://github.com/microsoft/vscode-java-debug/pull/1372), [java-debug#503](https://github.com/microsoft/java-debug/pull/503) + +### Changed +- Respect the setting 'java.debug.settings.forceBuildBeforeLaunch' even if autobuild is disabled. See [#1380](https://github.com/microsoft/vscode-java-debug/pull/1380). + +## 0.53.0 - 2023-08-01 +### Added +- Automatically refresh the CALL STACK view when the attached sources for frames have changed. See [#1370](https://github.com/microsoft/vscode-java-debug/pull/1370). + +### Changed +- Remove marketplace preview flag. See [#1369](https://github.com/microsoft/vscode-java-debug/pull/1369). + +## 0.52.0 - 2023-06-30 +### Added +- Use the setting `java.debug.settings.debugSupportOnDecompiledSource` to enable/disable debugging support on the decompiled source code. This feature requires [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java)@1.20.0 or higher. See [#1356](https://github.com/microsoft/vscode-java-debug/pull/1356). + +## 0.51.0 - 2023-05-31 +### Fixed +- NPE when adding lambda breakpoints in reactive projects. See [java-debug#477](https://github.com/microsoft/java-debug/issues/477). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. +- Lambda breakpoint on the first line of a method does not work. See [java-debug#488](https://github.com/microsoft/java-debug/issues/488). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. + +## 0.50.0 - 2023-04-26 +### Added +- Support specifying the exception types you want to break on. See [#1175](https://github.com/microsoft/vscode-java-debug/issues/1175) and [#295](https://github.com/microsoft/vscode-java-debug/issues/295). + +## 0.49.1 - 2023-03-28 +### Added +- Add context menus "Auto/Manual Expand Lazy Variables" to Variables view to auto show 'toString()' value. See [#1316](https://github.com/microsoft/vscode-java-debug/pull/1316). + +### Fixed +- Fix the error 'compareVersions is not a function'. See [#1307](https://github.com/microsoft/vscode-java-debug/pull/1307). + +## 0.49.0 - 2023-02-28 +### Added +- Enable Hot Code Replace when autobuild is disabled. See [#1296](https://github.com/microsoft/vscode-java-debug/pull/1296), [#1302](https://github.com/microsoft/vscode-java-debug/pull/1302). + +### Changed +- Display the running launch config name in progress bar for transparency. See [#1299](https://github.com/microsoft/vscode-java-debug/pull/1299). +- launch previously launched application if the current file isn't executable. See [#1036](https://github.com/microsoft/vscode-java-debug/issues/1036). + +## 0.48.0 - 2023-02-01 +### Changed +- Reject invalid DAP request. See [java-debug#466](https://github.com/microsoft/java-debug/pull/466). + +### Fixed +- Prioritize lookup the project source code during debugging. See [#1215](https://github.com/microsoft/vscode-java-debug/issues/1215). Thanks to [mozhuanzuojing](https://github.com/mozhuanzuojing) for contribution. + +## 0.47.0 - 2022-11-29 +### Changed +- Optimize the build error report of "Build failed, do you want to continue?". [#1214](https://github.com/microsoft/vscode-java-debug/issues/1214). + +### Fixed +- Use the system encoding to generate the *.argfile. [#1112](https://github.com/microsoft/vscode-java-debug/issues/1112). +- "shortenCommandLine": "argfile|auto" should include "vmArgs". [#1254](https://github.com/microsoft/vscode-java-debug/issues/1254). + +## 0.46.0 - 2022-11-02 +### Added +- Add "Step Into Target" feature to allow stepping directly into a specific function call when paused on a line. See [#1192](https://github.com/microsoft/vscode-java-debug/issues/1192). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. + +### Changed +- Exclude **/node_modules/** from .vscode/launch.json searches. See [#1234](https://github.com/microsoft/vscode-java-debug/pull/1234). Thanks to [Brandon Cheng](https://github.com/gluxon) for contribution. + +### Fixed +- Conditional Breakpoint got error code in reply:504. See [#1250](https://github.com/microsoft/vscode-java-debug/issues/1250). + +## 0.45.0 - 2022-10-12 +### Added +- Visualize the inline breakpoint locations. See [#1193](https://github.com/microsoft/vscode-java-debug/issues/1193). +- Show an extra column cursor when an inline breakpoint is hit. See [#1202](https://github.com/microsoft/vscode-java-debug/issues/1202). +- Support JEP 425: Virtual Threads (JDK 19). See [#1159](https://github.com/microsoft/vscode-java-debug/issues/1159). + +### Changed +- Enable async jdwp based on network latency for auto mode. See [java-debug#447](https://github.com/microsoft/java-debug/pull/447). + +### Fixed +- NPE when stopping JDT.LS. See [java-debug#448](https://github.com/microsoft/java-debug/issues/448). + +## 0.44.0 - 2022-09-01 +### Added +- **Experimental**: Support processing JDWP commands asynchronously to improve response speed of remote debugging. It's only enabled by default on VS Code Insiders. You can also opt-in by setting `java.debug.settings.jdwp.async`. See [#1208](https://github.com/microsoft/vscode-java-debug/pull/1208) and [java-debug#436](https://github.com/microsoft/java-debug/pull/436). +- Add support to specify Java executable via the property `javaExec` in launch.json. See [#1198](https://github.com/microsoft/vscode-java-debug/pull/1198). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. +- Add support for lambda breakpoints. See [java-debug#427](https://github.com/microsoft/java-debug/pull/427). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. + +## 0.43.0 - 2022-07-27 +### Added +- Support adding function breakpoints from the editor gutter. [java-debug#426](https://github.com/microsoft/java-debug/pull/426). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. + +### Changed +- Show target VM exceptions as result in evaluate requests. [java-debug#428](https://github.com/microsoft/java-debug/pull/428). Thanks to [Mathias Fußenegger](https://github.com/mfussenegger) for contribution. + +## 0.42.0 - 2022-06-29 +### Added +- Support function breakpoints, see [#258](https://github.com/microsoft/vscode-java-debug/issues/258). The current version support adding a function breakpoint with the syntax as `FullyQualifiedClassName#methodName` (e.g. `java.util.ArrayList#add`). Thanks to [Gayan Perera](https://github.com/gayanper) for contribution. + +### Changed +- Mark native frames and unavailable methods as subtle. [java-debug#409](https://github.com/microsoft/java-debug/pull/409). Thanks to [Mathias Fußenegger](https://github.com/mfussenegger) for contribution. + +### Fixed +- fix artifactId typo in Troubleshooting.md. [#1180](https://github.com/microsoft/vscode-java-debug/pull/1180). Thanks to [btoo](https://github.com/btoo) for contribution. + +## 0.41.0- 2022-06-01 +### Added +- Provide "Stop Java" button when triggering "Run Java" action. [#1166](https://github.com/microsoft/vscode-java-debug/issues/1166). +- [API] Support DAP request `processId` and event `processid` to get the exact pid of current running Java process. [java-debug#413](https://github.com/microsoft/java-debug/pull/413). + +### Changed +- Naming Java terminals with different names. [#1164](https://github.com/microsoft/vscode-java-debug/issues/1164). +- Enable Java terminal link provider on all terminals. [#1168](https://github.com/microsoft/vscode-java-debug/pull/1168). +- Disable HCR button when running Java without debugging. [#1167](https://github.com/microsoft/vscode-java-debug/pull/1167). + +## 0.40.1- 2022-04-15 +### Fixed +- Update command id to 'java.project.addToSourcePath.command'. [#1152](https://github.com/microsoft/vscode-java-debug/issues/1152). + +## 0.40.0 - 2022-03-28 +### Fixed +- Fix extension version. [#1146](https://github.com/microsoft/vscode-java-debug/pull/1146). + +## 0.39.0 - 2022-03-28 +### Added +- Support lazy loading object values from toString(). [java-debug#401](https://github.com/microsoft/java-debug/pull/401). +- API - Provide an api to query the processId of the debugging Java process. [java-debug#399](https://github.com/microsoft/java-debug/pull/399). + +### Changed +- Print logpoints to debug console. [#710](https://github.com/microsoft/vscode-java-debug/issues/710). Thanks to [James Clark](https://github.com/sbj42) for contribution. + +### Fixed +- VM launch failure doesn't report a useful error. [java-debug#397](https://github.com/microsoft/java-debug/issues/397). Thanks to [Karl von Randow](https://github.com/karlvr) for contribution. +- Engineering - Fix problemMatcher patterns for the watch task. [#1137](https://github.com/microsoft/vscode-java-debug/pull/1137). Thanks to [James Clark](https://github.com/sbj42) for contribution. + +## 0.38.0 - 2022-01-26 +### Added +- Thanks for the contribution from [Mu-Tsun Tsai](https://github.com/MuTsunTsai). Add zh-tw locale. [#1087](https://github.com/microsoft/vscode-java-debug/pull/1087). + +### Changed +- Change the inline button to debug icon. [#1108](https://github.com/microsoft/vscode-java-debug/pull/1108). + +### Fixed +- Improve the search performance of resolving main class. [java-debug#395](https://github.com/microsoft/java-debug/pull/395). +- If mainClass not specified, it will find main classes not belonging to current workspace. [#1098](https://github.com/microsoft/vscode-java-debug/issues/1098). +- Update CONTRIBUTING docs. [#1105](https://github.com/microsoft/vscode-java-debug/issues/1105). + +## 0.37.0 - 2021-11-24 +### Added +- Troubleshooting Guide for Encoding Issues on Windows. See [Troubleshooting_encoding](https://github.com/microsoft/vscode-java-debug/blob/main/Troubleshooting_encoding.md). + +### Fixed +- Address encoding issues on Windows. [#1077](https://github.com/microsoft/vscode-java-debug/pull/1077). +- Encoding - launcher.bat could not pass on redirected input into the java program being debugged. [microsoft/vscode-java-pack#756](https://github.com/microsoft/vscode-java-pack/issues/756). +- Encoding - Launching BAT for UTF-8 fix is incompatible with Security Policies disallowing BAT execution. [#646](https://github.com/microsoft/vscode-java-debug/issues/646). +- Encoding - Non-ASCII char support for Windows terminals. [#622](https://github.com/microsoft/vscode-java-debug/issues/622). +- Encoding - [Windows non-ASCII folder] Error: Could not find or load main class. [#623](https://github.com/microsoft/vscode-java-debug/issues/623). +- Step filter in the settings.json is not working. [#1085](https://github.com/microsoft/vscode-java-debug/issues/1085). +- Contribution from [ +John Grant](https://github.com/cyrfer): Support multiline values in envFile. [#1061](https://github.com/microsoft/vscode-java-debug/issues/1061). +- Contribution from [ +Adrien Piquerez](https://github.com/adpi2). Fix NPE when using step filter. [microsoft/java-debug#387](https://github.com/microsoft/java-debug/pull/387). +- Contribution from [Douglas M. Barcellos](https://github.com/dougmbarcellos). Update telemetry setting declaration in README. [#1084](https://github.com/microsoft/vscode-java-debug/pull/1084). + +## 0.36.0 - 2021-09-23 +### Changed +- Adopt new createStatusBarItem API for id and name properties. [#1020](https://github.com/microsoft/vscode-java-debug/issues/1020). + +### Fixed +- Unicode character in class name will fail to run. [#780](https://github.com/microsoft/vscode-java-debug/issues/780). +- Launching apps which require both a modulepath and a classpath doesn't work with shortenCommandLine="argfile". [#1047](https://github.com/microsoft/vscode-java-debug/issues/1047). +- Debugger fails to load variable values due to java.lang.OutOfMemoryError. [#1044](https://github.com/microsoft/vscode-java-debug/issues/1044). +- Fix privacy in the logger. [PR#1048](https://github.com/microsoft/vscode-java-debug/pull/1048). + +## 0.35.0 - 2021-07-28 +### Changed +- Add link to check detatils while reporting debugging progress. [PR#1034](https://github.com/microsoft/vscode-java-debug/pull/1034). + +### Fixed +- Catch up build errors before running a Java application. [#949](https://github.com/microsoft/vscode-java-debug/issues/949). + +## 0.34.0 - 2021-05-26 +### Changed +- Allow customizing the "classPaths" and "modulePaths" configurations via launch.json. See [#93](https://github.com/microsoft/vscode-java-debug/issues/93), [#980](https://github.com/microsoft/vscode-java-debug/issues/980). + +## 0.33.1 - 2021-04-30 +### Fixed +- HotFix: After upgrade from vscode-java v0.77.0 to v0.78.0 can't debug tests. [#995](https://github.com/microsoft/vscode-java-debug/issues/995). + +## 0.33.0 - 2021-04-28 +### Added +- Support inline values feature. [PR#977](https://github.com/microsoft/vscode-java-debug/pull/977). +- Show VARIABLES with different data views. [PR#982](https://github.com/microsoft/vscode-java-debug/pull/982). +- Adopt new APIs from vscode-tas-client. [#974](https://github.com/microsoft/vscode-java-debug/pull/974). +- Adopt workspaceTrust in package.json. [PR#988](https://github.com/microsoft/vscode-java-debug/pull/988). + +### Changed +- Engineering: Clean up deprecated logs. [PR#987](https://github.com/microsoft/vscode-java-debug/pull/987). + +### Fixed +- Breakpoints inside record methods don't work. [#973](https://github.com/microsoft/vscode-java-debug/issues/973). +- Support environment variable for port number in launch.json debug configuration. [#962](https://github.com/microsoft/vscode-java-debug/issues/962). +- Thanks for the contribution from [ZingBlue](https://github.com/ZingBlue): Spelling fix. [#968](https://github.com/microsoft/vscode-java-debug/pull/968). + +## 0.32.1 - 2021-03-23 +### Fixed +- Cannot launch debug session using JDK 16. [#970](https://github.com/microsoft/vscode-java-debug/issues/970). + +## 0.32.0 - 2021-03-12 +### Added +- Adopt TAS client for A/B testing. [PR#959](https://github.com/microsoft/vscode-java-debug/pull/959). + +### Changed +- Update to new product logo. [PR#952](https://github.com/microsoft/vscode-java-debug/pull/952). +- Adopt new 'run' menu in editor title. [PR#956](https://github.com/microsoft/vscode-java-debug/pull/956),[PR#960](https://github.com/microsoft/vscode-java-debug/pull/960). +- Engineering - Enable GitHub Actions. [PR#951](https://github.com/microsoft/vscode-java-debug/pull/951). + +## 0.31.0 - 2021-02-02 +### Added +- Support envFile option in launch.json. [#523](https://github.com/microsoft/vscode-java-debug/issues/523). + +### Fixed +- Git bash failed to execute Run/Debug when Windows username have blank space. [#678](https://github.com/microsoft/vscode-java-debug/issues/678). +- TEMP folder with spaces breaks debugger process. [#822](https://github.com/microsoft/vscode-java-debug/issues/822). +- The sort of completion list in DEBUG CONSOLE is different from that in editor. [#909](https://github.com/microsoft/vscode-java-debug/issues/909). +- The program failed to run in terminal if clicking run button several times in succession. [#924](https://github.com/microsoft/vscode-java-debug/issues/924). +- Fix vulnerabilities. [#935](https://github.com/microsoft/vscode-java-debug/issues/935), [#936](https://github.com/microsoft/vscode-java-debug/issues/936). + +## 0.30.0 - 2020-12-16 +### Added +- Add run button as inline button in Java Project Explorer. [PR#900](https://github.com/microsoft/vscode-java-debug/pull/900). +- Use progress to hint the current build status whenever you trigger the Run and Debug features. [PR#919](https://github.com/microsoft/vscode-java-debug/pull/919). +- Thanks for the contribution from [pablojimpas](https://github.com/pablojimpas): Spanish localization support. [PR#904](https://github.com/microsoft/vscode-java-debug/pull/904). + +### Changed +- Make the run buttons in editor toolbar more context-aware. [PR#898](https://github.com/microsoft/vscode-java-debug/pull/898). +- Update the group name of the Run and Debug menus registered in the Java Project Explorer. [PR#908](https://github.com/microsoft/vscode-java-debug/pull/908). +- Simplify the name label of the launch configuration. [PR#921](https://github.com/microsoft/vscode-java-debug/pull/921). +- Debt: Enable more tslint rules. [PR#914](https://github.com/microsoft/vscode-java-debug/pull/914),[PR#918](https://github.com/microsoft/vscode-java-debug/pull/918). + +### Fixed +- Find Java version from release file. [#910](https://github.com/microsoft/vscode-java-debug/issues/910). + +## 0.29.0 - 2020-10-16 +### Added +- Jump to source when clicking the stack trace printed to the terminal. [PR#890](https://github.com/microsoft/vscode-java-debug/pull/890). +- Contribute `Run` and `Debug` menus to Project Explorer. [#878](https://github.com/microsoft/vscode-java-debug/pull/878). +- Provide a user setting `java.debug.settings.vmArgs` to set the default VM arguments to launch your program. [#220](https://github.com/microsoft/vscode-java-debug/issues/220),[#876](https://github.com/microsoft/vscode-java-debug/issues/876). +- Provide a user setting `java.debug.settings.onBuildFailureProceed` to force the debug session to proceed when build fails. [#888](https://github.com/microsoft/vscode-java-debug/issues/888). + +### Changed +- Allow cancelling the outdated codelens job. [PR#881](https://github.com/microsoft/vscode-java-debug/pull/881). + +### Fixed +- Fix the wrong auto-completion result when typing the evaluation expression in DEBUG CONSOLE. [#880](https://github.com/microsoft/vscode-java-debug/issues/880). +- Fix the error 'UNC path is missing sharename: \\\\java'. [#882](https://github.com/microsoft/vscode-java-debug/issues/882). +- Use the correct runtime to validate the JVM versions between the debugger and debuggee. [PR#353](https://github.com/microsoft/java-debug/pull/353). + +## 0.28.0 - 2020-08-27 +### Added +- Add run/debug buttons to editor title bar for single file debugging. [#834](https://github.com/microsoft/vscode-java-debug/issues/834). +- Add user settings `java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest` and `java.debug.settings.jdwp.requestTimeout` to control JDWP request. [#862](https://github.com/microsoft/vscode-java-debug/pull/862),[#863](https://github.com/microsoft/vscode-java-debug/pull/863). + +### Changed +- Reduce the frequency of JDWP requests to improve performance when expanding VARIABLES view. [#347](https://github.com/microsoft/java-debug/pull/347). +- Migrate the legacy log to the telemetry wrapper. [#866](https://github.com/microsoft/vscode-java-debug/pull/866). + +### Fixed +- Fix Hot Code Replace error "Cannot find any changed classes for hot replace!". [#855](https://github.com/microsoft/vscode-java-debug/issues/855). + +## 0.27.1 - 2020-07-21 +### Fixed +- Hot Code Replace always reports "Cannot find any changed classes for hot replace!". [#850](https://github.com/microsoft/vscode-java-debug/issues/850). + +## 0.27.0 - 2020-07-17 +### Added +- Break on exception for "just my code". [#756](https://github.com/microsoft/vscode-java-debug/issues/756). +- Support step "just my code". [#628](https://github.com/microsoft/vscode-java-debug/issues/628). +- Show return value of a method. [#660](https://github.com/microsoft/vscode-java-debug/issues/660). +- Support "copy value" from Variable viewlet. [#819](https://github.com/microsoft/vscode-java-debug/issues/819). +- From upstream jdt: support using lambda and reference expressions in debug evaluation. [#281](https://github.com/microsoft/vscode-java-debug/issues/281). +- From upstream jdt: support evaluating local variables in the lambda body. [#754](https://github.com/microsoft/vscode-java-debug/issues/754). + +### Changed +- Always give UI feedback whenever you click ⚡ button to apply code changes. [#833](https://github.com/microsoft/vscode-java-debug/pull/833). +- Automatically add -XX:+ShowCodeDetailsInExceptionMessages when launching your program with Java 14. [#797](https://github.com/microsoft/vscode-java-debug/issues/797). +- Adopt the new resolveVariable API. [#750](https://github.com/microsoft/vscode-java-debug/issues/750). +- Adopt DebugAdapterDescriptorFactor API. [#751](https://github.com/microsoft/vscode-java-debug/issues/751). + +### Fixed +- Give a response when you trigger debugging in LightWeight mode. [#841](https://github.com/microsoft/vscode-java-debug/issues/841). +- Failed to get variables. Reason: com.sun.jdi.InvalidStackFrameException. [#767](https://github.com/microsoft/vscode-java-debug/issues/767). +- Render the source link for stack trace from Java modules. [#824](https://github.com/microsoft/vscode-java-debug/issues/824). + +## 0.26.0 - 2020-05-13 +### Added +- Support picking a Java process to auto attach. [#759](https://github.com/microsoft/vscode-java-debug/issues/759). + +### Fixed +- When running the Gradle application, the test scope is not filtered out. [#715](https://github.com/microsoft/vscode-java-debug/issues/715). +- Conditional breakpoint fails in the multi thread scenario. [#782](https://github.com/microsoft/vscode-java-debug/issues/782). +- Show a warning message about the Unsupported JDK error. [#789](https://github.com/microsoft/vscode-java-debug/issues/789). +- vmArgs in launch.json does not accept an array of strings. [#778](https://github.com/microsoft/vscode-java-debug/issues/778). +- Activate the extension before execute Java extension commands. [#775](https://github.com/microsoft/vscode-java-debug/pull/775). + +### Changed +- Contribution from [Mathias Fußenegger](https://github.com/mfussenegger): Extend readme with basic low level usage instructions. [java-debug#327](https://github.com/microsoft/java-debug/pull/327). + +Thank [Mathias Fußenegger](https://github.com/mfussenegger) for contribution. + +## 0.25.1 - 2020-03-06 +### Fixed +- Fix the Error: Could not find or load main class @x.y.z.argfile. [#769](https://github.com/microsoft/vscode-java-debug/issues/769). +- Cannot hit breakpoint at the class using Java 13 Text Blocks. [#773](https://github.com/microsoft/vscode-java-debug/issues/773). + +## 0.25.0 - 2020-02-20 +### Added +- Provide context menu to continue/pause all/other threads. [#748](https://github.com/microsoft/vscode-java-debug/pull/748). +- Contribution from [bhoppeadoy](https://github.com/bhoppeadoy): Add user setting `java.debug.settings.numericPrecision` to set the numeric precision when formatting doubles in "Variables" or "Debug Console" viewlet. [#745](https://github.com/microsoft/vscode-java-debug/issues/745). + +### Fixed +- Use project's Java runtime to launch the application. [#753](https://github.com/microsoft/vscode-java-debug/issues/753). +- Restart stop but not start the program. [#752](https://github.com/microsoft/vscode-java-debug/issues/752). +- Contribution from [xiaoyinl](https://github.com/xiaoyinl): Use HTTPS wherever possible. [#732](https://github.com/microsoft/vscode-java-debug/pull/732). + +## 0.24.0 - 2019-12-25 +### Added +- Support breaking when value changes (a.k.a. Data Breakpoints). [#654](https://github.com/microsoft/vscode-java-debug/issues/654). + +### Changed +- Improve "Run Java" experience: `F5` will run the current file without generating launch.json. [#724](https://github.com/microsoft/vscode-java-debug/issues/724). + +### Fixed +- Debug console will hang on Java exception stack trace. [#719](https://github.com/microsoft/vscode-java-debug/issues/719). +- Debug console won't automatically append `()` if selecting a method in completion list. [#711](https://github.com/microsoft/vscode-java-debug/issues/711), [#691](https://github.com/microsoft/vscode-java-debug/issues/691). +- Cannot pass `vmArgs` array to Java 13 project. [#703](https://github.com/microsoft/vscode-java-debug/issues/703). + +## 0.23.0 - 2019-10-29 +### Added +- Provide "Fix..." suggestions when "Build failed" occurs during launching the application. [#358](https://github.com/microsoft/vscode-java-debug/issues/358). +- Prompt to add the folder to source path if the running file isn't on classpath. [#470](https://github.com/microsoft/vscode-java-debug/issues/470). +- Provide samples for the commonly used debug configuration. See the [doc](https://github.com/microsoft/vscode-java-debug/blob/master/Configuration.md). + +### Fixed +- It's safe to keep running the run/debug codelens if the debug configuration fails to save into the launch.json. [PR#673](https://github.com/microsoft/vscode-java-debug/pull/673). +- Improve the error handling when running the file via the context "run" or "debug" menu. [PR#679](https://github.com/microsoft/vscode-java-debug/pull/679). +- Support searching main classes from the workspace invisible project. [PR#305](https://github.com/microsoft/java-debug/pull/305). + +### Changed +- Update troubleshooting doc for class not found error. See the [doc](https://github.com/microsoft/vscode-java-debug/blob/master/Troubleshooting.md#program-error-could-not-find-or-load-main-class-x). +- Update troubleshooting doc for build failed error. See the [doc](https://github.com/microsoft/vscode-java-debug/blob/master/Troubleshooting.md#build-failed-do-you-want-to-continue). + +## 0.22.0 - 2019-09-24 +### Added +- Show Run/Debug buttons when hover on a main method. [#657](https://github.com/microsoft/vscode-java-debug/issues/657). + +### Fixed +- Debugger just broken with git bash as the default shell on Windows. [#642](https://github.com/microsoft/vscode-java-debug/issues/642). +- [Mac] Failed to launch debuggee in terminal with TimeoutException. [#637](https://github.com/microsoft/vscode-java-debug/issues/637), [#651](https://github.com/microsoft/vscode-java-debug/issues/651). +- Pop an error message when click ⚡ HCR button in the Run mode. [PR#665](https://github.com/microsoft/vscode-java-debug/pull/665). +- Don't escape single quote of the program args. [PR#668](https://github.com/microsoft/vscode-java-debug/pull/668). + +## 0.21.0 - 2019-08-26 +### Added +- Add menu entries to `Run` and `Debug` a Java application when you right click a Java file in file explorer or opened editor. [#626](https://github.com/microsoft/vscode-java-debug/issues/626). + +### Changed +- Remove hard dependency of redhat.java. [PR#617](https://github.com/microsoft/vscode-java-debug/pull/617). +- Change the default console to integrated terminal. [#605](https://github.com/microsoft/vscode-java-debug/issues/605). + +### Fixed +- Java language server is activated by mistake when debugging a non-Java project. [#238](https://github.com/microsoft/vscode-java-debug/issues/238). +- [Windows] `integratedTerminal` console does not showing unicode characters. [#524](https://github.com/microsoft/vscode-java-debug/issues/524). +- Contribution from [pi1024e](https://github.com/pi1024e): Fix UI typos. [PR#630](https://github.com/microsoft/vscode-java-debug/pull/630). + +Thank [pi1024e](https://github.com/pi1024e) for contribution. + +## 0.20.0 - 2019-07-01 +### Fixed +- Fix: Adding wrong jar version to the classpath. [#566](https://github.com/microsoft/vscode-java-debug/issues/566). +- Fix: Adding wrong classpath at runtime for multi modules maven projects. [#584](https://github.com/microsoft/vscode-java-debug/issues/584). +- Contribution from [tom-shan](https://github.com/tom-shan): Should break earlier when destroying temporary launch file. [PR#280](https://github.com/microsoft/java-debug/pull/280). + +Thank [tom-shan](https://github.com/tom-shan) for contribution. + +## 0.19.0 - 2019-05-31 +### Added +- Add a debug toolbar button to apply the changed classes to the running application. [#559](https://github.com/microsoft/vscode-java-debug/issues/559). +- Show toString() values in Variable window and hover tooltip. [#315](https://github.com/microsoft/vscode-java-debug/issues/315), [#364](https://github.com/microsoft/vscode-java-debug/issues/364). +- Add a global user setting `java.debug.settings.console` to specify the default console to launch your program. [PR#594](https://github.com/microsoft/vscode-java-debug/pull/594). + +### Fixed +- Fix: The debug toolbar doesn't close after the program running in external terminal exits. [#582](https://github.com/microsoft/vscode-java-debug/issues/582). +- Fix: Cannot stop the debugging process automatically in attach mode. [java-debug#273](https://github.com/microsoft/java-debug/issues/273). + +## 0.18.0 - 2019-04-23 +### Added +- Enable "Logical Structure" view for Map and Collection variables. [#227](https://github.com/Microsoft/vscode-java-debug/issues/227). +- Add the source hyperlinks for the stack traces in the Debug Console output. [#490](https://github.com/Microsoft/vscode-java-debug/issues/490), [#506](https://github.com/Microsoft/vscode-java-debug/issues/506). +- Automatically add `--enable-preview` to vmArgs when necessary. [#553](https://github.com/Microsoft/vscode-java-debug/issues/553). + +### Changed +- Disable `java.debug.settings.showStaticVariables` by default to not show the static fields. + +### Fixed +- Fix: Debug Console does not support autocomplete when a .class file is open. [#535](https://github.com/Microsoft/vscode-java-debug/issues/535). + +## 0.17.0 - 2019-03-06 +### Added +- Popup the exception details via a UI widget when an exception breakpoint is hit. [#522](https://github.com/Microsoft/vscode-java-debug/issues/522). + +### Changed +- Reduce the extension load time by using webpack. [#492](https://github.com/Microsoft/vscode-java-debug/issues/492), [#517](https://github.com/Microsoft/vscode-java-debug/issues/517). + +### Fixed +- Add a new debug configuration `shortenCommandLine` to fix the issue "CreateProcess error=206, The filename or extension is too long". [#110](https://github.com/Microsoft/vscode-java-debug/issues/110). + +## 0.16.0 - 2018-12-12 +### Added +- Provide Chinese localized settings page for Java debugger, including launch.json configuration and user settings. [#472](https://github.com/Microsoft/vscode-java-debug/issues/472), [#477](https://github.com/Microsoft/vscode-java-debug/issues/477). +- Add new user settings `java.debug.settings.forceBuildBeforeLaunch` to control whether to build the workspace before Run/Debug. [#462](https://github.com/Microsoft/vscode-java-debug/issues/462). +- F5 will auto launch the current Java file if `mainClass` in launch.json is set to the variable `${file}`. [#431](https://github.com/Microsoft/vscode-java-debug/issues/431) + +### Changed +- Simplify generated launch.json. [#476](https://github.com/Microsoft/vscode-java-debug/issues/476). +- Remove the emoji before Run/Debug CodeLens. [#475](https://github.com/Microsoft/vscode-java-debug/issues/475). +- Use `vscode.open` api instead of `opn` library. [#479](https://github.com/Microsoft/vscode-java-debug/issues/479). + +### Fixed +- Fix the main class isn't unique issue. [#420](https://github.com/Microsoft/vscode-java-debug/issues/420). + +## 0.15.0 - 2018-11-01 +### Added +- Contribution from [Thad House](https://github.com/ThadHouse): Add new user settings `java.debug.settings.enableRunDebugCodeLens` to enable/disable Run|Debug Code Lenses on main methods. [#464](https://github.com/Microsoft/vscode-java-debug/issues/464). +- Contribution from [Julien Russo](https://github.com/Dotpys): Add italian translation for extension configuration. [PR#463](https://github.com/Microsoft/vscode-java-debug/pull/463). + +Thank [Thad House](https://github.com/ThadHouse) and [Julien Russo](https://github.com/Dotpys) for contribution. + +## 0.14.0 - 2018-10-10 +### Fixed +- Fix: Code Lenses for Run/Debug links on main methods don't show up immediately. [#438](https://github.com/Microsoft/vscode-java-debug/issues/438). +- Fix: It throws "ConfigError: 'mymodule/App' is not a valid class name." for java 9 program. [#437](https://github.com/Microsoft/vscode-java-debug/issues/437). +- Fix: Cannot run from src/test anymore. [#413](https://github.com/Microsoft/vscode-java-debug/issues/413). +- Fix: It throws InvalidStackFrameException during evaluating on conditional breakpoint. [#369](https://github.com/Microsoft/vscode-java-debug/issues/369). +- Fix: The launch command for internalConsole is different from integratedTerminal. [#440](https://github.com/Microsoft/vscode-java-debug/issues/440). + +## 0.13.0 - 2018-9-19 +### Added +- Use code lens to run java program in a much simpler way. [#375](https://github.com/Microsoft/vscode-java-debug/issues/375). +- Make args/vmArgs accept an array. [#389](https://github.com/Microsoft/vscode-java-debug/issues/389). +- Make mainClass accept variables. [#85](https://github.com/Microsoft/vscode-java-debug/issues/85). + +### Fixed +- Fix: Still include test classes in classpaths when auto resolve maven project. [#378](https://github.com/Microsoft/vscode-java-debug/issues/378). +- Fix: Duplicate class path during launching. [#370](https://github.com/Microsoft/vscode-java-debug/issues/370). +- Fix: Update Active Editor oct icon to file instead of clock. [#403](https://github.com/Microsoft/vscode-java-debug/issues/403). +- Fix: Launching the debuggee with the same JDK as java language server instead of JRE. [#366](https://github.com/Microsoft/vscode-java-debug/issues/366). +- Fix: Avoid pop up error window many times for logpoints in a loop. [#360](https://github.com/Microsoft/vscode-java-debug/issues/390). +- Fix: Debug buttons disabled. [#411](https://github.com/Microsoft/vscode-java-debug/issues/411) +- Fix: StepResponse/ContinueResponse should be sent before StoppedEvent. [java-debug#134](https://github.com/Microsoft/java-debug/issues/134) + +## 0.12.2 - 2018-9-6 +### Fixed +- Fix: Runtime scope class path entries are missing. [#402](https://github.com/Microsoft/vscode-java-debug/issues/402). + +## 0.12.1 - 2018-8-31 +### Fixed +- Fix: `env` config in launch.json not respected. [#393](https://github.com/Microsoft/vscode-java-debug/issues/393). + +## 0.12.0 - 2018-8-29 +### Added +- Start without debugging. See [#351](https://github.com/Microsoft/vscode-java-debug/issues/351). +- Add the validation to mainClass and projectName before launching. See [#355](https://github.com/Microsoft/vscode-java-debug/issues/355). +- Add "Learn More" link jumps to the associated troubleshooting paragraph [#360](https://github.com/Microsoft/vscode-java-debug/issues/360). + +### Changed +- Put recently used main class in the top [#350](https://github.com/Microsoft/vscode-java-debug/issues/350). +- Enable evaluation for hovers [#297](https://github.com/Microsoft/vscode-java-debug/issues/297). +- Distinguish user errors and system errors [#288](https://github.com/Microsoft/vscode-java-debug/issues/288). + +### Fixed +- Fix: vulnerabilities issue [PR#356](https://github.com/Microsoft/vscode-java-debug/pull/356). +- Fix: NPE for CompletionsProvider [PR#206](https://github.com/Microsoft/java-debug/pull/206). +- Fix: Debugger slow when watching variables [#305](https://github.com/Microsoft/vscode-java-debug/issues/305). +- Fix: Should not include test classes in classpath [#111](https://github.com/Microsoft/vscode-java-debug/issues/111). + +## 0.11.0 - 2018-8-2 +### Added +- Add a troubleshooting page for common errors. See [the troubleshooting guide](https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting.md). +- Build and publish the Java Debug Server plugin as p2 artifacts. See [PR#191](https://github.com/Microsoft/java-debug/pull/191), [PR#192](https://github.com/Microsoft/java-debug/pull/192). + +### Changed +- Auto select Java Debugger for .java file. See [PR#329](https://github.com/Microsoft/vscode-java-debug/pull/329). +- Improve the *launch.json* auto-generation UX. See [PR#342](https://github.com/Microsoft/vscode-java-debug/pull/342). +- Improve the logger coverage for the error response. See [PR#190](https://github.com/Microsoft/java-debug/pull/190). + +### Fixed +- Fix the attach error in JDK 10. See [PR#187](https://github.com/Microsoft/java-debug/pull/187). +- Fix the Java Debug Server plugin build error in JDK 10. See [PR#194](https://github.com/Microsoft/java-debug/pull/194). + +## 0.10.0 - 2018-6-27 +### Added +- Add support for Logpoint. The minimum compatible VS Code version is 1.22. See the feature request [#272](https://github.com/Microsoft/vscode-java-debug/issues/272) + +### Fixed +- Contribution from [LunarArcanus](https://github.com/LunarArcanus): Fix the grammar issue in README. See [PR#306](https://github.com/Microsoft/vscode-java-debug/pull/306). +- Fix the project's build errors in JDK 9/10. See [PR#178](https://github.com/Microsoft/java-debug/pull/178) + +## 0.9.0 - 2018-4-26 +### Added +- Support auto-complete feature in debug console view. See the feature request [#237](https://github.com/Microsoft/vscode-java-debug/issues/237) + +### Fixed +- Fix the ObjectCollectedException when enabling ExceptionBreakpoint. See [Issue #182](https://github.com/Microsoft/vscode-java-debug/issues/182) +- Fix the [issue #277](https://github.com/Microsoft/vscode-java-debug/issues/277) that the debugger doesn't stop on caught/uncaught exceptions. See [PR #172](https://github.com/Microsoft/java-debug/pull/172) +- Fix the [issue #273](https://github.com/Microsoft/vscode-java-debug/issues/273) that Chinese characters directory will cause messy code during stack trace's source looking up. See [PR #170](https://github.com/Microsoft/java-debug/pull/170) + + +## 0.8.0 - 2018-4-3 +### Added +- Support [restart frame](https://github.com/Microsoft/vscode-java-debug/issues/235). See [PR#160](https://github.com/Microsoft/java-debug/pull/160) + +### Changed +- Enable hot code replace by default. See [PR#263](https://github.com/Microsoft/vscode-java-debug/pull/263) +- Wait for building successfully before launch debug session. See [PR#257](https://github.com/Microsoft/vscode-java-debug/pull/257) +- Automatically detect projectName when only one main class or project available. See [PR#164](https://github.com/Microsoft/java-debug/pull/164) + + +## 0.7.0 - 2018-3-15 +### Added +- Support [conditional breakpoints](https://github.com/Microsoft/vscode-java-debug/issues/118). See [PR#153](https://github.com/Microsoft/java-debug/pull/153), [PR#154](https://github.com/Microsoft/java-debug/pull/154), [PR#156](https://github.com/Microsoft/java-debug/pull/156) +- Support prompting user for program arguments. See [PR#245](https://github.com/Microsoft/vscode-java-debug/pull/245) + +### Changed +- Fix the unsupported breakpoint at method entry/exit issue. See [PR#129](https://github.com/Microsoft/java-debug/pull/129) +- Fix the issue when the projectName is not specified, the expression evaluation doesn't work. See [PR#156](https://github.com/Microsoft/java-debug/pull/156) +- Fix VMDisconnectionException in HCR. See [PR#150](https://github.com/Microsoft/java-debug/pull/150) + + +## 0.6.0 - 2018-2-1 +### Added +- Support hot code replace. See [PR#225](https://github.com/Microsoft/vscode-java-debug/pull/225) + +## 0.5.0 - 2017-12-20 +### Added +- Support step filters when stepping. See [PR#155](https://github.com/Microsoft/vscode-java-debug/pull/155) +- Support expression evaluation. See [PR#126](https://github.com/Microsoft/vscode-java-debug/pull/126), [PR#131](https://github.com/Microsoft/java-debug/pull/131) +- Publish the binaries to the maven central repository. See [PR#132](https://github.com/Microsoft/java-debug/pull/132) + +### Changed +- Adopt new VSCode 1.19.0 debug activation events. See [PR#196](https://github.com/Microsoft/vscode-java-debug/pull/196) +- Looking up the stack frame's associated source file from source containers to improve searching perf. See [PR#127](https://github.com/Microsoft/java-debug/pull/127) + +## 0.4.0 - 2017-11-30 +### Added +- Add `stopOnEntry` and `console` options for launch.json. See [PR#177](https://github.com/Microsoft/vscode-java-debug/pull/177) +- Support console input by launching the program in the integrated/external terminal. See [PR#122](https://github.com/Microsoft/java-debug/pull/122) +- Add debugging settings: `java.debug.settings.showHex`, `java.debug.settings.showStaticVariables`, `java.debug.settings.showQualifiedNames`, `java.debug.settings.maxStringLength`. See [README](https://github.com/Microsoft/vscode-java-debug/README.md) for details +- Support project scope when resolving multiple-root project. See [PR#174](https://github.com/Microsoft/vscode-java-debug/pull/174) + +### Fixed +- Fix single file build issue. See [Issue#167](https://github.com/Microsoft/vscode-java-debug/issues/167) +- Fix perf issue when debugging with "stopOnEntry". See [PR#115](https://github.com/Microsoft/java-debug/pull/115) + +## 0.3.1 - 2017-11-17 +### Fixed +- Fix the unable to start debugging issue[Issue#146](https://github.com/Microsoft/vscode-java-debug/issues/146) + +## 0.3.0 - 2017-11-10 +### Added +- Support debugging java 9 project. See [Issue#47](https://github.com/Microsoft/vscode-java-debug/issues/47) +- Support debugging standalone java file. See [Issue#94](https://github.com/Microsoft/vscode-java-debug/issues/94) +- Support "cwd" and "env" in launch.json. See [Issue#12](https://github.com/Microsoft/vscode-java-debug/issues/12), [Issue#75](https://github.com/Microsoft/vscode-java-debug/issues/75) + +### Changed +- Build workspace before starting debugger. See [Issue#32](https://github.com/Microsoft/vscode-java-debug/issues/32) +- Show progress when initializing the launch.json. See [PR#106](https://github.com/Microsoft/vscode-java-debug/pull/106) +- Get debug settings from VSCode user preferences. See [PR#135](https://github.com/Microsoft/vscode-java-debug/pull/135),[PR#94](https://github.com/Microsoft/java-debug/pull/94) + +### Fixed +- Fix perf issue on getting locations of breakpoint. See [Issue#49](https://github.com/Microsoft/java-debug/issues/49) +- Show warning message when the debugger and the debuggee run in the different versions of JVMs. See [Issue#30](https://github.com/Microsoft/vscode-java-debug/issues/30) + +## 0.2.0 - 2017-10-20 +### Added +- Automatically resolve the main class during launching. See [Issue#9](https://github.com/Microsoft/vscode-java-debug/issues/9) +- Fully support external source files together with the changes from VSCode. See [PR#58](https://github.com/Microsoft/java-debug/pull/58) + +### Changed +- Adopt the new DebugConfigurationProvider protocol of VS Code. See [PR#87](https://github.com/Microsoft/vscode-java-debug/pull/87) +- Display the function names in the format of ClassName.MethodName(Parameter List...).. See [PR#73](https://github.com/Microsoft/java-debug/pull/73) +- Improve the call stack display info for the files without sources. See [PR#72](https://github.com/Microsoft/java-debug/pull/72) + +### Fixed +- Fix the inconsistent URI issue when set breakpoint request. See [PR#84](https://github.com/Microsoft/java-debug/pull/84) +- Avoid two stopped events for step and breakpoint. See [Issue#14](https://github.com/Microsoft/vscode-java-debug/issues/14) +- Fix the issue that JDT search might return multiple results from the same project. See [Issue#21](https://github.com/Microsoft/java-debug/issues/21) +- Avoid send error messages after debugger adapter stopped. See [PR#75](https://github.com/Microsoft/java-debug/pull/75) +- Fix several exception cases. See [PR#64](https://github.com/Microsoft/java-debug/pull/62), [PR#67](https://github.com/Microsoft/java-debug/pull/67), [PR#74](https://github.com/Microsoft/java-debug/pull/74) ## 0.1.0 - 2017-09-27 ### Added @@ -17,4 +677,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Variables - Callstacks - Threads -- Debug console \ No newline at end of file +- Debug console + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..cae7a2a0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,64 @@ +# Contributing to Java Debugger + +## Build and Debug + +### Getting the source +This debugger is written in [TypeScript](https://github.com/Microsoft/TypeScript), and it depends on a [Java Debug Server](https://github.com/Microsoft/java-debug) written in Java. +- Suggest to create a new folder first. + ```bash + mkdir javaDebugger + cd javaDebugger + ``` +- Check out source code for the extension. + ```bash + git clone https://github.com/Microsoft/vscode-java-debug.git + ``` +- Check out source code for the debug server. + ```bash + git clone https://github.com/Microsoft/java-debug.git + ``` +Now the folder structure looks like following: +```bash +javaDebugger/ +├── java-debug +└── vscode-java-debug +``` + +### Prerequisites +- [JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html), (version 11 or later) +- [VS Code](https://code.visualstudio.com/), (version 1.44.0 or later) +- [Node.JS](https://nodejs.org/en/), (>= 12.8.1) +- [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java), (version 0.60.0 or later) + +Install all the dependencies using `npm` (supposed to be installed together with [Node.JS](https://nodejs.org/en/)). +```bash +cd vscode-java-debug +npm install +``` + +### Build and Run +#### Build the Debug Server +For convenience, there is a build script `buildJdtlsExt.js` defined in `scripts/build`. It builds the Java Debug Server and then copies the .jar file into folder `vscode-java-debug/server`. +```bash +npm run build-server +``` +**NOTE**: If you didn't follow the steps to check out [vscode-java-debug](https://github.com/Microsoft/vscode-java-debug) and [java-debug](https://github.com/Microsoft/java-debug) in the same folder, please specify a correct `server_dir` in your [buildJdtlsExt.js](https://github.com/Microsoft/vscode-java-debug/blob/master/scripts/build/buildJdtlsExt.js#L8). + +#### Debug the Extension +Open folder `vscode-java-debug` in VS Code, or simply execute following commands if you have `code` in your system PATH. +```bash +cd vscode-java-debug +code . +``` +Press F5 to start debugging the extension, it will create a new window as the extension host. + +#### Debug the Debug Server +When you are debugging the extension, it is able to debug the Java process with local port `1044`. To remote debug the server, you can attach a Java debugger to `localhost:1044` using an IDE (Eclipse, IntelliJ IDEA, etc) or the Java Debugger for VS Code itself. + +Since we have checked in a valid [launch.json](https://github.com/Microsoft/java-debug/blob/master/.vscode/launch.json) to the repository, it would be easy to use the Java Debugger for VS Code itself to debug the server. +- Open folder `java-debug` in a new window in VS Code. +- Press F5 to attach. + +## Pull Requests +Before we can accept a pull request from you, you'll need to sign a [Contributor License Agreement (CLA)](https://github.com/Microsoft/vscode/wiki/Contributor-License-Agreement). It is an automated process and you only need to do it once. +To enable us to quickly review and accept your pull requests, always create one pull request per issue and [link the issue in the pull request](https://github.com/blog/957-introducing-issue-mentions). diff --git a/Configuration.md b/Configuration.md new file mode 100644 index 00000000..12e07c21 --- /dev/null +++ b/Configuration.md @@ -0,0 +1,411 @@ +# Java Debug Configuration + +## Table of Contents +* [Auto generate the launch.json](#auto-generate-the-launchjson) +* [Modify the launch.json](#modify-the-launchjson) + * [Main](#main) + * mainClass + * projectName + * [Arguments](#arguments) + * args + * vmArgs + * [Environment](#environment) + * console + * env + * [Don't step into the specified classes or methods](#dont-step-into-the-specified-classes-or-methods) + * stepFilters + * [Attach to a debuggee](#attach-to-a-debuggee) + * hostName + * port + * [Attach to mvn task](#attach-to-mvn-task) + * [Attach to embedded maven tomcat server](#attach-to-embedded-maven-tomcat-server) + * [Use javac as the builder and attach to java process](#use-javac-as-the-builder-and-attach-to-java-process) +* [Modify the settings.json (User Setting)](#modify-the-settingsjson-user-setting) + * java.debug.settings.console + * java.debug.settings.forceBuildBeforeLaunch + * java.debug.settings.onBuildFailureProceed + * java.debug.settings.hotCodeReplace + * java.debug.settings.enableRunDebugCodeLens +* [FAQ](#faq) + + +The debugger provides two kinds of configuration: *launch.json* and *settings.json* (User Settings), see the [README](https://github.com/Microsoft/vscode-java-debug#options) for the supported configuration list. launch.json is used to control the configuration per debug session, and the user setting is shared by the whole workspace or VS Code. + +## Auto generate the launch.json +When you run the program via `Run|Debug` CodeLens or `Run`/`Debug` context menu, the debugger automatically generates the launching configuration for you. +![runMenu](https://user-images.githubusercontent.com/14052197/67181889-715bb380-f410-11e9-9aef-c27ce697daa0.gif) + +## Modify the launch.json +If you don't see `.vscode/launch.json` in your VS Code window, you can go to "Run and Debug" viewlet to create an initial launch.json. +![create launch.json](https://user-images.githubusercontent.com/14052197/172300183-7758eb9b-5e61-485b-b238-a63a98a9fb11.png) + +On the other hand, the debugger provides multiple configuration templates to help you to easily add a new configuration. When you type `"java"` or `""` in launch.json, it will trigger auto-completion suggestions. +![launchConfig](https://user-images.githubusercontent.com/14052197/67182212-3908a500-f411-11e9-9467-48ba2f6e0e39.gif) + +In case you want to manually edit the configuration, below are the explanation and samples about the common debug configurations. +### Main +* `mainClass` - mainClass is used to define your program entry, and it's the most important configuration. The debugger provides three options to help you configure this key, see the samples below. + * `"mainClass": ""` + If you have no idea about what to set here, just leave it empty. The debugger will search all possible main classes from the workspace, then prompt you the list to choose for launch. +![emptyMainClass](https://user-images.githubusercontent.com/14052197/67261011-25bd0e80-f4d1-11e9-966d-3e82a4e261ce.gif) + + * `"mainClass": "${file}"` + If you have multiple main Java files, use this to auto switch to your current focus program. The debugger will resolve the main class from current active Java file, and set it as the launching main class. +![currentFile](https://user-images.githubusercontent.com/14052197/67183367-d7960580-f413-11e9-9773-7df735710054.gif) + + * `"mainClass": "com.microsoft.app.myApp"` + The fully qualified class name, generally it's filled by the debugger's auto generation. +![mainClass](https://user-images.githubusercontent.com/14052197/67190742-17181e00-f423-11e9-98ab-1c568f220ba7.gif) + +* `projectName` - The preferred project in which the debugger searches for classes. It's required for the evaluation feature. Most of the time, the debugger will auto generate the configuration for you. In case you want to manually configure it, here are the rules. + * When you open a maven project, the project name is the `artifactId`. + * When you open a gradle project, the project name is the `baseName` or the root folder name. + * When you open other Java files, leave the launch.json empty and allow the debugger auto generates the project name for you. + + > Pro Tip: The easiest way to get the project name is to install [Java Dependency Viewer](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-dependency) extension, the top node in the JAVA DEPENDENCIES view is your project name. +![java-dependency-viewer](https://user-images.githubusercontent.com/14052197/67185034-7cfea880-f417-11e9-8a3b-a3af1a9e86bb.png) + +### Arguments +* `args` - Program arguments which are used to pass application configuration to your program, and they are accessible via "args" String array parameter in your main method `public static void main(String[] args)`. It accepts three kinds of value, see the samples below. + * `"args": "arg0 arg1"` + Space separated String value. + ![programArgs](https://user-images.githubusercontent.com/14052197/67191536-5abf5780-f424-11e9-9664-6cc5805225bb.gif) + + * `"args": ["arg0", "arg1"]` + An array of String. + * `"args": "${command:SpecifyProgramArgs}"` + The debugger will prompt you with an input box to type the args value before launching the program. This is convenient when you have a program running against multiple data set. + ![specifyArgs](https://user-images.githubusercontent.com/14052197/67191890-0ff20f80-f425-11e9-8df2-5fd98e61c204.gif) + +* `vmArgs` - VM arguments are used to configure JVM options and platform properties. Most of these arguments have a prefix (-D, -X, -XX). For example, *-Xms256m* arguments defines the initial Java heap size to 256MB. And you can also use *-DpropertyName=propertyValue* to configure system properties for your program. These properties are read via API *System.getProperty(propertyName)*. It accepts a String or an array of String, see the samples below. + * `"vmArgs": "-Xms256m -Xmx1g -Dserver=production"` + Space separated String value. + * `"vmArgs": ["-Xms256m", "-Xmx1g", "-Dserver=production"]` + An array of String. + +### Environment +- `console` - The specified console to launch the current program. Current default value is `integratedTerminal`. You could customize it via the global user setting `java.debug.settings.console` for the whole workspace, or `console` in launch.json for each debug session. The `console` option in launch.json (if provided) takes precedence over `java.debug.settings.console` in user settings. + * `"console": "internalConsole"` + VS Code debug console (input stream not supported). If you're developing backend application, `internalConsole` is recommended. + ![internalConsole](https://user-images.githubusercontent.com/14052197/67193516-fef6cd80-f427-11e9-8a97-9014470c3a4d.gif) + + * `"console": "integratedTerminal"` + VS Code integrated terminal. If you're developing console application with io input requirements, you must use the terminal to accept user input. For example, use *Scanner* class for user input. + ![integratedTerminal](https://user-images.githubusercontent.com/14052197/67195762-251e6c80-f42c-11e9-89d0-9545560beea9.gif) + + * `"console": "externalTerminal"` + External terminal that can be configured in user settings. The user scenario is same as integrated terminal. The difference is opening an external terminal window to run your program. + ![externalTerminal](https://user-images.githubusercontent.com/14052197/67196194-eccb5e00-f42c-11e9-9d4c-6baa5eec18bc.gif) + +- `env` - The extra environment variables for the program. It's accessible via `System.getenv(key)`. It accepts key-value pairs. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Hello", + "request": "launch", + "env": { + "HOST": "127.0.0.1", + "PORT": 8080 + } + } + ] + } + ``` + +- `envFile` - Absolute path to a file containing environment variable definitions. Multiple files can be specified by providing an array of absolute paths + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Hello", + "request": "launch", + "envFile": "${workspaceFolder}/.env" + } + ] + } + ``` + +### Don't step into the specified classes or methods + +- `stepFilters` - Skip the specified classes or methods you don't want to step into. Class names should be fully qualified. Wildcard is supported. + - Skip the class loader. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Hello", + "request": "launch", + "stepFilters": { + "skipClasses": [ + "java.lang.ClassLoader", + ] + } + } + ] + } + ``` + ![skipClassLoader](https://user-images.githubusercontent.com/14052197/67254877-ff3bab00-f4b1-11e9-8da0-22b49935bd57.gif) + + - Skip the JDK classes. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Hello", + "request": "launch", + "stepFilters": { + "skipClasses": [ + "$JDK" + ] + } + } + ] + } + ``` + ![skipJDK](https://user-images.githubusercontent.com/14052197/67255028-9dc80c00-f4b2-11e9-9113-bef0c0bdf5cb.gif) + + - Skip the constructors and the synthetic methods. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Hello", + "request": "launch", + "stepFilters": { + "skipSynthetics": true, + "skipStaticInitializers": true, + "skipConstructors": true + } + } + ] + } + ``` + ![skipMethods](https://user-images.githubusercontent.com/14052197/67255209-83daf900-f4b3-11e9-8533-70f6ff941e8d.gif) + +### Attach to a debuggee +- `hostName` - The host name or ip address of the debuggee you want to attach. +- `port` - The port of the debuggee you want to attach. + +Before attaching to a debuggee, your debuggee program must be started with debug mode. The standard command line for debug mode is like `java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -cp bin MyApp`, and then the debug port of your debuggee is *5005*. +```json +{ + "type": "java", + "name": "Debug (Attach)", + "request": "attach", + "hostName": "localhost", + "port": 5005 +} +``` + +In some cases, you may want to start your program with the external builder and launcher, then you can configure these jobs in [tasks.json](https://code.visualstudio.com/docs/editor/tasks) and attach to it. For example, launching springboot application via mvn command, and then attach a debugger. +#### Attach to mvn task +1) Configure your command in .vscode/tasks.json - The mvn task is a background task, you should use *problemMatcher* filter to tell VS Code it's ready. + ```json + { + "label": "mvnDebug", + "type": "shell", + "command": "mvn spring-boot:run -Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005\"", + "isBackground": true, + "problemMatcher": [{ + "pattern": [{ + "regexp": "\\b\\B", + "file": 1, + "location": 2, + "message": 3 + }], + "background": { + "activeOnStart": true, + "beginsPattern": "^.*Attaching agents:.*", + "endsPattern": "^.*Listening for transport dt_socket at address.*" + } + }] + } + ``` +2) Configure `preLaunchTask` and the debug port in .vscode/launch.json. + ```json + { + "type": "java", + "name": "Debug (Attach)", + "request": "attach", + "hostName": "localhost", + "port": 5005, + "preLaunchTask": "mvnDebug" + } + ``` +3) F5 will launch the mvn task, and attach the debugger. See the demo. +![attachToMvn](https://user-images.githubusercontent.com/14052197/67262705-4f2d6880-f4d8-11e9-9e2d-9c35a6613c08.gif) + +#### Attach to embedded maven tomcat server + - pom.xml sample for embedded tomcat server. + ```xml + ... + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + ... + ``` + - The steps to attach to the embedded maven tomcat server. + 1) Use .vscode/tasks.json to configure *run-tomcat* and *stop-tomcat* tasks. + ```json + { + "version": "2.0.0", + "tasks": [ + { + "label": "run-tomcat", + "type": "shell", + "command": "MAVEN_OPTS=\"$MAVEN_OPTS -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n\" ./mvnw tomcat7:run", + "group": "build", + "isBackground": true, + "problemMatcher": [{ + "pattern": [{ + "regexp": "\\b\\B", + "file": 1, + "location": 2, + "message": 3 + }], + "background": { + "activeOnStart": true, + "beginsPattern": "^.*Listening for", + "endsPattern": "^.*transport dt_socket at address.*" + } + }] + }, + { + "label": "stop-tomcat", + "type": "shell", + "command": "echo ${input:terminate}}", + "problemMatcher": [] + } + ], + "inputs": [ + { + "id": "terminate", + "type": "command", + "command": "workbench.action.tasks.terminate", + "args": "run-tomcat" + } + ] + } + ``` + 2) Use .vscode/launch.json to configure the attach configuration. Use `preLaunchTask` to run tomcat before the attach, and `postDebugTask` to stop tomcat after the debug ends. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Debug (Attach)", + "request": "attach", + "hostName": "localhost", + "port": 5005, + "preLaunchTask": "run-tomcat", + "postDebugTask": "stop-tomcat" + } + ] + } + ``` + 3) F5 will auto start the tomcat server and attach the debugger. The demo below will show how to debug spring mvc in tomcat. + ![attachToEmbeddedTomcat](https://user-images.githubusercontent.com/14052197/67541153-80957680-f71a-11e9-9d59-e9aaa752fe33.gif) + + > If you want to try to debug your Java webapps in a standalone tomcat server, please try VS Code [Tomcat for Java](https://marketplace.visualstudio.com/items?itemName=adashen.vscode-tomcat) extension. + + > If you want to try to debug embedded tomcat server with gradle plugin, see the [gradle sample](https://github.com/microsoft/vscode-java-debug/issues/140#issuecomment-343656398). + +#### Use javac as the builder and attach to java process +1) Configure the javac builder and java runner jobs in .vscode/tasks.json. + ```json + { + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "javac -g -sourcepath ./**/*.java -d ./bin" + }, + { + "label": "debug", + "dependsOn": "build", + "type": "shell", + "command": "java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -cp bin app.SimpleCalc", + "isBackground": true, + "problemMatcher": [{ + "pattern": [{ + "regexp": "\\b\\B", + "file": 1, + "location": 2, + "message": 3 + }], + "background": { + "activeOnStart": true, + "beginsPattern": "^.*Listening for", + "endsPattern": "^.*transport dt_socket at address.*" + } + }] + } + ] + } + ``` +2) Configure `preLaunchTask` and the debug port in .vscode/launch.json. + ```json + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Debug (Attach)", + "request": "attach", + "hostName": "localhost", + "port": 5005, + "preLaunchTask": "debug" + } + ] + } + ``` +3) F5 will run the tasks and attach the debugger. See the demo. +![attachToJava](https://user-images.githubusercontent.com/14052197/67263956-3cb52e00-f4dc-11e9-9c78-6e66cb3d7c2b.gif) + +## Modify the settings.json (User Setting) +- `java.debug.settings.console` - The specified console to launch Java program, defaults to `integratedTerminal`. If you want to customize the console for a specific debug session, please use `console` option in launch.json instead. + ![terminal](https://user-images.githubusercontent.com/14052197/67256063-cf8fa180-f4b7-11e9-9455-77daad2f0ec9.gif) + +- `java.debug.settings.forceBuildBeforeLaunch` - Force building the workspace before launching java program, defaults to `true`. Sometimes you may be bothered with the message *"Build failed, do you want to continue?"*, you could disable this setting to suppress the message. + +- `java.debug.settings.onBuildFailureProceed` - Sometimes you may be bothered with the message *"Build failed, do you want to continue?"*, you could use this setting to suppress the message and proceed. + +- `java.debug.settings.hotCodeReplace` - Reload the changed Java classes during debugging, defaults to `manual`. It supports `manual`, `auto`, `never`. + - `manual` - Click the toolbar to apply the changes. + ![hcr](https://user-images.githubusercontent.com/14052197/67256313-f5697600-f4b8-11e9-9db6-54540b6350ad.png) + - `auto` - Automatically apply the changes after saved. + - `never` - Never apply the changes. + +- `java.debug.settings.enableRunDebugCodeLens` - Enable the code lens provider for the *Run* and *Debug* buttons over main entry points, defaults to `true`. + - `true` - Show the code lens. + ![codelens](https://user-images.githubusercontent.com/14052197/67256585-83922c00-f4ba-11e9-883f-2b3de3db2dfa.png) + - `false` - Show the Run/Debug link in the hover. + ![hover](https://user-images.githubusercontent.com/14052197/67256539-2ac29380-f4ba-11e9-8a5b-e5e1d0a27f0e.png) + +## FAQ +### 1. No way to take input. +If you are using *Scanner(System.in)* to get the user input, you need change the user setting `java.debug.settings.console` to `integratedTerminal` or `externalTerminal`. + +### 2. Code output is not in the DEBUG CONSOLE panel but Terminal. +By default, the debugger uses the terminal to launch your program for better accepting user input. And you will see the original command line is displayed at the top of the terminal. If you want a cleaner console to show your code output, you could try to change the user setting `java.debug.settings.console` to `internalConsole`. Please notice that the internal console (VS Code built-in DEBUG CONSOLE) doesn't support user input. + +### 3. The classpath changed when using terminal. +In order to avoid the command line being too long, the debugger will shorten your classpath into classpath.jar (for JDK 8 only) or argsfile (for JDK 9 and above) by default. If your program need read the original classpath value (for example, *System.getProperty("java.class.path")*), you could try to change the console to `internalConsole`, or use a higher JDK (9 and above) to launch your program. + +### 4. Failed to launch debuggee in terminal with TransportTimeoutException. +When launching failed in terminal, then you could try to change the user setting `java.debug.settings.console` to `internalConsole`. diff --git a/README.md b/README.md index 11e7d198..767764ad 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -# Java Debug Extension for Visual Studio Code +# Debugger for Java [![Gitter](https://badges.gitter.im/Microsoft/vscode-java-debug.svg)](https://gitter.im/Microsoft/vscode-java-debug) +[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/microsoft/vscode-java-debug/build.yml)](https://github.com/microsoft/vscode-java-debug/actions/workflows/build.yml?query=branch%3Amain) ## Overview -A lightweight Java Debugger based on [Java Debug Server](https://github.com/Microsoft/java-debug). It works with [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) to allow users debugging Java code using Visual Studio Code (VS Code). Here's a list of features: +A lightweight Java Debugger based on [Java Debug Server](https://github.com/Microsoft/java-debug) which extends the [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java). It allows users to debug Java code using Visual Studio Code (VS Code). Here's a list of features: - Launch/Attach -- Breakpoints +- Breakpoints/Conditional Breakpoints/Logpoints - Exceptions - Pause & Continue - Step In/Out/Over @@ -14,6 +15,15 @@ A lightweight Java Debugger based on [Java Debug Server](https://github.com/Micr - Callstacks - Threads - Debug console +- Evaluation +- Hot Code Replace +- No-Config Debug (debug Java apps without launch.json) +- **[AI]** AI-Assisted Debugging (GitHub Copilot integration) + +## Requirements +- JDK (version 1.8.0 or later) +- VS Code (version 1.19.0 or later) +- [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) (version 0.14.0 or later) ## Install @@ -27,44 +37,179 @@ ext install vscode-java-debug ## Use - Launch VS Code -- Open a Java project (Maven/Gradle/Eclipse) +- Open a Java project (Maven/Gradle/Eclipse/Single Java file) - Open a Java file to activate the extensions -- Add debug configurations and edit launch.json - - To launch: specify `mainClass` - - To attach: specify `hostName` and `port` -- Press F5 +- Press `F5` Please also check the documentation of [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) if you have trouble setting up your project. +## No-Config Debug + +You can now debug Java applications without creating a `launch.json` file! Simply open a terminal in VS Code and use the `debugjava` command: + +```bash +# Debug a main class +debugjava -cp bin com.example.Main + +# Debug a JAR file +debugjava -jar target/myapp.jar + +# Debug with arguments +debugjava -cp bin com.example.Main arg1 arg2 +``` + +The debugger will automatically attach. See [No-Config Debug Documentation](bundled/scripts/noConfigScripts/README.md) for more details. + +## AI-Assisted Debugging + +When using GitHub Copilot Chat, you can now ask AI to help you debug Java applications! The extension provides a Language Model Tool that enables natural language debugging: + +- "Debug my Spring Boot application" +- "Debug the Main class in this project" +- "Debug Calculator with arguments 10 and 5" + +The AI will automatically: +1. Detect your project type (Maven/Gradle/VS Code) +2. Build/compile your project +3. Start debugging with appropriate configuration + +See [Language Model Tool Documentation](bundled/agents/README.md) for more details. + ## Options ### Launch -- `mainClass` (required) - The main class of the program (fully qualified name, e.g. com.xyz.MainClass). +- `mainClass` - The fully qualified name of the class containing the main method. If not specified, the debugger automatically resolves the possible main class from current project. + - `${file}` - Current Java file. + - `com.mypackage.Main` - The fully qualified class name. + - `com.java9.mymodule/com.mypackage.Main` - The fully qualified module name and class name. + - `/path/to/Main.java` - The file path of the main class. - `args` - The command line arguments passed to the program. + - `"${command:SpecifyProgramArgs}"` - Prompt user for program arguments. + - A space-separated string or an array of string. - `sourcePaths` - The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories. -- `classPaths` - The classpaths for launching the JVM. If not specified, the debugger will automatically resolve from current project. -- `encoding` - The `file.encoding` setting for the JVM. If not specified, 'UTF-8' will be used. Possible values can be found in http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html. -- `vmArgs` - The extra options and system properties for the JVM (e.g. -Xms\ -Xmx\ -D\=\). -- `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. +- `modulePaths` - The modulepaths for launching the JVM. If not specified, the debugger will automatically resolve from current project. If multiple values are specified, the debugger will merge them together. + - `$Auto` - Automatically resolve the modulepaths of current project. + - `$Runtime` - The modulepaths within 'runtime' scope of current project. + - `$Test` - The modulepaths within 'test' scope of current project. + - `!/path/to/exclude` - Exclude the specified path from modulepaths. + - `/path/to/append` - Append the specified path to the modulepaths. +- `classPaths` - The classpaths for launching the JVM. If not specified, the debugger will automatically resolve from current project. If multiple values are specified, the debugger will merge them together. + - `$Auto` - Automatically resolve the classpaths of current project. + - `$Runtime` - The classpaths within 'runtime' scope of current project. + - `$Test` - The classpaths within 'test' scope of current project. + - `!/path/to/exclude` - Exclude the specified path from classpaths. + - `/path/to/append` - Append the specified path to the classpaths. +- `encoding` - The `file.encoding` setting for the JVM. Possible values can be found in https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html. +- `vmArgs` - The extra options and system properties for the JVM (e.g. -Xms\ -Xmx\ -D\=\), it accepts a string or an array of string. +- `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. It is required when the workspace has multiple java projects, otherwise the expression evaluation and conditional breakpoint may not work. +- `cwd` - The working directory of the program. Defaults to `${workspaceFolder}`. +- `env` - The extra environment variables for the program. +- `envFile` - Absolute path to a file containing environment variable definitions. Multiple files can be specified by providing an array of absolute paths +- `stopOnEntry` - Automatically pause the program after launching. +- `console` - The specified console to launch the program. If not specified, use the console specified by the `java.debug.settings.console` user setting. + - `internalConsole` - VS Code debug console (input stream not supported). + - `integratedTerminal` - VS Code integrated terminal. + - `externalTerminal` - External terminal that can be configured in user settings. +- `shortenCommandLine` - When the project has long classpath or big VM arguments, the command line to launch the program may exceed the maximum command line string limitation allowed by the OS. This configuration item provides multiple approaches to shorten the command line. Defaults to `auto`. + - `none` - Launch the program with the standard command line 'java [options] classname [args]'. + - `jarmanifest` - Generate the classpath parameters to a temporary classpath.jar file, and launch the program with the command line 'java -cp classpath.jar classname [args]'. + - `argfile` - Generate the classpath parameters to a temporary argument file, and launch the program with the command line 'java @argfile [args]'. This value only applies to Java 9 and higher. + - `auto` - Automatically detect the command line length and determine whether to shorten the command line via an appropriate approach. +- `stepFilters` - Skip specified classes or methods when stepping. + - `classNameFilters` - [**Deprecated** - replaced by `skipClasses`] Skip the specified classes when stepping. Class names should be fully qualified. Wildcard is supported. + - `skipClasses` - Skip the specified classes when stepping. + - `$JDK` - Skip the JDK classes from the default system bootstrap classpath, such as rt.jar, jrt-fs.jar. + - `$Libraries` - Skip the classes from application libraries, such as Maven, Gradle dependencies. + - `java.*` - Skip the specified classes. Wildcard is supported. + - `java.lang.ClassLoader` - Skip the classloaders. + - `skipSynthetics` - Skip synthetic methods when stepping. + - `skipStaticInitializers` - Skip static initializer methods when stepping. + - `skipConstructors` - Skip constructor methods when stepping. +- `javaExec` - The path to java executable to use. By default, the project JDK's java executable is used. ### Attach -- `hostName` (required) - The host name or IP address of remote debuggee. -- `port` (required) - The debug port of remote debuggee. +- `hostName` (required, unless using `processId`) - The host name or IP address of remote debuggee. +- `port` (required, unless using `processId`) - The debug port of remote debuggee. +- `processId` - Use process picker to select a process to attach, or Process ID as integer. + - `${command:PickJavaProcess}` - Use process picker to select a process to attach. + - an integer pid - Attach to the specified local process. - `timeout` - Timeout value before reconnecting, in milliseconds (default to 30000ms). - `sourcePaths` - The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories. -- `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. +- `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. It is required when the workspace has multiple java projects, otherwise the expression evaluation and conditional breakpoint may not work. +- `stepFilters` - Skip specified classes or methods when stepping. + - `classNameFilters` - [**Deprecated** - replaced by `skipClasses`] Skip the specified classes when stepping. Class names should be fully qualified. Wildcard is supported. + - `skipClasses` - Skip the specified classes when stepping. + - `$JDK` - Skip the JDK classes from the default system bootstrap classpath, such as rt.jar, jrt-fs.jar. + - `$Libraries` - Skip the classes from application libraries, such as Maven, Gradle dependencies. + - `java.*` - Skip the specified classes. Wildcard is supported. + - `java.lang.ClassLoader` - Skip the classloaders. + - `skipSynthetics` - Skip synthetic methods when stepping. + - `skipStaticInitializers` - Skip static initializer methods when stepping. + - `skipConstructors` - Skip constructor methods when stepping. ### User Settings - `java.debug.logLevel`: minimum level of debugger logs that are sent to VS Code, defaults to `warn`. +- `java.debug.settings.showHex`: show numbers in hex format in "Variables" viewlet, defaults to `false`. +- `java.debug.settings.showStaticVariables`: show static variables in "Variables" viewlet, defaults to `false`. +- `java.debug.settings.showQualifiedNames`: show fully qualified class names in "Variables" viewlet, defaults to `false`. +- `java.debug.settings.showLogicalStructure`: show the logical structure for the Collection and Map classes in "Variables" viewlet, defaults to `true`. +- `java.debug.settings.showToString`: show 'toString()' value for all classes that override 'toString' method in "Variables" viewlet, defaults to `true`. +- `java.debug.settings.maxStringLength`: the maximum length of string displayed in "Variables" or "Debug Console" viewlet, the string longer than this length will be trimmed, defaults to `0` which means no trim is performed. +- `java.debug.settings.numericPrecision`: the precision when formatting doubles in "Variables" or "Debug Console" viewlet. +- `java.debug.settings.hotCodeReplace`: Reload the changed Java classes during debugging, defaults to `manual`. See the [wiki page](https://github.com/Microsoft/vscode-java-debug/wiki/Hot-Code-Replace) for more information about usages and limitations. + - `manual` - Click the toolbar to apply the changes. + - `auto` - Automatically apply the changes after compilation. This only works when `'java.autobuild.enabled'` is on. + - `never` - Never apply the changes. +- `java.debug.settings.enableRunDebugCodeLens`: enable the code lens provider for the run and debug buttons over main entry points, defaults to `true`. +- `java.debug.settings.forceBuildBeforeLaunch`: force building the workspace before launching java program, defaults to `true`. +- `java.debug.settings.onBuildFailureProceed`: Force to proceed when build fails, defaults to false. +- `java.debug.settings.console`: The specified console to launch Java program, defaults to `integratedTerminal`. If you want to customize the console for a specific debug session, please modify the 'console' config in launch.json. + - `internalConsole` - VS Code debug console (input stream not supported). + - `integratedTerminal` - VS Code integrated terminal. + - `externalTerminal` - External terminal that can be configured in user settings. +- `java.debug.settings.exceptionBreakpoint.exceptionTypes`: Specifies a set of exception types you want to break on, e.g. `java.lang.NullPointerException`. A specific exception type and its subclasses can be selected for caught exceptions, uncaught exceptions, or both can be selected. +- `java.debug.settings.exceptionBreakpoint.allowClasses`: Specifies the allowed locations where the exception breakpoint can break on. Wildcard is supported, e.g. `java.*`, `*.Foo`. +- `java.debug.settings.exceptionBreakpoint.skipClasses`: Skip the specified classes when breaking on exception. + - `$JDK` - Skip the JDK classes from the default system bootstrap classpath, such as rt.jar, jrt-fs.jar. + - `$Libraries` - Skip the classes from application libraries, such as Maven, Gradle dependencies. + - `java.*` - Skip the specified classes. Wildcard is supported. + - `java.lang.ClassLoader` - Skip the classloaders. +- `java.debug.settings.stepping.skipClasses`: Skip the specified classes when stepping. + - `$JDK` - Skip the JDK classes from the default system bootstrap classpath, such as rt.jar, jrt-fs.jar. + - `$Libraries` - Skip the classes from application libraries, such as Maven, Gradle dependencies. + - `java.*` - Skip the specified classes. Wildcard is supported. + - `java.lang.ClassLoader` - Skip the classloaders. +- `java.debug.settings.stepping.skipSynthetics`: Skip synthetic methods when stepping. +- `java.debug.settings.stepping.skipStaticInitializers`: Skip static initializer methods when stepping. +- `java.debug.settings.stepping.skipConstructors`: Skip constructor methods when stepping. +- `java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest`: The maximum number of variables or fields that can be requested in one JDWP request. The higher the value, the less frequently debuggee will be requested when expanding the variable view. Also a large number can cause JDWP request timeout. Defaults to 100. +- `java.debug.settings.jdwp.requestTimeout`: The timeout (ms) of JDWP request when the debugger communicates with the target JVM. Defaults to 3000. +- `java.debug.settings.jdwp.async`: Experimental: Controls whether the debugger is allowed to send JDWP commands asynchronously. Async mode can improve remote debugging response speed on high-latency networks. Defaults to `auto`, and automatically switch to async mode when the latency of a single jdwp request exceeds 15ms during attach debugging. + - `auto` (Default) + - `on` + - `off` +- `java.debug.settings.vmArgs`: The default VM arguments to launch the Java program. Eg. Use '-Xmx1G -ea' to increase the heap size to 1GB and enable assertions. If you want to customize the VM arguments for a specific debug session, please modify the 'vmArgs' config in launch.json. +- `java.debug.settings.debugSupportOnDecompiledSource`: [Experimental]: Enable debugging support on the decompiled source code. Be aware that this feature may affect the loading speed of Call Stack Viewlet. You also need [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java)@1.20.0 or higher to use this feature. +- `java.debug.settings.suspendAllThreads`: Suspend all threads when hitting a breakpoint or stopping for an exception. Takes effect only for new debug sessions; changes during a running session don’t apply. +- `java.silentNotification`: Controls whether notifications can be used to report progress. If true, use status bar to report progress instead. Defaults to `false`. + +> Pro Tip: The documentation [Configuration.md](https://github.com/microsoft/vscode-java-debug/blob/master/Configuration.md) provides lots of samples to demonstrate how to use these debug configurations, recommend to take a look. + +## Troubleshooting +Reference the [Troubleshooting Guide](https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting.md) for common errors. +Reference the [Troubleshooting Guide for Encoding Issues](https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting_encoding.md) for encoding issues. + +## Contributing +If you are interested in fixing issues and contributing directly to the code base, please see the document [How to Contribute](https://github.com/microsoft/vscode-java-debug/blob/main/CONTRIBUTING.md). ## Feedback and Questions You can find the full list of issues at [Issue Tracker](https://github.com/Microsoft/vscode-java-debug/issues). You can submit a [bug or feature suggestion](https://github.com/Microsoft/vscode-java-debug/issues/new), and participate community driven [![Gitter](https://badges.gitter.im/Microsoft/vscode-java-debug.svg)](https://gitter.im/Microsoft/vscode-java-debug) ## License -This extension is licensed under [MIT License](https://github.com/Microsoft/vscode-arduino/blob/master/LICENSE.txt). +This extension is licensed under [MIT License](https://github.com/Microsoft/vscode-java-debug/blob/master/LICENSE.txt). ## Data/Telemetry -Java Debug Extension for Visual Studio Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](http://go.microsoft.com/fwlink/?LinkId=521839) to learn more.  \ No newline at end of file +VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don't wish to send usage data to Microsoft, you can set the `telemetry.telemetryLevel` setting to `"off"`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..e138ec5d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt new file mode 100644 index 00000000..063da394 --- /dev/null +++ b/ThirdPartyNotices.txt @@ -0,0 +1,174 @@ +vscode-java-debug + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. + +1. omichelsen/compare-versions (https://github.com/omichelsen/compare-versions) +2. motdotla/dotenv (https://github.com/motdotla/dotenv) +3. lodash/lodash (https://github.com/lodash/lodash) +4. uuidjs/uuid (https://github.com/uuidjs/uuid) +5. Eskibear/vscode-extension-telemetry-wrapper (https://github.com/Eskibear/vscode-extension-telemetry-wrapper) +6. Microsoft/vscode-languageserver-node (https://github.com/Microsoft/vscode-languageserver-node) + + +%% omichelsen/compare-versions NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) 2015-2017 Ole Michelsen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF omichelsen/compare-versions NOTICES AND INFORMATION + +%% motdotla/dotenv NOTICES AND INFORMATION BEGIN HERE +========================================= +BSD-2-Clause License + +Copyright (c) 2015, Scott Motte +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +========================================= +END OF motdotla/dotenv NOTICES AND INFORMATION + +%% lodash/lodash NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License + +Copyright JS Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. +========================================= +END OF lodash/lodash NOTICES AND INFORMATION + +%% uuidjs/uuid NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF uuidjs/uuid NOTICES AND INFORMATION + +%% Eskibear/vscode-extension-telemetry-wrapper NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright 2018 Yan Zhang + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF Eskibear/vscode-extension-telemetry-wrapper NOTICES AND INFORMATION + +%% Microsoft/vscode-languageserver-node NOTICES AND INFORMATION BEGIN HERE +========================================= +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF Microsoft/vscode-languageserver-node NOTICES AND INFORMATION \ No newline at end of file diff --git a/Troubleshooting.md b/Troubleshooting.md new file mode 100644 index 00000000..b47793cb --- /dev/null +++ b/Troubleshooting.md @@ -0,0 +1,138 @@ +# Troubleshooting + +This document provides the information needed to troubleshoot common errors of Debugger for Java (the debugger). If it does not cover the problem you are seeing, please [log an issue](https://github.com/Microsoft/vscode-java-debug/issues) instead. + +## Java Language Support extension fails to start. +The debugger works with [Language Support for Java(TM) by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) (the language server) for source mapping and project support. If the language server fails to start, the debugger will not work as expected. Here is a simple way to check whether the language server is started. Open a .java or a Java project folder in VS Code, and then check the icon at the right side of the status bar. You should see the 👍 icon if the language server is loaded correctly. + + ![status indicator](https://raw.githubusercontent.com/redhat-developer/vscode-java/master/images/statusMarker.png). + +### Try: +1. If you get the error *"The JAVA_HOME environment variable points to a missing folder"* or *"Java runtime could not be located"*, please make sure that the environment variable JAVA_HOME points to a valid JDK. Otherwise, ignore this step. +2. Open your Maven *pom.xml* file or Gradle *build.gradle* file, then run VS Code command *"Java: Update project configuration"* to force the language server to update the project configuration/classpath. +3. Run VS Code command *"Java: Clean the Java language server workspace"* to clean the stale workspace cache. +4. Try more [troubleshooting guide](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting) from the language server product site. + +## Build failed, do you want to continue? +### Reason: +The error indicates your workspace has build errors. There are two kinds of build errors. One is compilation error for source code, the other is project error. + +### Try: +1. Open VS Code PROBLEMS View, and fix the errors there. +2. Run VS Code command *"Java: Open Java language server log file"*, search keyword `build/building workspace` to find more details for the build errors. +3. If still cannot find out what errors, then reference the [language server troubleshooting](#try) paragraph to [2]update project configuration, and [3]clean workspace cache. + +## x.java isn't on the classpath. Only syntax errors will be reported +### Reason: +This error indicates the Java file you opened isn't on the classpath of any project, and no .class file will be generated because Java language server only auto builds Java source files on the project classpath. If you try to run or debug this Java file, you may get the error "Could not find or load main class". + +### Try: +1. Go to *File Explorer*, right click the folder containing your Java file, and run the menu *"Add Folder to Java Source Path"* to mark the containing folder as a Java source root. +2. Run VS Code command *"Java: List all Java source paths"* to check whether the containing folder is added as a Java source root. + +## Program Error: Could not find or load main class x +### Reason: +You configure the incorrect main class name in `mainClass` of *launch.json*, or your Java file is not on the classpath. + +### Try: +1. Check whether the class name specified in `mainClass` exists and is in the right form. +2. Run VS Code command *"Java: List all Java source paths"* to show all source paths recognized by the workspace. +3. Check the Java file you are running is under any source path? If not, go to *File Explorer*, right click the folder containing your Java file, and run the menu *"Add Folder to Java Source Path"* to mark the containing folder as a Java source root. +4. Run VS Code command *"Java: Force Java compilation"* to rebuild your workspace. +5. If the problem persists, it's probably because the language server doesn't load your project correctly. Please reference the [language server troubleshooting](#try) paragraph for more troubleshooting info. + +## Program throws ClassNotFoundException +### Reason: +This error indicates your application attempts to reference some classes which are not found in the entire classpaths. + +### Try: +1. Check whether you configure the required libraries in the dependency settings file (e.g. *pom.xml*). +2. If you have recently modified the *pom.xml* or *build.gradle* config file, you need right click on *pom.xml* or *build.gradle* file and then run the menu *"Update project configuration"* to force the language server to update the project configuration/classpath. +3. Run VS Code command *"Java: Force Java compilation"* to force the language server to rebuild the current project. +4. If the problem persists, it's probably because the language server doesn't load your project correctly. Please reference the [language server troubleshooting](#try) paragraph for more troubleshooting info. + +## Program throws UnsupportedClassVersionError +Below is a typical error message. + +![image](https://user-images.githubusercontent.com/14052197/78854443-ed47c780-7a53-11ea-8317-d8b097dfba99.png) + +### Reason: +The compiled classes are not compatible with the runtime JDK. + +The class file version `57.65535` stands for Java 13 preview, where the major version `57` stands for Java 13, the minor version `65535` stands for preview feature. Similarly `58.65535` stands for Java 14 preview. + +The error says the compiled class is `57.65535`, but the runtime JDK only recognizes class file version `58.65535`. That's because the preview feature is not backward compatible, i.e. JVM 14 doesn't support 13 preview feature. The [openjdk](https://openjdk.java.net/jeps/12) website has claimed the reason that it would be costly for JDK 14 to support preview features from JDK 13 which were changed or dropped in response to feedback. + +One possible root cause for this error is your runtime JDK is the latest JDK but the upstream [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) extension doesn't catch up the support yet. + +### Try: +1. Try to update [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) to the latest, and then try step 3 to rebuild the workspace. +2. If it doesn't work, then try to install an older JDK version, set its installation folder to "java.home" user setting in _.vscode/settings.json_ and reopen your VS Code workspace. +3. Click **F1** -> **Java: Force Java compilation** -> **Full** to rebuild the workspace. +4. If it still doesn't work, then try **F1** -> **Java: Clean the Java language server workspace** to clean the cache. + +## Failed to complete hot code replace: +### Reason: +This error indicates you are doing `Hot Code Replace`. The `Hot Code Replace` feature depends on the underlying JVM implementation. If you get this error, that indicates the new changes cannot be hot replaced by JVM. + +### Try: +1. Check the HCR limitation from the [wiki](https://github.com/microsoft/vscode-java-debug/wiki/Hot-Code-Replace). +2. Restart your application to apply the new changes. Or ignore the message, and continue to debug. +3. You can disable the hot code replace feature by changing the user setting `"java.debug.settings.hotCodeReplace": "never"`. + +## Please specify the host name and the port of the remote debuggee in the launch.json. +### Reason: +This error indicates you are debugging a remote Java application. The reason is that you don't configure the remote machine's host name and debug port correctly. + +### Try: +1. Check whether the remote Java application is launched in debug mode. The typical command to enable debug mode is like *"java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -classpath \ MyMainClass"*, where the parameter *"address=5005"* represents the target JVM exposes *5005* as the debug port. +2. Check the debug port is not blocked by the remote machine's firewall. + +## Failed to evaluate. Reason: Cannot evaluate because the thread is resumed. +### Reason: +There are two possible reasons for this error. +- Reason 1: you try to evaluate an expression when the target thread is running. Evaluation only works when your program is on suspend, for example, stopping at a breakpoint or stepping in/out/over. +- Reason 2: you take the VS Code DEBUG CONSOLE view for program input by mistake. DEBUG CONSOLE only accepts input for evaluation, not for program console input. + +### Try: +1. For Reason 1, try to add a breakpoint and stop your program there, then evaluate the expression. +2. For Reason 2, try to change the `console` option in the *launch.json* to `externalTerminal` or `integratedTerminal`. This is the official solution for program console input. + +## Cannot find a class with the main method +### Reason: +When the `mainClass` is unconfigured in the *launch.json*, the debugger will resolve a class with main method automatically. This error indicates the debugger doesn't find any main class in the whole workspace. + +### Try: +1. Check at least one main class exists in your workspace. +2. If no main class exists, please create a main class first. Otherwise, it's probably because the language server fails to start. Please reference the [language server troubleshooting](#try) paragraph for more troubleshooting info. + +## No delegateCommandHandler for vscode.java.startDebugSession when starting Debugger +### Reason: +Cause of error is for now unknown, but something caused vscode java support and debugger to not be configured correctly. + +### Try: +1. Restart VS Code and the issue should disappear +2. If it continues to error try restart again, and if still a problem open an issue at [vscode-java-debug](https://github.com/Microsoft/vscode-java-debug) + +## Failed to resolve classpath: +### Reason: +Below are the common failure reasons. +- 'C:\demo\com\microsoft\app\Main.java' is not a valid class name. +- Main class 'com.microsoft.app.Main' doesn't exist in the workspace. +- Main class 'com.microsoft.app.Main' isn't unique in the workspace. +- The project 'demo' is not a valid java project. + +In launch mode, the debugger resolves the classpaths automatically based on the given `mainClass` and `projectName`. It looks for the class specified by `mainClass` as the entry point for launching an application. If there are multiple classes with the same name in the current workspace, the debugger uses the one inside the project specified by `projectName`. + +### Try: +1. Check whether the class name specified in `mainClass` exists and is in the right form. The debugger only works with fully qualified class names, e.g. `com.microsoft.app.Main`. +2. Check whether the `projectName` is correct. The actual project name is not always the same to the folder name you see in the File Explorer. Please check the value specified by `projectDescription/name` in the *.project* file, or the `artifactId` in the *pom.xml* for maven project, or the folder name for gradle project. +3. If the problem persists, please try to use the debugger to regenerate the debug configurations in *launch.json*. Remove the existing *launch.json* file and press F5. The debugger will automatically generate a new *launch.json* with the right debug configurations. + +## Request type "xyz" is not supported. Only "launch" and "attach" are supported. +### Reason: +The value specified in `request` option of *launch.json* is incorrect. + +### Try: +1. Reference the VS Code official document [launch configurations](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) about how to configure *launch.json*. +2. Try to use the debugger to regenerate the debug configurations in *launch.json*. Remove the existing *launch.json* file and press F5. The debugger will automatically generate a new *launch.json* with the right debug configurations. diff --git a/Troubleshooting_encoding.md b/Troubleshooting_encoding.md new file mode 100644 index 00000000..834d3972 --- /dev/null +++ b/Troubleshooting_encoding.md @@ -0,0 +1,84 @@ +# Troubleshooting Guide for Encoding Issues + +This document provides a guide mostly for Windows users to solve common Java encoding issues. + +## 1. Background +Computers can only understand the binary data such as 0 and 1, and it uses charset to encode/decode the data into real-world characters. When two processes interact with each other for I/O, they have to use the compatible charset for encoding and decoding, otherwise garbled characters will probably appear. macOS and Linux use UTF-8 everywhere and encoding is not a problem for them. For Windows, however, the default charset is not UTF-8 and is platform-dependent, which can lead to inconsistent encoding between different tools. + +## 2. Common Problems +Below are the typical encoding problems when running a Java program on Windows terminal. + +2.1) The file or directory name contains unicode characters, Java launcher cannot find the corresponding classpath or main class well. +``` +C:\Test>java -cp 中文目录 Hello +Error: Could not find or load main class Hello +``` + +``` +C:\Test>java -cp ./Exercises 练习 +Error: Could not find or load main class ?? +Caused by: java.lang.ClassNotFoundException: ?? +``` + +2.2) The string literals with unicode characters appear garbled when printed to the terminal. +```java +public class Hello { + public static void main(String[] args) { + System.out.println("你好!"); + } +} +``` + +``` +C:\Test>java -cp ./Exercises Hello +??! +``` + +2.3) Garbled characters when Java program interacts with terminal for I/O. + +```java +import java.util.Scanner; + +public class Hello { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + System.out.println(scanner.nextLine()); + } +} +``` + +``` +C:\Test>chcp +65001 + +C:\Test>java -Dfile.encoding=UTF-8 -cp ./Exercises Hello +你好 +�� +``` + +## 3.Troubleshooting Suggestions +The following diagram shows the parts of encoding that may be involved when writing and running Java in VS Code. +

+ encoding_diagram +
+ Encoding on Windows +

+ +- During the compilation phase, VS Code Java extension uses the file encoding from VS Code settings to read .java source files and compile .class files. Encoding is consistent between editor and Java extension. + +- During the run/debug phase, Java extension launches the application in the terminal by default. Most encoding problems occur because the terminal and JVM use incompatible charsets for data processing, or use charsets that do not support the target unicode characters. + - JVM - Uses a default charset compatible with the system locale of Windows platform, and you can change it by using the JVM argument `"-Dfile.encoding"`, or by using `"encoding"` setting in launch.json when running through Java debugger extension. + - Windows Terminals - Uses code page to handle encoding, and you can use `"chcp"` command to view and change the code page. + +To solve the encoding problems, the straightforward idea is to use UTF-8 in all toolchains. But unfortunately Windows terminals (such as cmd) do not support UTF-8 perfectly. Therefore, the alternative idea is to let the terminal and JVM use compatible character sets for data processing. + +### 3.1) Fix Suggestion : Change system locale to the target language. + +On Windows, when you change the system locale, the default Java charset will be changed to one compatible with the system locale, and the terminal's (e.g. cmd) code page will be automatically updated to be consistent as well. Therefore, changing system locale to the target language can solve most encoding issues on Windows. This is also suggested by Java site https://www.java.com/en/download/help/locale.html. + +The following screenshot shows how to change the system locale in Windows. for example, if I want to use a terminal to enter Chinese characters into a Java program, I can set the Windows system locale to Chinese. The default Java charset will be `"GBK"` and the cmd codepage will be `"936"`, which will support Chinese characters nicely. +

+ change_system_locale +
+ Change System Locale +

diff --git a/bundled/agents/README.md b/bundled/agents/README.md new file mode 100644 index 00000000..3dab2c1d --- /dev/null +++ b/bundled/agents/README.md @@ -0,0 +1,195 @@ +# Java Debug Agent + +The Java Debug Agent is an AI-powered debugging assistant that integrates with GitHub Copilot Chat to help you debug Java applications using natural language. + +## Overview + +Instead of manually setting breakpoints and inspecting variables, you can simply describe your debugging task in natural language. The agent will: + +1. Analyze your code to form hypotheses +2. Set targeted breakpoints +3. Inspect variables and evaluate expressions +4. Find the root cause of bugs + +## Requirements + +- VS Code 1.95.0 or later +- [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) +- [Debugger for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug) +- GitHub Copilot Chat extension + +## Getting Started + +### 1. Open Copilot Chat + +Press `Ctrl+Shift+I` (Windows/Linux) or `Cmd+Shift+I` (macOS) to open Copilot Chat. + +### 2. Switch to JavaDebug Agent Mode + +In the Copilot Chat panel, click on the agent selector (usually shows "Copilot" or current agent name) and select **JavaDebug** from the dropdown list. + +![Select Agent](images/javadebug.png) + + +### 3. Enter Your Debugging Request + +Once in JavaDebug mode, simply type your debugging request: + +``` +Why am I getting a NullPointerException in OrderService? +``` + +![Invoke Agent](images/invoke-agent.png) + + +### 4. Let the Agent Work + +The agent will: +- Read relevant code files +- Form a hypothesis about the bug +- Set breakpoints at strategic locations +- Start or attach to a debug session +- Inspect variables to verify the hypothesis +- Report the root cause + +![Agent Working](images/agent-working.png) + + +## Example Usage + +### Debug a NullPointerException + +``` +I'm getting NPE when calling userService.getUser() +``` + +The agent will: +1. Read `UserService.java` +2. Hypothesize which variable might be null +3. Set a breakpoint before the NPE +4. Check variable values +5. Report: "The `user` variable is null because `findById()` returns null when ID doesn't exist" + +### Debug Wrong Calculation Result + +``` +The calculateTotal() method returns wrong value +``` + +### Debug with Specific Input + +``` +Debug processOrder with orderId=456 +``` + +### Debug Multi-threaded Issues + +``` +I suspect a race condition in the worker threads +``` + +## Agent Capabilities + +| Capability | Description | +|------------|-------------| +| **Start Debug Session** | Launch or attach to Java applications | +| **Set Breakpoints** | Set conditional or unconditional breakpoints | +| **Inspect Variables** | View local variables, fields, and objects | +| **Evaluate Expressions** | Execute Java expressions in debug context | +| **Step Through Code** | Step over, step into, step out | +| **Multi-thread Support** | Debug concurrent applications | +| **Stack Trace Analysis** | View and navigate call stacks | + +## How It Works + +The agent uses **hypothesis-driven debugging**: + +``` +┌─────────────────────────────────────────┐ +│ 1. STATIC ANALYSIS │ +│ Read code, understand the problem │ +└─────────────────┬───────────────────────┘ + ↓ +┌─────────────────────────────────────────┐ +│ 2. FORM HYPOTHESIS │ +│ "Variable X is null at line Y" │ +└─────────────────┬───────────────────────┘ + ↓ +┌─────────────────────────────────────────┐ +│ 3. SET BREAKPOINT │ +│ At the location to verify │ +└─────────────────┬───────────────────────┘ + ↓ +┌─────────────────────────────────────────┐ +│ 4. VERIFY │ +│ Check if hypothesis is correct │ +│ ├─ YES → Report root cause │ +│ └─ NO → Form new hypothesis │ +└─────────────────────────────────────────┘ +``` + +## Tips for Best Results + +### Stay in Agent Mode + +Make sure you're in **JavaDebug** agent mode (check the agent selector in Chat panel). If you switch back to default Copilot mode, the debugging tools won't be available. + +### Be Specific + +``` +✅ Good: "Why does getUserById return null when id=123?" +❌ Vague: "Something is wrong" +``` + +### Mention the Error + +``` +✅ Good: "Getting ArrayIndexOutOfBoundsException in processItems()" +❌ Vague: "Debug processItems" +``` + +### Provide Context + +``` +✅ Good: "The order total is $0 instead of $150 for order 456" +❌ Vague: "Wrong calculation" +``` + +## Troubleshooting + +### Agent Can't Find the File + +Make sure the Java project is properly loaded. Check that: +- The Java extension is activated (look for Java icon in status bar) +- The project is imported (check Java Projects view) + +### Debug Session Won't Start + +Ensure: +- Your project compiles successfully +- No other debug session is running +- The main class can be found + +### Breakpoint Not Hit + +The agent will tell you to trigger the scenario. You need to: +1. Run the part of your application that executes the code +2. The breakpoint will be hit when the code path is executed + +## Limitations + +- Requires an active Java project with proper configuration +- Cannot debug remote applications without proper attach configuration +- Performance may vary with large codebases + +## Feedback + +If you encounter issues or have suggestions, please: +- File an issue on [GitHub](https://github.com/microsoft/vscode-java-debug/issues) +- Include the agent's response and your debugging request + +## See Also + +- [Debugger for Java Documentation](https://github.com/microsoft/vscode-java-debug) +- [No-Config Debug](../scripts/noConfigScripts/README.md) +- [Troubleshooting Guide](../../Troubleshooting.md) diff --git a/bundled/agents/debug.agent.md b/bundled/agents/debug.agent.md new file mode 100644 index 00000000..168dd465 --- /dev/null +++ b/bundled/agents/debug.agent.md @@ -0,0 +1,723 @@ +--- +description: An expert Java debugging assistant that uses hypothesis-driven debugging to find root causes systematically +tools: ['execute/getTerminalOutput', 'execute/runInTerminal', 'read/problems', 'read/readFile', 'read/terminalLastCommand', 'search', 'vscjava.vscode-java-debug/debugJavaApplication', 'vscjava.vscode-java-debug/setJavaBreakpoint', 'vscjava.vscode-java-debug/debugStepOperation', 'vscjava.vscode-java-debug/getDebugVariables', 'vscjava.vscode-java-debug/getDebugStackTrace', 'vscjava.vscode-java-debug/evaluateDebugExpression', 'vscjava.vscode-java-debug/getDebugThreads', 'vscjava.vscode-java-debug/removeJavaBreakpoints', 'vscjava.vscode-java-debug/stopDebugSession', 'vscjava.vscode-java-debug/getDebugSessionInfo'] +--- + +# Java Debugging Agent + +You are an expert Java debugging assistant using **hypothesis-driven debugging**. You systematically form hypotheses, set targeted breakpoints, and verify assumptions through runtime inspection. + +## ⚠️ CRITICAL RULES + +1. **NO BREAKPOINT = NO DEBUG** - Only proceed with debug operations AFTER setting at least one breakpoint +2. **HYPOTHESIS FIRST** - Always state your hypothesis BEFORE setting a breakpoint +3. **TARGETED INSPECTION** - Don't dump all variables; only inspect what's relevant to your hypothesis +4. **ONE HYPOTHESIS AT A TIME** - Verify one hypothesis before moving to the next +5. **CLEANUP BASED ON LAUNCH METHOD** - Check `Launch Method` field: if "Can be safely stopped" → cleanup. If "Stopping will disconnect" → do NOT cleanup + +--- + +## The Hypothesis-Driven Debugging Loop + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ HYPOTHESIS-DRIVEN DEBUGGING │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 1: STATIC ANALYSIS ║ │ +│ ║ • Read and understand the code ║ │ +│ ║ • Form specific hypothesis about the bug ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 2: SETUP ║ │ +│ ║ • Set breakpoint at location relevant to hypothesis ║ │ +│ ║ • Check/wait for debug session ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 3: DYNAMIC VERIFICATION ║ │ +│ ║ • Inspect ONLY variables relevant to hypothesis ║ │ +│ ║ • Evaluate specific expressions to test hypothesis ║ │ +│ ║ ║ │ +│ ║ Result A: Hypothesis CONFIRMED → Root cause found! Report & Exit ║ │ +│ ║ Result B: Hypothesis REJECTED → Form new hypothesis, loop back ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 4: CLEANUP (check Launch Method) ║ │ +│ ║ • If "Can be safely stopped": Remove breakpoints, stop session ║ │ +│ ║ • If "Stopping will disconnect": Do NOT cleanup ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Phase 1: Static Analysis (ALWAYS DO THIS FIRST) + +### 1.1 Read and Understand the Code + +``` +search/codebase("method name or error keyword") +readFile("ClassName.java") +``` + +### 1.2 Form a Specific Hypothesis + +**This is the most critical step!** State your hypothesis explicitly: + +```markdown +## My Hypothesis + +Based on code analysis, I believe the bug is: +- **What**: `user` variable is null when `user.getName()` is called +- **Where**: Line 52 in OrderService.java +- **Why**: The `findById()` might return null when ID doesn't exist + +I will verify this by setting a breakpoint at line 52 and checking if `user == null`. +``` + +### 1.3 Hypothesis Types for Common Bugs + +| Bug Type | Hypothesis Template | +|----------|-------------------| +| NullPointerException | "Variable X is null at line Y because Z" | +| Wrong Result | "The calculation at line Y produces wrong value because condition Z is incorrect" | +| Array Index Out of Bounds | "Index X exceeds array length at line Y because loop condition is wrong" | +| Infinite Loop | "Loop at line Y never terminates because condition Z is always true" | +| Concurrency | "Thread A modifies X while Thread B reads it without synchronization" | + +--- + +## Phase 2: Setup (Breakpoint Gates All Debug Actions) + +### 2.1 Set Breakpoint Based on Hypothesis + +``` +vscjava.vscode-java-debug/setJavaBreakpoint(filePath="OrderService.java", lineNumber=52) +``` + +**Remember your breakpoint location** - you'll compare it with the paused location later. + +### 2.2 Check Session State (Call ONCE, Then Act!) + +``` +vscjava.vscode-java-debug/getDebugSessionInfo() +``` + +**⚠️ CRITICAL: Call this tool ONCE, read the response, then take action. DO NOT call it in a loop!** + +The tool will return one of these states: + +**State A: 🔴 PAUSED at breakpoint** +``` +═══════════════════════════════════════════ +🔴 DEBUG SESSION PAUSED +═══════════════════════════════════════════ +🔴 Status: PAUSED (breakpoint) + +📍 Current Location: +• File: /path/to/OrderService.java +• Line: 52 +• Method: OrderService.java:52 in processOrder +• Thread: main (ID: 1) +``` +→ **Action**: Proceed immediately to Phase 3 (Inspect variables) + +**State B: 🟢 RUNNING (Not at breakpoint yet)** +``` +═══════════════════════════════════════════ +🟢 DEBUG SESSION RUNNING +═══════════════════════════════════════════ +🟢 Status: RUNNING + +⏳ WAITING - Session is running, not yet at breakpoint +``` +→ **Action**: PAUSE your tool calls (do NOT end the debugging workflow). Tell user: "Breakpoint set. Program is running but hasn't hit the breakpoint yet. Please trigger the relevant operation. Let me know when done, and I'll continue the analysis." + +**⚠️ IMPORTANT: This is NOT the end of debugging! The workflow is PAUSED, waiting for the breakpoint to be hit.** + +**State C: ❌ NO SESSION** +``` +❌ No active debug session found. +``` +→ **Action**: STOP calling tools. Tell user: "Please start a debug session first, or use vscjava.vscode-java-debug/debugJavaApplication to start one." + +### 2.3 Decision Matrix (STRICT!) + +| Tool Response | Your Action | +|--------------|-------------| +| Shows `🔴 DEBUG SESSION PAUSED` with file/line | ✅ Immediately call `vscjava.vscode-java-debug/evaluateDebugExpression` or `vscjava.vscode-java-debug/getDebugVariables` | +| Shows `🟢 DEBUG SESSION RUNNING` | ⏸️ PAUSE & WAIT! Tell user to trigger the scenario, then **continue** when user confirms | +| Shows `❌ No active debug session` | ⛔ STOP! Tell user to start debug session | + +**🚫 NEVER DO THIS:** +``` +vscjava.vscode-java-debug/getDebugSessionInfo() // Returns RUNNING +vscjava.vscode-java-debug/getDebugSessionInfo() // Still RUNNING +vscjava.vscode-java-debug/getDebugSessionInfo() // Still RUNNING... (LOOP!) +``` + +**✅ CORRECT BEHAVIOR:** +``` +vscjava.vscode-java-debug/getDebugSessionInfo() // Returns RUNNING +// PAUSE HERE! Tell user: "Waiting for breakpoint. Please trigger the scenario and let me know when done." +// WAIT FOR USER RESPONSE - debugging is NOT finished, just waiting for user action +``` + +**When user confirms they triggered the scenario:** +``` +vscjava.vscode-java-debug/getDebugSessionInfo() // Check again - should now be PAUSED +// If PAUSED → Continue to Phase 3 (inspect variables) +// If still RUNNING → Ask user to verify the scenario triggers the breakpoint location +// If NO SESSION → Program may have terminated; you can safely restart debugging +``` + +### 2.4 Automatic Cleanup on Restart + +**Good news:** The `debugJavaApplication` tool automatically cleans up before starting: +- Stops any existing Java debug session (avoids JDWP port conflicts) +- Closes existing "Java Debug" terminals (avoids confusion) + +This means you can safely call `debugJavaApplication` again without manually stopping the previous session. The tool handles cleanup for you. + +### 2.5 Fallback: When debugJavaApplication Fails or Times Out + +When `debugJavaApplication` returns timeout or failure, follow this recovery workflow: + +**Step 1: Check terminal output for errors** +``` +execute/getTerminalOutput(id="Java Debug") +``` + +Look for common errors: +- `ClassNotFoundException` → Wrong class name or classpath +- `NoClassDefFoundError` → Missing dependencies +- `Error: Could not find or load main class` → Compilation issue +- Build errors from Maven/Gradle + +**Step 2: Report findings and ask user to start manually** + +Based on terminal output, tell the user what went wrong and ask them to start the debug session manually: + +```markdown +"Debug session failed to start automatically. + +**Error found**: [describe error from terminal] + +Please start a debug session manually: +1. Fix the error above, OR +2. Use VS Code's 'Run and Debug' (F5) with your own launch configuration, OR +3. Use 'Run > Attach to Java Process' if your application is already running with debug enabled + +Let me know when the debug session is ready, and I'll continue the analysis." +``` + +**Step 3: Wait for user confirmation** + +⛔ **STOP HERE and end your response.** Wait for user to reply (e.g., "ready", "started", "continue"). + +**Step 4: Verify session after user confirms** + +When user says the session is ready: +``` +vscjava.vscode-java-debug/getDebugSessionInfo() +``` + +Then proceed based on session state: +- 🔴 PAUSED → Continue to Phase 3 +- 🟢 RUNNING → Tell user to trigger the scenario +- ❌ NO SESSION → Ask user to try again + +**Complete Fallback Example:** +``` +1. vscjava.vscode-java-debug/setJavaBreakpoint(filePath="App.java", lineNumber=25) + → ✓ Breakpoint set + +2. vscjava.vscode-java-debug/debugJavaApplication(target="App", workspacePath="...") + → ⚠️ Timeout: session not detected within 15 seconds + +3. execute/getTerminalOutput(id="Java Debug") + → "Error: Could not find or load main class App" + +4. Tell user: + "The debug session failed to start. Terminal shows: 'Could not find or load main class App'. + This usually means the class wasn't compiled or the classpath is incorrect. + + Please either: + - Run 'mvn compile' or 'gradle build' first, then try again + - Or start a debug session manually using VS Code's Run and Debug + + Let me know when ready." + +5. [STOP - Wait for user response] + +6. User: "ok, started" + +7. vscjava.vscode-java-debug/getDebugSessionInfo() + → 🔴 PAUSED at App.java:25 + +8. Continue with Phase 3 (hypothesis verification)... +``` + +--- + +## Phase 3: Dynamic Verification (Hypothesis Testing) + +### 3.1 TARGETED Inspection (Don't Dump Everything!) + +❌ **BAD** - Dumping all variables: +``` +vscjava.vscode-java-debug/getDebugVariables(scopeType="all") // Returns 50+ variables, wastes context +``` + +✅ **GOOD** - Targeted inspection based on hypothesis: +``` +// Hypothesis: "user is null" +vscjava.vscode-java-debug/evaluateDebugExpression(expression="user == null") // Returns: true + +// Only if needed, get specific details: +vscjava.vscode-java-debug/evaluateDebugExpression(expression="orderId") // Returns: 456 +vscjava.vscode-java-debug/evaluateDebugExpression(expression="orderRepository.findById(orderId).isPresent()") // Returns: false +``` + +### 3.2 Verify Your Hypothesis + +**If Hypothesis CONFIRMED:** +```markdown +## Hypothesis Verified ✓ + +My hypothesis was correct: +- `user` is indeed null at line 52 +- `orderRepository.findById(456)` returns Optional.empty() +- Root cause: Order ID 456 doesn't exist in database + +**Fix**: Add null check or use `orElseThrow()` with meaningful exception. +``` +→ Proceed to Phase 4 (Cleanup) + +**If Hypothesis REJECTED:** +```markdown +## Hypothesis Rejected ✗ + +My hypothesis was wrong: +- `user` is NOT null (user = User@abc123) +- Need to form new hypothesis... + +**New Hypothesis**: The NPE occurs inside `user.getOrders()` because `orders` list is null. +``` +→ Remove old breakpoint, set new one, loop back to Phase 2 + +### 3.3 Step Strategically (Not Aimlessly!) + +Only step when you have a reason: + +``` +// I need to see what happens AFTER this line executes +vscjava.vscode-java-debug/debugStepOperation(operation="stepOver") + +// I need to see what happens INSIDE this method call +vscjava.vscode-java-debug/debugStepOperation(operation="stepInto") +``` + +**Never step without stating why:** +```markdown +I'm stepping over line 52 to see the result of `processOrder()` call. +After this step, I'll check if `result` is null. +``` + +--- + +## Phase 4: Cleanup (Based on Launch Method) + +After finding root cause OR when giving up, cleanup depends on how the debug session was started. + +Check the `Launch Method` field from `vscjava.vscode-java-debug/getDebugSessionInfo()` output: + +### If Launch Method shows: `✅ Can be safely stopped` + +This includes: +- `debugjava (No-Config)` - Started by the debug_java_application tool +- `VS Code launch` - Started via VS Code's launch configuration + +You can safely cleanup: + +``` +vscjava.vscode-java-debug/removeJavaBreakpoints() +vscjava.vscode-java-debug/stopDebugSession(reason="Analysis complete - root cause identified") +``` + +### If Launch Method shows: `⚠️ Stopping will disconnect from process` + +This means user manually attached to an existing Java process. + +**Do NOT cleanup.** Keep breakpoints and keep the session connected: +- The user attached to a running process they want to keep running +- Stopping the session would disconnect from the process +- Removing breakpoints might interfere with their ongoing debugging + +Simply report your findings and let the user decide what to do next. + +--- + +## Context Management Best Practices + +### Don't Overflow LLM Context + +Java objects can be huge. Use targeted evaluation: + +| Instead of... | Use... | +|--------------|--------| +| `vscjava.vscode-java-debug/getDebugVariables(scopeType="all")` | `vscjava.vscode-java-debug/evaluateDebugExpression("specificVar")` | +| Dumping entire List | `vscjava.vscode-java-debug/evaluateDebugExpression("list.size()")` then `vscjava.vscode-java-debug/evaluateDebugExpression("list.get(0)")` | +| Viewing entire object | `vscjava.vscode-java-debug/evaluateDebugExpression("obj.getClass().getName()")` then specific fields | + +### Evaluate Expressions to Test Hypotheses + +``` +// Test null hypothesis +vscjava.vscode-java-debug/evaluateDebugExpression(expression="user == null") + +// Test collection state +vscjava.vscode-java-debug/evaluateDebugExpression(expression="orders != null && !orders.isEmpty()") + +// Test calculation +vscjava.vscode-java-debug/evaluateDebugExpression(expression="total == price * quantity") + +// Check object type +vscjava.vscode-java-debug/evaluateDebugExpression(expression="obj instanceof ExpectedType") +``` + +--- + +## Multi-Threading Debugging + +### Understanding Thread States + +**Debugger-Level States** (from `getDebugThreads`): + +``` +vscjava.vscode-java-debug/getDebugThreads() +``` + +Returns thread list with debugger states: +``` +═══════════════════════════════════════════ +THREADS (4 total) +═══════════════════════════════════════════ + +Thread #1: main [🔴 SUSPENDED] at App.java:25 +Thread #14: worker-1 [🟢 RUNNING] +Thread #15: worker-2 [🔴 SUSPENDED] at Worker.java:42 +Thread #16: pool-1-thread-1 [🟢 RUNNING] +``` + +⚠️ **Limitation**: Debugger states only show SUSPENDED or RUNNING. Threads showing as 🟢 RUNNING without stack frames might actually be BLOCKED, WAITING, or TIMED_WAITING in Java terms. + +### Getting Detailed JVM Thread States (Using jstack) + +When you need to diagnose deadlocks, lock contention, or blocking issues, use the **jstack** JVM tool via terminal: + +```bash +# Step 1: Find the Java process ID +jps -l + +# Step 2: Get complete thread dump with lock info and deadlock detection +jstack +``` + +**Why jstack instead of a debugger tool?** +- ✅ **Complete stack traces** for ALL threads (including BLOCKED ones) +- ✅ **Automatic deadlock detection** with detailed lock ownership +- ✅ **Works reliably** - no evaluate expression limitations +- ✅ **Shows native frames** and JVM internal threads + +**Example jstack output:** +``` +Found one Java-level deadlock: +============================= +"worker-1": + waiting to lock monitor 0x00007f9b2c003f08 (object 0x00000000d6e30208, a java.lang.Object), + which is held by "worker-2" +"worker-2": + waiting to lock monitor 0x00007f9b2c004018 (object 0x00000000d6e30210, a java.lang.Object), + which is held by "worker-1" + +"worker-1" #14 prio=5 os_prio=0 tid=0x00007f9b28001000 nid=0x5f03 waiting for monitor entry + java.lang.Thread.State: BLOCKED (on object monitor) + at com.example.Service.methodA(Service.java:30) + - waiting to lock <0x00000000d6e30208> (a java.lang.Object) + - locked <0x00000000d6e30210> (a java.lang.Object) + at com.example.Worker.run(Worker.java:25) +``` + +### When to Use Each Tool + +| Scenario | Tool to Use | +|----------|------------| +| List threads and find suspended ones | `getDebugThreads()` | +| Threads show RUNNING but no stack frames | **`jstack `** in terminal | +| Suspect deadlock | **`jstack `** in terminal | +| Inspect specific thread's variables | `getDebugVariables(threadId=X)` | +| Need lock contention details | **`jstack `** in terminal | + +### Key Concepts + +| Thread State | Can Inspect Variables? | Can Evaluate Expressions? | +|--------------|------------------------|---------------------------| +| 🔴 SUSPENDED | ✅ Yes | ✅ Yes | +| 🟢 RUNNING | ❌ No | ❌ No | + +**Only SUSPENDED threads can be inspected!** + +### Inspecting Specific Threads + +``` +// Inspect variables in thread #15 (worker-2) +vscjava.vscode-java-debug/getDebugVariables(threadId=15) + +// Get stack trace of thread #1 (main) +vscjava.vscode-java-debug/getDebugStackTrace(threadId=1) + +// Evaluate expression in thread #15's context +vscjava.vscode-java-debug/evaluateDebugExpression(threadId=15, expression="sharedCounter") +``` + +### Multi-Thread Debugging Workflow + +1. **List all threads and identify suspended ones:** + ``` + vscjava.vscode-java-debug/getDebugThreads() + → Find threads with 🔴 SUSPENDED status + ``` + +2. **Form thread-specific hypothesis:** + ```markdown + ## Hypothesis + Thread "worker-2" (#15) is modifying `sharedCounter` without synchronization + while "main" thread (#1) is reading it. + ``` + +3. **Inspect each suspended thread:** + ``` + // Check main thread's view + vscjava.vscode-java-debug/evaluateDebugExpression(threadId=1, expression="sharedCounter") + → Result: 42 + + // Check worker-2's view + vscjava.vscode-java-debug/evaluateDebugExpression(threadId=15, expression="sharedCounter") + → Result: 43 // Different value! Race condition confirmed! + ``` + +4. **Step specific thread:** + ``` + vscjava.vscode-java-debug/debugStepOperation(operation="stepOver", threadId=15) + ``` + +### Common Multi-Threading Bugs + +| Bug Type | What to Look For | Diagnostic Tool | +|----------|------------------|-----------------| +| Race Condition | Same variable has different values in different threads | `getDebugVariables` on each thread | +| Deadlock | Multiple threads stuck, program hangs | **`jstack `** in terminal | +| Thread Starvation | One thread always RUNNING, others stuck | **`jstack `** in terminal | +| Lock Contention | Threads waiting for same lock | **`jstack `** in terminal | +| Memory Visibility | Thread sees stale value (check `volatile` keyword) | `evaluateDebugExpression` | + +### Deadlock Diagnosis Workflow + +**Use jstack for reliable deadlock detection:** + +``` +=== STEP 1: Detect the hang === +User: "Program seems frozen/stuck" + +=== STEP 2: Find the Java process === +Run in terminal: +$ jps -l +12345 com.example.MainApp ← This is the target PID + +=== STEP 3: Get thread dump === +Run in terminal: +$ jstack 12345 + +=== STEP 4: jstack automatically detects deadlock === +Found one Java-level deadlock: +============================= +"worker-1": + waiting to lock monitor 0x00007f9b2c003f08 (a java.lang.Object), + which is held by "worker-2" +"worker-2": + waiting to lock monitor 0x00007f9b2c004018 (a java.lang.Object), + which is held by "worker-1" + +Java stack information for the threads listed above: +=================================================== +"worker-1": + at com.example.Service.methodA(Service.java:30) + - waiting to lock <0x00000000d6e30208> (a java.lang.Object) + - locked <0x00000000d6e30210> (a java.lang.Object) + +"worker-2": + at com.example.Service.methodB(Service.java:50) + - waiting to lock <0x00000000d6e30210> (a java.lang.Object) + - locked <0x00000000d6e30208> (a java.lang.Object) + +=== STEP 5: Analyze the deadlock === +Diagnosis: Classic deadlock! +- worker-1 holds lock @210, wants lock @208 +- worker-2 holds lock @208, wants lock @210 +- Circular wait = DEADLOCK + +=== STEP 6: Report fix === +Fix: Ensure consistent lock ordering - always acquire locks in same order +``` + +### Alternative Thread Dump Methods + +If jstack is not available, use these alternatives: + +**Option 1: JConsole/VisualVM** +```bash +# Launch JConsole +jconsole +# Connect to the Java process → Go to "Threads" tab → "Detect Deadlock" +``` + +**Option 2: Add diagnostic code** +```java +// Add before suspected deadlock area +Thread.dumpStack(); +// Or for full dump: +ManagementFactory.getThreadMXBean().dumpAllThreads(true, true); +``` + +### Key Thread States in jstack Output + +| State | Meaning | +|-------|---------| +| `BLOCKED (on object monitor)` | Thread waiting for a monitor lock - **potential deadlock** | +| `WAITING (on object monitor)` | Thread waiting for notification (wait()) | +| `TIMED_WAITING (sleeping/parking)` | Thread waiting with timeout | +| `RUNNABLE` | Thread running or ready to run | + +--- + +## Example: Complete Hypothesis-Driven Debug Session + +``` +User: "Getting NPE when calling OrderService.processOrder()" + +=== PHASE 1: STATIC ANALYSIS === + +1. Read code: + search/codebase("OrderService processOrder") + readFile("OrderService.java") + +2. Form hypothesis: + "Looking at line 52: `order.getItems().forEach(...)` - I hypothesize that + either `order` is null OR `order.getItems()` returns null. + + I'll verify by checking both conditions at line 52." + +=== PHASE 2: SETUP === + +3. Set breakpoint: + vscjava.vscode-java-debug/setJavaBreakpoint(filePath="OrderService.java", lineNumber=52) + +4. Check session: + vscjava.vscode-java-debug/getDebugSessionInfo() + → ❌ No session + + "Breakpoint set. Please trigger the failing scenario." + +[User triggers scenario, breakpoint hits] + +5. Verify location: + vscjava.vscode-java-debug/getDebugSessionInfo() + → 🔴 PAUSED at OrderService.java:52 ✓ + +=== PHASE 3: DYNAMIC VERIFICATION === + +6. Test hypothesis with TARGETED evaluation: + vscjava.vscode-java-debug/evaluateDebugExpression(expression="order == null") + → false (order is NOT null) + + vscjava.vscode-java-debug/evaluateDebugExpression(expression="order.getItems() == null") + → true ✓ FOUND IT! + +7. Gather supporting evidence: + vscjava.vscode-java-debug/evaluateDebugExpression(expression="order.getId()") + → 456 + + vscjava.vscode-java-debug/evaluateDebugExpression(expression="order.getStatus()") + → "PENDING" + +8. Report: + "## Root Cause Found + + **Hypothesis CONFIRMED**: `order.getItems()` returns null for order 456. + + The order exists but its `items` field was never initialized. + This happens for orders with status='PENDING' before items are added. + + **Fix**: Initialize items as empty list in Order constructor, or add null check." + +=== PHASE 4: CLEANUP (for launch sessions only) === + +9. Check session type and cleanup if needed: + vscjava.vscode-java-debug/getDebugSessionInfo() // Check Launch Method field + + // If Launch Method shows "✅ Can be safely stopped": + vscjava.vscode-java-debug/removeJavaBreakpoints() + vscjava.vscode-java-debug/stopDebugSession(reason="Root cause identified - items field is null") + + // If Launch Method shows "⚠️ Stopping will disconnect": + // Do NOT cleanup - just report findings +``` + +--- + +## What NOT To Do + +❌ **Don't debug without a hypothesis:** +``` +// BAD - aimless debugging +vscjava.vscode-java-debug/setJavaBreakpoint(filePath="...", lineNumber=1) // Why line 1? +vscjava.vscode-java-debug/getDebugVariables(scopeType="all") // Looking for what? +``` + +❌ **Don't dump all variables:** +``` +// BAD - context overflow +vscjava.vscode-java-debug/getDebugVariables(scopeType="all") // 100+ variables +``` + +❌ **Don't step aimlessly:** +``` +// BAD - stepping without purpose +vscjava.vscode-java-debug/debugStepOperation(operation="stepOver") +vscjava.vscode-java-debug/debugStepOperation(operation="stepOver") +vscjava.vscode-java-debug/debugStepOperation(operation="stepOver") // Where are we going? +``` + +✅ **DO: Hypothesis-driven, targeted debugging:** +``` +// GOOD +"Hypothesis: user is null at line 52" +vscjava.vscode-java-debug/setJavaBreakpoint(filePath="Service.java", lineNumber=52) +vscjava.vscode-java-debug/evaluateDebugExpression(expression="user == null") // Verify hypothesis +``` + +--- + +## Remember + +1. **Hypothesis FIRST** - Always state what you're looking for before setting breakpoints +2. **Targeted inspection** - Only check variables relevant to your hypothesis +3. **Verify or reject** - Each inspection should confirm or reject your hypothesis +4. **Iterate** - If hypothesis rejected, form a new one based on what you learned +5. **Cleanup based on Launch Method** - Check `Launch Method` in session info: if "Can be safely stopped" → remove breakpoints and stop session. If "Stopping will disconnect" → do NOT cleanup (keep breakpoints, keep session connected) diff --git a/bundled/agents/images/agent-working.png b/bundled/agents/images/agent-working.png new file mode 100644 index 00000000..affe97bd Binary files /dev/null and b/bundled/agents/images/agent-working.png differ diff --git a/bundled/agents/images/invoke-agent.png b/bundled/agents/images/invoke-agent.png new file mode 100644 index 00000000..e9c46cce Binary files /dev/null and b/bundled/agents/images/invoke-agent.png differ diff --git a/bundled/agents/images/javadebug.png b/bundled/agents/images/javadebug.png new file mode 100644 index 00000000..60f631f3 Binary files /dev/null and b/bundled/agents/images/javadebug.png differ diff --git a/bundled/scripts/noConfigScripts/README.md b/bundled/scripts/noConfigScripts/README.md new file mode 100644 index 00000000..021f0553 --- /dev/null +++ b/bundled/scripts/noConfigScripts/README.md @@ -0,0 +1,102 @@ +# Java No-Config Debug + +This feature enables configuration-less debugging for Java applications, similar to the JavaScript Debug Terminal in VS Code. + +## How It Works + +When you open a terminal in VS Code with this extension installed, the following environment variables are automatically set: + +- `VSCODE_JDWP_ADAPTER_ENDPOINTS`: Path to a communication file for port exchange +- `PATH`: Includes the `debugjava` command wrapper + +Note: `JAVA_TOOL_OPTIONS` is NOT set globally to avoid affecting other Java tools (javac, maven, gradle). Instead, it's set only when you run the `debugjava` command. + +## Usage + +### Basic Usage + +Instead of running: +```bash +java -cp . com.example.Main +``` + +Simply run: +```bash +debugjava -cp . com.example.Main +``` + +The debugger will automatically attach, and breakpoints will work without any launch.json configuration! + +### Maven Projects + +```bash +debugjava -jar target/myapp.jar +``` + +### Gradle Projects + +```bash +debugjava -jar build/libs/myapp.jar +``` + +### With Arguments + +```bash +debugjava -cp . com.example.Main arg1 arg2 --flag=value +``` + +### Spring Boot + +```bash +debugjava -jar myapp.jar --spring.profiles.active=dev +``` + +## Advantages + +1. **No Configuration Required**: No need to create or maintain launch.json +2. **Rapid Prototyping**: Perfect for quick debugging sessions +3. **Script Debugging**: Debug applications launched by complex shell scripts +4. **Environment Consistency**: Inherits all terminal environment variables +5. **Parameter Flexibility**: Easy to change arguments using terminal history (↑ key) + +## How It Works Internally + +1. When you run `debugjava`, the wrapper script temporarily sets `JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0` +2. The wrapper determines which Java executable to use (priority order): + - First: `JAVA_HOME/bin/java` if JAVA_HOME environment variable is set (user's explicit choice) + - Second: `VSCODE_JAVA_EXEC` environment variable (Java path from VS Code's Java Language Server) + - Third: `java` command from system PATH +3. The wrapper launches the Java process with JDWP enabled +4. JVM starts and outputs: "Listening for transport dt_socket at address: 12345" +5. The wrapper captures the JDWP port from this output +6. The port is written to a communication file +7. VS Code's file watcher detects the file and automatically starts an attach debug session + +## Troubleshooting + +### Port Already in Use + +If you see "Address already in use", another Java debug session is running. Terminate it first. + +### No Breakpoints Hit + +1. Ensure you're running with `debugjava` command (not plain `java`) +2. Check that the `debugjava` command is available: `which debugjava` (Unix) or `Get-Command debugjava` (PowerShell) +3. Verify the terminal was opened AFTER the extension activated +4. Check the Debug Console for error messages + +### Node.js Not Found + +The wrapper script requires Node.js to be installed and available in PATH. + +## Limitations + +- Requires Node.js to be installed and available in PATH +- Only works in terminals opened within VS Code +- Requires using the `debugjava` command instead of `java` +- The Java process will suspend (hang) until the debugger attaches + +## See Also + +- [Debugger for Java Documentation](https://github.com/microsoft/vscode-java-debug) +- [JDWP Documentation](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) diff --git a/bundled/scripts/noConfigScripts/debugjava b/bundled/scripts/noConfigScripts/debugjava new file mode 100644 index 00000000..881a9211 --- /dev/null +++ b/bundled/scripts/noConfigScripts/debugjava @@ -0,0 +1,12 @@ +#!/bin/bash +# Java No-Config Debug Wrapper Script for Unix/Linux/macOS +# This script intercepts java commands and automatically enables JDWP debugging + +# Get the directory of this script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables only for the node process, not the current shell +# This ensures JAVA_TOOL_OPTIONS doesn't affect subsequent commands in the terminal +JDWP_ADAPTER_ENDPOINTS=$VSCODE_JDWP_ADAPTER_ENDPOINTS \ +JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0" \ +exec node "$SCRIPT_DIR/jdwp-wrapper.js" "$@" diff --git a/bundled/scripts/noConfigScripts/debugjava.bat b/bundled/scripts/noConfigScripts/debugjava.bat new file mode 100644 index 00000000..3606188c --- /dev/null +++ b/bundled/scripts/noConfigScripts/debugjava.bat @@ -0,0 +1,19 @@ +@echo off +REM Java No-Config Debug Wrapper Script for Windows +REM This script intercepts java commands and automatically enables JDWP debugging + +REM Use setlocal to ensure environment variables don't persist after this script exits +setlocal + +REM Export the endpoint file path for JDWP port communication +set JDWP_ADAPTER_ENDPOINTS=%VSCODE_JDWP_ADAPTER_ENDPOINTS% + +REM Set JDWP options only for this debugjava invocation +REM This overrides the global JAVA_TOOL_OPTIONS to avoid affecting other Java processes +set JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0 + +REM Use Node.js wrapper to capture JDWP port +node "%~dp0jdwp-wrapper.js" %* + +REM endlocal is implicit at script exit, but we can call it explicitly for clarity +endlocal diff --git a/bundled/scripts/noConfigScripts/debugjava.fish b/bundled/scripts/noConfigScripts/debugjava.fish new file mode 100644 index 00000000..47d7cf75 --- /dev/null +++ b/bundled/scripts/noConfigScripts/debugjava.fish @@ -0,0 +1,12 @@ +#!/usr/bin/env fish +# Java No-Config Debug Wrapper Script for Fish Shell +# This script intercepts java commands and automatically enables JDWP debugging + +# Get the directory of this script +set script_dir (dirname (status -f)) + +# Set environment variables only for the node process, not the current shell +# This ensures JAVA_TOOL_OPTIONS doesn't affect subsequent commands in the terminal +env JDWP_ADAPTER_ENDPOINTS=$VSCODE_JDWP_ADAPTER_ENDPOINTS \ + JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0" \ + node "$script_dir/jdwp-wrapper.js" $argv diff --git a/bundled/scripts/noConfigScripts/debugjava.ps1 b/bundled/scripts/noConfigScripts/debugjava.ps1 new file mode 100644 index 00000000..0404a860 --- /dev/null +++ b/bundled/scripts/noConfigScripts/debugjava.ps1 @@ -0,0 +1,32 @@ +# Java No-Config Debug Wrapper Script for PowerShell +# This script intercepts java commands and automatically enables JDWP debugging + +# Get the directory of this script +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +# Save current environment variables to restore later +$oldJavaToolOptions = $env:JAVA_TOOL_OPTIONS +$oldJdwpAdapterEndpoints = $env:JDWP_ADAPTER_ENDPOINTS + +try { + # Set environment variables only for this debugjava invocation + $env:JDWP_ADAPTER_ENDPOINTS = $env:VSCODE_JDWP_ADAPTER_ENDPOINTS + $env:JAVA_TOOL_OPTIONS = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0" + + # Use Node.js wrapper to capture JDWP port + & node (Join-Path $scriptDir "jdwp-wrapper.js") $args +} +finally { + # Restore original environment variables to avoid affecting subsequent commands + if ($null -eq $oldJavaToolOptions) { + Remove-Item Env:\JAVA_TOOL_OPTIONS -ErrorAction SilentlyContinue + } else { + $env:JAVA_TOOL_OPTIONS = $oldJavaToolOptions + } + + if ($null -eq $oldJdwpAdapterEndpoints) { + Remove-Item Env:\JDWP_ADAPTER_ENDPOINTS -ErrorAction SilentlyContinue + } else { + $env:JDWP_ADAPTER_ENDPOINTS = $oldJdwpAdapterEndpoints + } +} diff --git a/bundled/scripts/noConfigScripts/jdwp-wrapper.js b/bundled/scripts/noConfigScripts/jdwp-wrapper.js new file mode 100644 index 00000000..cae86170 --- /dev/null +++ b/bundled/scripts/noConfigScripts/jdwp-wrapper.js @@ -0,0 +1,144 @@ +#!/usr/bin/env node +/** + * JDWP Port Listener and Communication Wrapper + * + * This script wraps Java process execution and captures the JDWP port + * from the JVM output, then writes it to the endpoint file for VS Code + * to pick up and attach the debugger. + * + * JDWP Output Format: + * "Listening for transport dt_socket at address: 12345" + */ + +const { spawn } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +// Get environment variables +const endpointFile = process.env.JDWP_ADAPTER_ENDPOINTS || process.env.VSCODE_JDWP_ADAPTER_ENDPOINTS; +const javaToolOptions = process.env.JAVA_TOOL_OPTIONS || ''; + +// Check if debugging is enabled +const isDebugEnabled = javaToolOptions.includes('jdwp') && endpointFile; + +// Helper function to find java command +function getJavaCommand() { + // Priority 1: Try JAVA_HOME environment variable first (user's explicit choice) + const javaHome = process.env.JAVA_HOME; + if (javaHome) { + const javaPath = path.join(javaHome, 'bin', 'java'); + const javaPathExe = process.platform === 'win32' ? `${javaPath}.exe` : javaPath; + + // Check if the file exists + if (fs.existsSync(javaPathExe)) { + return javaPath; + } + if (fs.existsSync(javaPath)) { + return javaPath; + } + + console.warn(`[Java Debug] JAVA_HOME is set to '${javaHome}', but java command not found there. Falling back to VS Code's Java.`); + } + + // Priority 2: Use VSCODE_JAVA_EXEC if provided by VS Code (from Java Language Server) + const vscodeJavaExec = process.env.VSCODE_JAVA_EXEC; + if (vscodeJavaExec && fs.existsSync(vscodeJavaExec)) { + return vscodeJavaExec; + } + + // Priority 3: Fall back to 'java' in PATH + return 'java'; +} + +const javaCmd = getJavaCommand(); + +// Helper function to setup signal handlers for graceful termination +function setupSignalHandlers(child) { + const signals = ['SIGINT', 'SIGTERM']; + signals.forEach(signal => { + process.on(signal, () => { + child.kill(signal); + }); + }); +} + +if (!isDebugEnabled) { + // No debugging, just run java normally + const child = spawn(javaCmd, process.argv.slice(2), { + stdio: 'inherit', + shell: false + }); + setupSignalHandlers(child); + // Use 'close' event to ensure stdio streams are closed before exiting + child.on('close', (code) => process.exit(code || 0)); + child.on('error', (err) => { + console.error(`[Java Debug] Failed to start java: ${err.message}`); + console.error(`[Java Debug] Make sure Java is installed and either JAVA_HOME is set correctly or 'java' is in your PATH.`); + process.exit(1); + }); +} else { + // Debugging enabled, capture JDWP port + const child = spawn(javaCmd, process.argv.slice(2), { + stdio: ['inherit', 'pipe', 'pipe'], + shell: false + }); + setupSignalHandlers(child); + + let portCaptured = false; + const jdwpPortRegex = /Listening for transport dt_socket at address:\s*(\d+)/; + + // Shared function to capture JDWP port from output + const capturePort = (output) => { + if (portCaptured) return; + + const match = output.match(jdwpPortRegex); + if (match && match[1]) { + const port = parseInt(match[1], 10); + + // Validate port range + if (port < 1 || port > 65535) { + console.error(`[Java Debug] Invalid port number: ${port}`); + return; + } + + console.log(`[Java Debug] Captured JDWP port: ${port}`); + + // Write port to endpoint file + const endpointData = JSON.stringify({ + client: { + host: 'localhost', + port: port + } + }); + + try { + fs.writeFileSync(endpointFile, endpointData, 'utf8'); + console.log(`[Java Debug] Wrote endpoint file: ${endpointFile}`); + portCaptured = true; + } catch (err) { + console.error(`[Java Debug] Failed to write endpoint file: ${err}`); + } + } + }; + + // Monitor stdout for JDWP port + child.stdout.on('data', (data) => { + const output = data.toString(); + process.stdout.write(data); + capturePort(output); + }); + + // Monitor stderr for JDWP port (it might appear on stderr) + child.stderr.on('data', (data) => { + const output = data.toString(); + process.stderr.write(data); + capturePort(output); + }); + + // Use 'close' event to ensure stdio streams are closed before exiting + child.on('close', (code) => process.exit(code || 0)); + child.on('error', (err) => { + console.error(`[Java Debug] Failed to start java: ${err}`); + process.exit(1); + }); +} diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 763bb7ae..00000000 --- a/gulpfile.js +++ /dev/null @@ -1,40 +0,0 @@ -const gulp = require("gulp"); -const cp = require('child_process'); -const tslint = require("gulp-tslint"); -const copy = require("gulp-copy"); - -const server_dir = '../java-debug'; - -gulp.task("tslint", () => { - return gulp.src(["**/*.ts", "!**/*.d.ts", "!node_modules/**", "!./src/views/node_modules/**"]) - .pipe(tslint()) - .pipe(tslint.report()); -}); - -gulp.task('build_server', () => { - cp.execSync(mvnw() + ' clean package', { - cwd: server_dir, - stdio: [0, 1, 2] - }); - gulp.src(server_dir + '/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.*.jar') - .pipe(copy('./server', { - prefix: 4 - })) - .pipe(gulp.dest('.')); -}); - -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/images/commands/hot_code_replace.svg b/images/commands/hot_code_replace.svg new file mode 100644 index 00000000..3e070476 --- /dev/null +++ b/images/commands/hot_code_replace.svg @@ -0,0 +1,13 @@ + + + + +lightning +Created with Sketch. + + + + diff --git a/images/docs/33868694-673f14b0-df3f-11e7-9983-b3cff5842020.gif b/images/docs/33868694-673f14b0-df3f-11e7-9983-b3cff5842020.gif new file mode 100644 index 00000000..61c95281 Binary files /dev/null and b/images/docs/33868694-673f14b0-df3f-11e7-9983-b3cff5842020.gif differ diff --git a/images/docs/34507770-69597114-f074-11e7-8f32-027ad1d7a4fd.gif b/images/docs/34507770-69597114-f074-11e7-8f32-027ad1d7a4fd.gif new file mode 100644 index 00000000..489cb817 Binary files /dev/null and b/images/docs/34507770-69597114-f074-11e7-8f32-027ad1d7a4fd.gif differ diff --git a/images/docs/37269785-0ffef8e6-2607-11e8-955f-93548ad5a0ad.gif b/images/docs/37269785-0ffef8e6-2607-11e8-955f-93548ad5a0ad.gif new file mode 100644 index 00000000..3ce29cba Binary files /dev/null and b/images/docs/37269785-0ffef8e6-2607-11e8-955f-93548ad5a0ad.gif differ diff --git a/images/docs/41949312-77627a40-79f3-11e8-9fd2-def4fa06e28d.gif b/images/docs/41949312-77627a40-79f3-11e8-9fd2-def4fa06e28d.gif new file mode 100644 index 00000000..0645eace Binary files /dev/null and b/images/docs/41949312-77627a40-79f3-11e8-9fd2-def4fa06e28d.gif differ diff --git a/images/docs/args.PNG b/images/docs/args.PNG new file mode 100644 index 00000000..fd2d6160 Binary files /dev/null and b/images/docs/args.PNG differ diff --git a/logo.png b/logo.png index a6135492..4e40f9ee 100644 Binary files a/logo.png and b/logo.png differ diff --git a/package-lock.json b/package-lock.json index da916238..46fe9962 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3572 +1,5707 @@ { - "name": "vscode-java-debug", - "version": "0.1.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/mocha": { - "version": "2.2.41", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.41.tgz", - "integrity": "sha1-4nzwgXFT658nE7LT9saPHhw8pgg=", - "dev": true - }, - "@types/node": { - "version": "6.0.85", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.85.tgz", - "integrity": "sha512-6qLZpfQFO/g5Ns2e7RsW6brk0Q6Xzwiw7kVVU/XiQNOiJXSojhX76GP457PBYIsNMH2WfcGgcnZB4awFDHrwpA==", - "dev": true - }, + "name": "vscode-java-debug", + "version": "0.58.5", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "vscode-java-debug", + "version": "0.58.5", + "license": "SEE LICENSE IN LICENSE.txt", + "dependencies": { + "compare-versions": "^4.1.4", + "dotenv": "^16.4.5", + "lodash": "^4.17.23", + "uuid": "^8.3.2", + "vscode-extension-telemetry-wrapper": "^0.14.0", + "vscode-languageclient": "6.0.0-next.9", + "vscode-languageserver-types": "3.16.0", + "vscode-tas-client": "^0.1.84" + }, + "devDependencies": { + "@types/glob": "^7.2.0", + "@types/lodash": "^4.17.13", + "@types/mocha": "^10.0.9", + "@types/node": "^14.18.63", + "@types/uuid": "^8.3.4", + "@types/vscode": "1.95.0", + "@vscode/test-electron": "^2.4.1", + "mocha": "^10.8.2", + "ts-loader": "^9.5.1", + "tslint": "^6.1.3", + "typescript": "^4.9.5", + "webpack": "^5.105.0", + "webpack-cli": "^4.10.0" + }, + "engines": { + "vscode": "^1.95.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "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, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "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, + "engines": { + "node": ">=6.0.0" + } + }, + "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, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "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 + }, + "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, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@microsoft/1ds-core-js": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.3.4.tgz", + "integrity": "sha512-3gbDUQgAO8EoyQTNcAEkxpuPnioC0May13P1l1l0NKZ128L9Ts/sj8QsfwCRTjHz0HThlA+4FptcAJXNYUy3rg==", + "dependencies": { + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "node_modules/@microsoft/1ds-post-js": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.3.4.tgz", + "integrity": "sha512-nlKjWricDj0Tn68Dt0P8lX9a+X7LYrqJ6/iSfQwMfDhRIGLqW+wxx8gxS+iGWC/oc8zMQAeiZaemUpCwQcwpRQ==", + "dependencies": { + "@microsoft/1ds-core-js": "4.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "node_modules/@microsoft/applicationinsights-channel-js": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.3.4.tgz", + "integrity": "sha512-Z4nrxYwGKP9iyrYtm7iPQXVOFy4FsEsX0nDKkAi96Qpgw+vEh6NH4ORxMMuES0EollBQ3faJyvYCwckuCVIj0g==", + "dependencies": { + "@microsoft/applicationinsights-common": "3.3.4", + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-common": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.3.4.tgz", + "integrity": "sha512-4ms16MlIvcP4WiUPqopifNxcWCcrXQJ2ADAK/75uok2mNQe6ZNRsqb/P+pvhUxc8A5HRlvoXPP1ptDSN5Girgw==", + "dependencies": { + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-core-js": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.4.tgz", + "integrity": "sha512-MummANF0mgKIkdvVvfmHQTBliK114IZLRhTL0X0Ep+zjDwWMHqYZgew0nlFKAl6ggu42abPZFK5afpE7qjtYJA==", + "dependencies": { + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-shims": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", + "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", + "dependencies": { + "@nevware21/ts-utils": ">= 0.9.4 < 2.x" + } + }, + "node_modules/@microsoft/applicationinsights-web-basic": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.3.4.tgz", + "integrity": "sha512-OpEPXr8vU/t/M8T9jvWJzJx/pCyygIiR1nGM/2PTde0wn7anl71Gxl5fWol7K/WwFEORNjkL3CEyWOyDc+28AA==", + "dependencies": { + "@microsoft/applicationinsights-channel-js": "3.3.4", + "@microsoft/applicationinsights-common": "3.3.4", + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/dynamicproto-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", + "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", + "dependencies": { + "@nevware21/ts-utils": ">= 0.10.4 < 2.x" + } + }, + "node_modules/@nevware21/ts-async": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.3.tgz", + "integrity": "sha512-UsF7eerLsVfid7iV1oXF80qXBwHNBeqSqfh/nPZgirRU1MACmSsj83EZKS2ViFHVfSGG6WIuXMGBP6KciXfYhA==", + "dependencies": { + "@nevware21/ts-utils": ">= 0.11.5 < 2.x" + } + }, + "node_modules/@nevware21/ts-utils": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.5.tgz", + "integrity": "sha512-7nIzWKR50mf3htOg53kwPLqD5iJaRfVyBvb1NJhlIncyP1WzK8vAQbU9rqIsRtv7td1CnqspdP6IWNEjOjaeug==" + }, + "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, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "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, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "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 + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "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 + }, + "node_modules/@types/lodash": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.95.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.95.0.tgz", + "integrity": "sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vscode/extension-telemetry": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.7.tgz", + "integrity": "sha512-2GQbcfDUTg0QC1v0HefkHNwYrE5LYKzS3Zb0+uA6Qn1MBDzgiSh23ddOZF/JRqhqBFOG0mE70XslKSGQ5v9KwQ==", + "dependencies": { + "@microsoft/1ds-core-js": "^4.3.0", + "@microsoft/1ds-post-js": "^4.3.0", + "@microsoft/applicationinsights-web-basic": "^3.3.0" + }, + "engines": { + "vscode": "^1.75.0" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "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, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "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 + }, + "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 + }, + "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 + }, + "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, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "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 + }, + "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, + "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" + } + }, + "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, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "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, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "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 + }, + "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, + "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" + } + }, + "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, + "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" + } + }, + "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, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "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, + "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" + } + }, + "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, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": 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 + }, + "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 + }, + "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, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "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, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "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, + "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" + } + }, + "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, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, + "optional": true + } + } + }, + "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, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "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, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/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==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "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 + }, + "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, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "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" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "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 + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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, + "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" + } + ] + }, + "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/chalk/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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/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/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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/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, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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/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/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "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 + }, + "node_modules/compare-versions": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.4.tgz", + "integrity": "sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "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 + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "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, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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 + }, + "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, + "engines": { + "node": ">=6" + } + }, + "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-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/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/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.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==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.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" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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 + }, + "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==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/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, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "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, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/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" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-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, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "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==", + "dev": true + }, + "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, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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 + }, + "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 + }, + "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, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "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, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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==", + "dev": true + }, + "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, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "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": "^8.1.0", + "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": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/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_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 + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", + "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.3.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "string-width": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "1.3.0", + "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, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "dev": true, + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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 + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-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 + }, + "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 + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/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, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "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" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/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, + "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" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/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, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "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, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^10.2.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tas-client": { + "version": "0.2.33", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", + "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==" + }, + "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, + "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" + } + }, + "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, + "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 + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/tslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/tslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/tslint/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslint/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/tslint/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, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tslint/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/tslint/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/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" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vscode-extension-telemetry-wrapper": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry-wrapper/-/vscode-extension-telemetry-wrapper-0.14.0.tgz", + "integrity": "sha512-EYr1hqiYVSGfupchDN405zSwuvA8V3tJ62KcLIRDr/4ongOc2AvSZ0BlRq8a0w950tadsMlXTKEheB97fZBttg==", + "dependencies": { + "@vscode/extension-telemetry": "^0.9.6", + "uuid": "^8.3.2" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "6.0.0-next.9", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.9.tgz", + "integrity": "sha512-NEpeeFM9FKrrRqlBHXGfwpkhtnjruDz3zfFBP+Cymr10qigAEtE/JsODJsIG/ErGqjh3/JXxu8SUOVTGu5oK+w==", + "dependencies": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "^3.15.0-next.14" + }, + "engines": { + "vscode": "^1.40.0" + } + }, + "node_modules/vscode-languageclient/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-protocol/node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "node_modules/vscode-tas-client": { + "version": "0.1.84", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", + "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", + "dependencies": { + "tas-client": "0.2.33" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "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, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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, + "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 + } + } + }, + "node_modules/webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "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, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "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, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "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 + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-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/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/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/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@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": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@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 + }, + "@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": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "@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 + }, + "@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": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@microsoft/1ds-core-js": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.3.4.tgz", + "integrity": "sha512-3gbDUQgAO8EoyQTNcAEkxpuPnioC0May13P1l1l0NKZ128L9Ts/sj8QsfwCRTjHz0HThlA+4FptcAJXNYUy3rg==", + "requires": { + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/1ds-post-js": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.3.4.tgz", + "integrity": "sha512-nlKjWricDj0Tn68Dt0P8lX9a+X7LYrqJ6/iSfQwMfDhRIGLqW+wxx8gxS+iGWC/oc8zMQAeiZaemUpCwQcwpRQ==", + "requires": { + "@microsoft/1ds-core-js": "4.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/applicationinsights-channel-js": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.3.4.tgz", + "integrity": "sha512-Z4nrxYwGKP9iyrYtm7iPQXVOFy4FsEsX0nDKkAi96Qpgw+vEh6NH4ORxMMuES0EollBQ3faJyvYCwckuCVIj0g==", + "requires": { + "@microsoft/applicationinsights-common": "3.3.4", + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/applicationinsights-common": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.3.4.tgz", + "integrity": "sha512-4ms16MlIvcP4WiUPqopifNxcWCcrXQJ2ADAK/75uok2mNQe6ZNRsqb/P+pvhUxc8A5HRlvoXPP1ptDSN5Girgw==", + "requires": { + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/applicationinsights-core-js": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.4.tgz", + "integrity": "sha512-MummANF0mgKIkdvVvfmHQTBliK114IZLRhTL0X0Ep+zjDwWMHqYZgew0nlFKAl6ggu42abPZFK5afpE7qjtYJA==", + "requires": { + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/applicationinsights-shims": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", + "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", + "requires": { + "@nevware21/ts-utils": ">= 0.9.4 < 2.x" + } + }, + "@microsoft/applicationinsights-web-basic": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.3.4.tgz", + "integrity": "sha512-OpEPXr8vU/t/M8T9jvWJzJx/pCyygIiR1nGM/2PTde0wn7anl71Gxl5fWol7K/WwFEORNjkL3CEyWOyDc+28AA==", + "requires": { + "@microsoft/applicationinsights-channel-js": "3.3.4", + "@microsoft/applicationinsights-common": "3.3.4", + "@microsoft/applicationinsights-core-js": "3.3.4", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.2 < 2.x", + "@nevware21/ts-utils": ">= 0.11.3 < 2.x" + } + }, + "@microsoft/dynamicproto-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", + "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", + "requires": { + "@nevware21/ts-utils": ">= 0.10.4 < 2.x" + } + }, + "@nevware21/ts-async": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.3.tgz", + "integrity": "sha512-UsF7eerLsVfid7iV1oXF80qXBwHNBeqSqfh/nPZgirRU1MACmSsj83EZKS2ViFHVfSGG6WIuXMGBP6KciXfYhA==", + "requires": { + "@nevware21/ts-utils": ">= 0.11.5 < 2.x" + } + }, + "@nevware21/ts-utils": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.5.tgz", + "integrity": "sha512-7nIzWKR50mf3htOg53kwPLqD5iJaRfVyBvb1NJhlIncyP1WzK8vAQbU9rqIsRtv7td1CnqspdP6IWNEjOjaeug==" + }, + "@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, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@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": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@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 + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@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 + }, + "@types/lodash": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", + "dev": true + }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "@types/mocha": { + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", + "dev": true + }, + "@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "dev": true + }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "@types/vscode": { + "version": "1.95.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.95.0.tgz", + "integrity": "sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==", + "dev": true + }, + "@vscode/extension-telemetry": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.7.tgz", + "integrity": "sha512-2GQbcfDUTg0QC1v0HefkHNwYrE5LYKzS3Zb0+uA6Qn1MBDzgiSh23ddOZF/JRqhqBFOG0mE70XslKSGQ5v9KwQ==", + "requires": { + "@microsoft/1ds-core-js": "^4.3.0", + "@microsoft/1ds-post-js": "^4.3.0", + "@microsoft/applicationinsights-web-basic": "^3.3.0" + } + }, + "@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "dev": true, + "requires": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" + } + }, + "@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": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "@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 + }, + "@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 + }, + "@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 + }, + "@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": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "@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 + }, + "@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": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "@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": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@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": { + "@xtuc/long": "4.2.2" + } + }, + "@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 + }, + "@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": { + "@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" + } + }, + "@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": { + "@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" + } + }, + "@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": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "@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": { + "@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" + } + }, + "@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": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true, + "requires": {} + }, + "@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.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true + }, + "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": {} + }, + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "requires": { + "debug": "^4.3.4" + } + }, + "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": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "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": { + "ajv": "^8.0.0" + } + }, + "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": { + "fast-deep-equal": "^3.1.3" + } + }, + "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 + }, + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true + }, + "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": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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 + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "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 + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true + }, + "bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "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 + }, + "browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "requires": { + "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" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "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 + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "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 + }, + "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": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "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": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.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" + } + }, + "chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "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 + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } }, + "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": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "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": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "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": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "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 + }, + "compare-versions": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.4.tgz", + "integrity": "sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "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 + }, + "diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true + }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "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 + }, + "emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "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": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + } + }, + "envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true + }, + "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 + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "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 + }, + "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": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "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 + }, + "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, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "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 + }, + "fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "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 + }, + "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 + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "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": { + "is-glob": "^4.0.1" + } + }, + "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 + }, + "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==", + "dev": true + }, + "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 + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "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 + }, + "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": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "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 + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "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": { + "hasown": "^2.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "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 + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "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 + }, + "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==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "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 + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "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": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "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, + "requires": { + "argparse": "^2.0.1" + } + }, + "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": { + "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 + }, + "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": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "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 + }, + "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": { + "immediate": "~3.0.5" + } + }, + "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 + }, + "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": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + }, + "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": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "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==", + "dev": true + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "requires": { + "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": "^8.1.0", + "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": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "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-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 + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", + "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", + "dev": true, + "requires": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.3.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "string-width": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "dependencies": { + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true + }, + "is-unicode-supported": { + "version": "1.3.0", + "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 + }, + "log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "dev": true, + "requires": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + } + } + } + }, + "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": { + "yocto-queue": "^0.1.0" + } + }, + "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": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "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 + }, + "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 + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "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 + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "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": { + "find-up": "^4.0.0" + }, + "dependencies": { + "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": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "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": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "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": { + "p-limit": "^2.2.0" + } + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": 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" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "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 + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "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 + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "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 + }, + "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": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "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, + "requires": { + "randombytes": "^2.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "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": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "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": { + "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 + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "requires": { + "bl": "^5.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^10.2.1", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "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 + }, + "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": { + "has-flag": "^4.0.0" + } + }, + "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 + }, + "tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true + }, + "tas-client": { + "version": "0.2.33", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", + "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==" + }, + "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": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "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, + "requires": { + "@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" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "dependencies": { "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "applicationinsights": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz", - "integrity": "sha1-Fi67SKODQIvE3kTbMrQXMH9Fu8E=" - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "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 - }, - "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 - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "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 - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "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=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } + "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" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "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 - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.2", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - }, - "dependencies": { - "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 - } - } - }, - "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "dev": true - }, - "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 - }, - "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 - }, - "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true - }, - "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=", - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "dateformat": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "deep-assign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", - "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", - "dev": true, - "requires": { - "is-obj": "1.0.1" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.2" - } - }, - "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 - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true, - "requires": { - "fs-exists-sync": "0.1.0" - } + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", - "dev": true, - "requires": { - "end-of-stream": "1.4.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true, - "requires": { - "once": "1.4.0" - } + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "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.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "1.2.0" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true, - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", - "dev": true - }, - "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": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "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.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true }, "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "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.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true, - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "0.2.0", - "which": "1.3.0" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "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 - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.3", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - } - } - } - }, - "gulp-chmod": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", - "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", - "dev": true, - "requires": { - "deep-assign": "1.0.0", - "stat-mode": "0.2.2", - "through2": "2.0.3" - } - }, - "gulp-copy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-copy/-/gulp-copy-1.0.1.tgz", - "integrity": "sha512-uhIdHo9SoWkf+pjfjETOMD/6ez10ZItO5/L1bFRfVGH+7lq9zE3TSjkh3WVPuTS9ttPRHA7yW4g1QRE1hPwUOA==", - "dev": true, - "requires": { - "gulp": "3.9.1", - "gulp-util": "3.0.8", - "through2": "2.0.3" - } - }, - "gulp-filter": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A==", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "multimatch": "2.1.0", - "streamfilter": "1.0.5" - } - }, - "gulp-gunzip": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz", - "integrity": "sha1-e24HsPWP09QlFcSOrVpj3wVy9i8=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "gulp-remote-src": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", - "integrity": "sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "node.extend": "1.1.6", - "request": "2.79.0", - "through2": "2.0.3", - "vinyl": "2.0.2" - }, - "dependencies": { - "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 - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.4.3", - "uuid": "3.1.0" - } - }, - "vinyl": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", - "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", - "dev": true, - "requires": { - "clone": "1.0.2", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "is-stream": "1.1.0", - "remove-trailing-separator": "1.0.2", - "replace-ext": "1.0.0" - } - } - } - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-symdest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", - "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "mkdirp": "0.5.1", - "queue": "3.1.0", - "vinyl-fs": "2.4.4" - } - }, - "gulp-tslint": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.2.tgz", - "integrity": "sha512-0RNGqbp2TKPdbG+sWU3mNMXEMuF/noY1KS4+jd5lOStkvuFINkFL29dHX3IT1u+vVFD4Glwf+lkcdR2QMVNMzA==", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "map-stream": "0.0.7", - "through": "2.3.8" - }, - "dependencies": { - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - } - } - }, - "gulp-untar": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.6.tgz", - "integrity": "sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "streamifier": "0.1.1", - "tar": "2.2.1", - "through2": "2.0.3" - } - }, - "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.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.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.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "gulp-vinyl-zip": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz", - "integrity": "sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "queue": "3.1.0", - "through2": "0.6.5", - "vinyl": "0.4.6", - "vinyl-fs": "2.4.4", - "yauzl": "2.8.0", - "yazl": "2.4.2" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "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" - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.1", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - } - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, - "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true, - "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" - } - }, - "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "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": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "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.1" - } - }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true, - "requires": { - "is-unc-path": "0.1.2" - } - }, - "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 - }, - "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "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": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "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" - } - }, - "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 - }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, - "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 - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-stable-stringify": { - "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 - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "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" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, - "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "0.4.3", - "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "1.4.0" - } - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "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._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "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 - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "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.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "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.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", - "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", - "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", - "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", - "dev": true - }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "3.2.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.0.2" - } - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "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 - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" - }, - "dependencies": { - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true, - "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "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 - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "2.3.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": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "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=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "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 - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", - "dev": true - }, - "queue": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", - "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.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" - } - } - } - }, - "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" - } - } - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.4.0" - } - }, - "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" - } - }, - "remove-trailing-separator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", - "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "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": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" - }, - "dependencies": { - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "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.1.1" - } - } - } - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true, - "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true, - "requires": { - "glob": "7.1.2" - }, - "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.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-support": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.17.tgz", - "integrity": "sha512-30c1Ch8FSjV0FwC253iftbbj0dU/OXoSg1LAEGZJUlGgjTNj6cu+DVqJWWIZJY5RXLWV4eFtR+4ouo0VIOYOTg==", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "0.1.1" - } - }, - "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "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 - }, - "streamfilter": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.5.tgz", - "integrity": "sha1-h1BxEb644phFFxe1Ec/tjwAqv1M=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, - "streamifier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", - "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", - "dev": true - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - } + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true }, "supports-color": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "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.3", - "xtend": "4.0.1" - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, - "to-iso-string": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", - "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", - "dev": true - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tslib": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz", - "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw=", - "dev": true - }, - "tslint": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.7.0.tgz", - "integrity": "sha1-wl4NDJL6EgHCvDDoROCOaCtPNVI=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "colors": "1.1.2", - "commander": "2.11.0", - "diff": "3.3.1", - "glob": "7.1.2", - "minimatch": "3.0.4", - "resolve": "1.4.0", - "semver": "5.4.1", - "tslib": "1.7.1", - "tsutils": "2.8.2" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "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.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "tsutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.8.2.tgz", - "integrity": "sha1-LBSGukMSYIRbCsb5Aq/Z1wio6mo=", - "dev": true, - "requires": { - "tslib": "1.7.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "typescript": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz", - "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=", - "dev": true - }, - "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 - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "url-parse": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", - "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", - "dev": true, - "requires": { - "querystringify": "1.0.0", - "requires-port": "1.0.0" - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "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.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "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.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "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 - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vscode": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.5.tgz", - "integrity": "sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ=", - "dev": true, - "requires": { - "glob": "7.1.2", - "gulp-chmod": "2.0.0", - "gulp-filter": "5.0.1", - "gulp-gunzip": "0.0.3", - "gulp-remote-src": "0.4.3", - "gulp-symdest": "1.1.0", - "gulp-untar": "0.0.6", - "gulp-vinyl-zip": "1.4.0", - "mocha": "3.5.0", - "request": "2.81.0", - "semver": "5.4.1", - "source-map-support": "0.4.17", - "url-parse": "1.1.9", - "vinyl-source-stream": "1.1.0" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "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=", - "dev": true - }, - "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.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "mocha": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz", - "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "vscode-extension-telemetry": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz", - "integrity": "sha1-ImG/+Ya2aQpvH3RqRaxb0fhdKeA=", - "requires": { - "applicationinsights": "0.18.0", - "winreg": "1.2.3" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "winreg": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz", - "integrity": "sha1-k60RayaW2ofVj3JlqPzqUlSpZdU=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "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" + } + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + }, + "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, + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "vscode-extension-telemetry-wrapper": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry-wrapper/-/vscode-extension-telemetry-wrapper-0.14.0.tgz", + "integrity": "sha512-EYr1hqiYVSGfupchDN405zSwuvA8V3tJ62KcLIRDr/4ongOc2AvSZ0BlRq8a0w950tadsMlXTKEheB97fZBttg==", + "requires": { + "@vscode/extension-telemetry": "^0.9.6", + "uuid": "^8.3.2" + } + }, + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==" + }, + "vscode-languageclient": { + "version": "6.0.0-next.9", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.9.tgz", + "integrity": "sha512-NEpeeFM9FKrrRqlBHXGfwpkhtnjruDz3zfFBP+Cymr10qigAEtE/JsODJsIG/ErGqjh3/JXxu8SUOVTGu5oK+w==", + "requires": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "^3.15.0-next.14" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + }, + "dependencies": { + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + } + } + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "vscode-tas-client": { + "version": "0.1.84", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", + "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", + "requires": { + "tas-client": "0.2.33" + } + }, + "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": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", + "dev": true, + "requires": { + "@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" + } + }, + "webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "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 + } + } + }, + "webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + } + }, + "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 + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true + }, + "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": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "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 + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } }, - "yauzl": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", - "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } + "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": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "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 + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } }, - "yazl": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.2.tgz", - "integrity": "sha1-FMsZCD4eJacAksFYiqvg9OTdTYg=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13" - } + "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": { + "ansi-regex": "^5.0.1" + } } + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "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, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "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 } + } } diff --git a/package.json b/package.json index 57ea78e5..38de66c8 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,19 @@ { "name": "vscode-java-debug", - "displayName": "Java Debug Extension for Visual Studio Code", + "displayName": "Debugger for Java", "description": "A lightweight Java debugger for Visual Studio Code", - "version": "0.1.0", + "version": "0.58.5", "publisher": "vscjava", - "preview": true, + "preview": false, "aiKey": "67d4461e-ccba-418e-8082-1bd0acfe8516", "icon": "logo.png", + "workspaceTrust": { + "request": "onDemand", + "description": "Extension may require your trust on workspace for code execution." + }, + "capabilities": { + "virtualWorkspaces": false + }, "keywords": [ "java", "debug", @@ -14,7 +21,7 @@ "debugger" ], "engines": { - "vscode": "^1.17.0" + "vscode": "^1.95.0" }, "license": "SEE LICENSE IN LICENSE.txt", "repository": { @@ -26,27 +33,354 @@ }, "homepage": "https://github.com/Microsoft/vscode-java-debug/blob/master/README.md", "categories": [ - "Debuggers" + "Debuggers", + "Programming Languages", + "Other" ], "activationEvents": [ "onLanguage:java", - "onCommand:vscode.java.startDebugSession" + "onDebugInitialConfigurations", + "onDebugResolve:java", + "onCommand:JavaDebug.SpecifyProgramArgs", + "onCommand:JavaDebug.PickJavaProcess", + "onLanguageModelTool:debug_java_application" ], - "main": "./out/src/extension", + "main": "./dist/extension", "contributes": { + "breakpoints": [ + { + "language": "java" + } + ], "javaExtensions": [ - "./server/com.microsoft.java.debug.plugin-0.1.0.jar" + "./server/com.microsoft.java.debug.plugin-0.53.2.jar" + ], + "commands": [ + { + "command": "java.debug.hotCodeReplace", + "title": "Hot Code Replace", + "icon": { + "dark": "images/commands/hot_code_replace.svg", + "light": "images/commands/hot_code_replace.svg" + } + }, + { + "command": "java.debug.runJavaFile", + "title": "Run Java", + "icon": "$(play)" + }, + { + "command": "java.debug.debugJavaFile", + "title": "Debug Java", + "icon": "$(debug-alt-small)" + }, + { + "command": "java.debug.runFromProjectView", + "title": "Run", + "icon": "$(play)" + }, + { + "command": "java.debug.debugFromProjectView", + "title": "Debug", + "icon": "$(debug-alt-small)" + }, + { + "command": "java.debug.continueAll", + "title": "Continue All" + }, + { + "command": "java.debug.continueOthers", + "title": "Continue Others" + }, + { + "command": "java.debug.pauseAll", + "title": "Pause All" + }, + { + "command": "java.debug.pauseOthers", + "title": "Pause Others" + }, + { + "command": "java.debug.breakpoints.exceptionTypes", + "title": "Manage Java Breakpoint Exception Types" + }, + { + "command": "java.debug.variables.showHex", + "title": "Show as Hex" + }, + { + "command": "java.debug.variables.notShowHex", + "title": "Show as Dec" + }, + { + "command": "java.debug.variables.showQualifiedNames", + "title": "Show Qualified Names" + }, + { + "command": "java.debug.variables.notShowQualifiedNames", + "title": "Show Simple Names" + }, + { + "command": "java.debug.variables.showStaticVariables", + "title": "Show Static Variables" + }, + { + "command": "java.debug.variables.notShowStaticVariables", + "title": "Hide Static Variables" + }, + { + "command": "java.debug.variables.showLogicalStructure", + "title": "Enable Logical Structure View" + }, + { + "command": "java.debug.variables.notShowLogicalStructure", + "title": "Disable Logical Structure View" + }, + { + "command": "java.debug.variables.showToString", + "title": "Enable 'toString()' Object View" + }, + { + "command": "java.debug.variables.notShowToString", + "title": "Disable 'toString()' Object View" + }, + { + "command": "java.debug.variables.autoExpandLazyVariables", + "title": "Auto Expand Lazy Variables" + }, + { + "command": "java.debug.variables.manualExpandLazyVariables", + "title": "Manual Expand Lazy Variables" + } ], - "commands": [], + "menus": { + "view/item/context": [ + { + "command": "java.debug.debugFromProjectView", + "when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/", + "group": "inline@100" + }, + { + "command": "java.debug.runFromProjectView", + "when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/", + "group": "8_execution@10" + }, + { + "command": "java.debug.debugFromProjectView", + "when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/", + "group": "8_execution@20" + } + ], + "explorer/context": [ + { + "command": "java.debug.runJavaFile", + "when": "resourceExtname == .java", + "group": "1_javaactions@90" + }, + { + "command": "java.debug.debugJavaFile", + "when": "resourceExtname == .java", + "group": "1_javaactions@91" + } + ], + "editor/context": [ + { + "command": "java.debug.runJavaFile", + "when": "editorLangId == java && resourceExtname == .java", + "group": "javadebug@1" + }, + { + "command": "java.debug.debugJavaFile", + "when": "editorLangId == java && resourceExtname == .java", + "group": "javadebug@2" + } + ], + "editor/title/run": [ + { + "command": "java.debug.runJavaFile", + "when": "resourceExtname == .java", + "group": "1_javadebug@10" + }, + { + "command": "java.debug.debugJavaFile", + "when": "resourceExtname == .java", + "group": "1_javadebug@20" + } + ], + "debug/toolBar": [ + { + "command": "java.debug.hotCodeReplace", + "group": "navigation@100", + "when": "inDebugMode && debugType == java && javaHotReload == 'manual' && javaHotReloadOn" + } + ], + "debug/callstack/context": [ + { + "command": "java.debug.continueAll", + "when": "inDebugMode && debugType == java && callStackItemType == 'thread'" + }, + { + "command": "java.debug.continueOthers", + "when": "inDebugMode && debugType == java && callStackItemType == 'thread'" + }, + { + "command": "java.debug.pauseAll", + "when": "inDebugMode && debugType == java && callStackItemType == 'thread'" + }, + { + "command": "java.debug.pauseOthers", + "when": "inDebugMode && debugType == java && callStackItemType == 'thread'" + } + ], + "commandPalette": [ + { + "command": "java.debug.hotCodeReplace", + "when": "false" + }, + { + "command": "java.debug.runJavaFile", + "when": "false" + }, + { + "command": "java.debug.debugJavaFile", + "when": "false" + }, + { + "command": "java.debug.continueAll", + "when": "false" + }, + { + "command": "java.debug.continueOthers", + "when": "false" + }, + { + "command": "java.debug.pauseAll", + "when": "false" + }, + { + "command": "java.debug.pauseOthers", + "when": "false" + }, + { + "command": "java.debug.runFromProjectView", + "when": "false" + }, + { + "command": "java.debug.debugFromProjectView", + "when": "false" + }, + { + "command": "java.debug.variables.showHex", + "when": "false" + }, + { + "command": "java.debug.variables.notShowHex", + "when": "false" + }, + { + "command": "java.debug.variables.showQualifiedNames", + "when": "false" + }, + { + "command": "java.debug.variables.notShowQualifiedNames", + "when": "false" + }, + { + "command": "java.debug.variables.showStaticVariables", + "when": "false" + }, + { + "command": "java.debug.variables.notShowStaticVariables", + "when": "false" + }, + { + "command": "java.debug.variables.showLogicalStructure", + "when": "false" + }, + { + "command": "java.debug.variables.notShowLogicalStructure", + "when": "false" + }, + { + "command": "java.debug.variables.showToString", + "when": "false" + }, + { + "command": "java.debug.variables.notShowToString", + "when": "false" + }, + { + "command": "java.debug.variables.autoExpandLazyVariables", + "when": "false" + }, + { + "command": "java.debug.variables.manualExpandLazyVariables", + "when": "false" + } + ], + "debug/variables/context": [ + { + "command": "java.debug.variables.showHex", + "when": "debugType == 'java' && javadebug:showHex == 'off'", + "group": "1_view@1" + }, + { + "command": "java.debug.variables.notShowHex", + "when": "debugType == 'java' && javadebug:showHex == 'on'", + "group": "1_view@1" + }, + { + "command": "java.debug.variables.showQualifiedNames", + "when": "debugType == 'java' && javadebug:showQualifiedNames == 'off'", + "group": "1_view@2" + }, + { + "command": "java.debug.variables.notShowQualifiedNames", + "when": "debugType == 'java' && javadebug:showQualifiedNames == 'on'", + "group": "1_view@2" + }, + { + "command": "java.debug.variables.showStaticVariables", + "when": "debugType == 'java' && javadebug:showStaticVariables == 'off'", + "group": "1_view@3" + }, + { + "command": "java.debug.variables.notShowStaticVariables", + "when": "debugType == 'java' && javadebug:showStaticVariables == 'on'", + "group": "1_view@3" + }, + { + "command": "java.debug.variables.showLogicalStructure", + "when": "debugType == 'java' && javadebug:showLogicalStructure == 'off'", + "group": "1_view@4" + }, + { + "command": "java.debug.variables.notShowLogicalStructure", + "when": "debugType == 'java' && javadebug:showLogicalStructure == 'on'", + "group": "1_view@4" + }, + { + "command": "java.debug.variables.autoExpandLazyVariables", + "when": "debugType == 'java' && javadebug:expandLazyVariable == 'off'", + "group": "1_view@6" + }, + { + "command": "java.debug.variables.manualExpandLazyVariables", + "when": "debugType == 'java' && javadebug:expandLazyVariable == 'on'", + "group": "1_view@6" + } + ] + }, "debuggers": [ { "type": "java", "label": "Java", - "startSessionCommand": "vscode.java.startDebugSession", - "enableBreakpointsFor": { - "languageIds": [ - "java" - ] + "languages": [ + "java" + ], + "variables": { + "SpecifyProgramArgs": "JavaDebug.SpecifyProgramArgs", + "PickJavaProcess": "JavaDebug.PickJavaProcess" }, "configurationAttributes": { "launch": { @@ -56,30 +390,81 @@ "properties": { "projectName": { "type": "string", - "description": "The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program.", + "description": "%java.debugger.launch.projectName.description%", "default": "" }, "mainClass": { "type": "string", - "description": "The main class of the program (fully qualified name, e.g. com.xyz.MainClass).", + "description": "%java.debugger.launch.mainClass.description%", "default": "" }, - "args": { + "javaExec": { "type": "string", - "description": "The command line arguments passed to the program.", + "description": "%java.debugger.launch.javaExec.description%", + "default": "" + }, + "args": { + "type": [ + "array", + "string" + ], + "description": "%java.debugger.launch.args.description%", "default": "" }, "vmArgs": { - "type": "string", - "description": "The extra options and system properties for the JVM (e.g. -Xms -Xmx -D=).", + "type": [ + "array", + "string" + ], + "description": "%java.debugger.launch.vmArgs.description%", "default": "" }, + "modulePaths": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": [ + "$Auto", + "$Runtime", + "$Test", + "!" + ], + "enumDescriptions": [ + "%java.debugger.launch.modulePaths.auto%", + "%java.debugger.launch.modulePaths.runtime%", + "%java.debugger.launch.modulePaths.test%", + "%java.debugger.launch.modulePaths.exclude%" + ] + }, + "string" + ] + }, + "description": "%java.debugger.launch.modulePaths.description%", + "default": [] + }, "classPaths": { "type": "array", "items": { - "type": "string" + "anyOf": [ + { + "enum": [ + "$Auto", + "$Runtime", + "$Test", + "!" + ], + "enumDescriptions": [ + "%java.debugger.launch.classPaths.auto%", + "%java.debugger.launch.classPaths.runtime%", + "%java.debugger.launch.classPaths.test%", + "%java.debugger.launch.classPaths.exclude%" + ] + }, + "string" + ] }, - "description": "The classpaths for launching the JVM. If not specified, the debugger will automatically resolve from current project.", + "description": "%java.debugger.launch.classPaths.description%", "default": [] }, "sourcePaths": { @@ -87,35 +472,161 @@ "items": { "type": "string" }, - "description": "The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories.", + "description": "%java.debugger.launch.sourcePaths.description%", "default": [] }, "encoding": { "type": "string", - "description": "The file.encoding setting for the JVM. If not specified, 'UTF-8' will be used. Possible values can be found in http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html.", + "description": "%java.debugger.launch.encoding.description%", "default": "UTF-8" + }, + "cwd": { + "type": "string", + "description": "%java.debugger.launch.cwd.description%", + "default": "${workspaceFolder}" + }, + "env": { + "type": "object", + "description": "%java.debugger.launch.env.description%", + "default": {} + }, + "envFile": { + "type": [ + "array", + "string" + ], + "description": "%java.debugger.launch.envFile.description%", + "default": "${workspaceFolder}/.env" + }, + "stopOnEntry": { + "type": "boolean", + "description": "%java.debugger.launch.stopOnEntry.description%", + "default": true + }, + "console": { + "type": "string", + "enum": [ + "internalConsole", + "integratedTerminal", + "externalTerminal" + ], + "enumDescriptions": [ + "%java.debugger.launch.internalConsole.description%", + "%java.debugger.launch.integratedTerminal.description%", + "%java.debugger.launch.externalTerminal.description%" + ], + "description": "%java.debugger.launch.console.description%", + "default": "integratedTerminal" + }, + "shortenCommandLine": { + "type": "string", + "enum": [ + "none", + "jarmanifest", + "argfile", + "auto" + ], + "enumDescriptions": [ + "%java.debugger.launch.shortenCommandLine.none%", + "%java.debugger.launch.shortenCommandLine.jarmanifest%", + "%java.debugger.launch.shortenCommandLine.argfile%", + "%java.debugger.launch.shortenCommandLine.auto%" + ], + "description": "%java.debugger.launch.shortenCommandLine.description%", + "default": "auto" + }, + "stepFilters": { + "type": "object", + "description": "%java.debugger.launch.stepFilters.description%", + "default": { + "skipClasses": [ + "$JDK", + "junit.*" + ], + "skipSynthetics": false, + "skipStaticInitializers": false, + "skipConstructors": false + }, + "properties": { + "skipClasses": { + "type": "array", + "description": "%java.debugger.launch.skipClasses.description%", + "items": { + "anyOf": [ + { + "enum": [ + "$JDK", + "$Libraries", + "java.lang.ClassLoader", + "" + ], + "enumDescriptions": [ + "%java.debugger.launch.skipClasses.skipJDK%", + "%java.debugger.launch.skipClasses.skipLibraries%", + "%java.debugger.launch.skipClasses.skipClassLoader%", + "%java.debugger.launch.skipClasses.skipClassPattern%" + ] + }, + "string" + ] + }, + "default": [ + "$JDK", + "junit.*" + ] + }, + "skipSynthetics": { + "type": "boolean", + "description": "%java.debugger.launch.skipSynthetics.description%", + "default": true + }, + "skipStaticInitializers": { + "type": "boolean", + "description": "%java.debugger.launch.skipStaticInitializers.description%", + "default": true + }, + "skipConstructors": { + "type": "boolean", + "description": "%java.debugger.launch.skipConstructors.description%", + "default": true + } + } } } }, "attach": { - "required": [ - "hostName", - "port" - ], "properties": { "hostName": { "type": "string", "default": "localhost", - "description": "The host name or ip address of remote debuggee." + "description": "%java.debugger.attach.hostName.description%" }, "port": { - "type": "number", - "description": "The debug port of remote debuggee." + "type": [ + "number", + "string" + ], + "description": "%java.debugger.attach.port.description%" + }, + "processId": { + "anyOf": [ + { + "enum": [ + "${command:PickJavaProcess}" + ], + "description": "%java.debugger.attach.processPicker.description%", + "default": "${command:PickJavaProcess}" + }, + { + "type": "integer", + "description": "%java.debugger.attach.processId.description%" + } + ] }, "timeout": { "type": "number", "default": 30000, - "description": "Timeout value before reconnecting, in milliseconds (default to 30000ms)." + "description": "%java.debugger.attach.timeout.description%" }, "sourcePaths": { "type": "array", @@ -123,53 +634,146 @@ "type": "string" }, "default": [], - "description": "The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories." + "description": "%java.debugger.launch.sourcePaths.description%" }, "projectName": { "type": "string", - "description": "The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects.", + "description": "%java.debugger.attach.projectName.description%", "default": "" + }, + "stepFilters": { + "type": "object", + "description": "%java.debugger.launch.stepFilters.description%", + "default": { + "skipClasses": [ + "$JDK", + "junit.*" + ], + "skipSynthetics": false, + "skipStaticInitializers": false, + "skipConstructors": false + }, + "properties": { + "skipClasses": { + "type": "array", + "description": "%java.debugger.launch.skipClasses.description%", + "items": { + "anyOf": [ + { + "enum": [ + "$JDK", + "$Libraries", + "java.lang.ClassLoader", + "" + ], + "enumDescriptions": [ + "%java.debugger.launch.skipClasses.skipJDK%", + "%java.debugger.launch.skipClasses.skipLibraries%", + "%java.debugger.launch.skipClasses.skipClassLoader%", + "%java.debugger.launch.skipClasses.skipClassPattern%" + ] + }, + "string" + ] + }, + "default": [ + "$JDK", + "junit.*" + ] + }, + "skipSynthetics": { + "type": "boolean", + "description": "%java.debugger.launch.skipSynthetics.description%", + "default": false + }, + "skipStaticInitializers": { + "type": "boolean", + "description": "%java.debugger.launch.skipStaticInitializers.description%", + "default": false + }, + "skipConstructors": { + "type": "boolean", + "description": "%java.debugger.launch.skipConstructors.description%", + "default": false + } + } } } } }, - "initialConfigurations": [ + "configurationSnippets": [ { - "type": "java", - "name": "Debug (Launch)", - "request": "launch", - "mainClass": "", - "args": "" + "label": "Java: Launch Program", + "description": "%java.debugger.snippet.launch.description%", + "body": { + "type": "java", + "name": "Launch Java Program", + "request": "launch", + "mainClass": "" + } }, { - "type": "java", - "name": "Debug (Attach)", - "request": "attach", - "hostName": "localhost", - "port": 0 - } - ], - "configurationSnippets": [ + "label": "Java: Launch Program in External Terminal", + "description": "%java.debugger.snippet.launchInExternalTerminal.description%", + "body": { + "type": "java", + "name": "Launch External Terminal", + "request": "launch", + "console": "externalTerminal", + "mainClass": "" + } + }, { - "label": "Java: Launch Program", - "description": "Add a new configuration for launching a java program.", + "label": "Java: Launch Program in Current File", + "description": "%java.debugger.snippet.launchCurrentFile.description%", + "body": { + "type": "java", + "name": "Launch Current File", + "request": "launch", + "mainClass": "^\"\\${file}\"" + } + }, + { + "label": "Java: Launch Program with Arguments Prompt", + "description": "%java.debugger.snippet.launchWithArgumentsPrompt.description%", "body": { "type": "java", - "name": "Debug (Launch)", + "name": "Launch with Arguments Prompt", "request": "launch", "mainClass": "", - "args": "" + "args": "^\"\\${command:SpecifyProgramArgs}\"" } }, { - "label": "Java: Attach to Remote Program", - "description": "Add a new configuration for attaching to a running java program.", + "label": "Java: Attach", + "description": "%java.debugger.snippet.attach.description%", "body": { "type": "java", - "name": "Debug (Attach)", + "name": "Attach", "request": "attach", "hostName": "localhost", - "port": 0 + "port": "" + } + }, + { + "label": "Java: Attach to Process", + "description": "%java.debugger.snippet.attachProcess.description%", + "body": { + "type": "java", + "request": "attach", + "name": "Attach by Process ID", + "processId": "^\"\\${command:PickJavaProcess}\"" + } + }, + { + "label": "Java: Attach to Remote Program", + "description": "%java.debugger.snippet.attachRemote.description%", + "body": { + "type": "java", + "name": "Attach to Remote Program", + "request": "attach", + "hostName": "", + "port": "" } } ] @@ -177,42 +781,595 @@ ], "configuration": { "type": "object", - "title": "Java Debugger Configuration", + "title": "%java.debugger.configuration.title%", "properties": { "java.debug.logLevel": { "type": "string", "default": "warn", + "description": "%java.debugger.configuration.logLevel.description%", "enum": [ "error", "warn", "info", "verbose" ] + }, + "java.debug.settings.showHex": { + "type": "boolean", + "description": "%java.debugger.configuration.showHex.description%", + "default": false + }, + "java.debug.settings.showStaticVariables": { + "type": "boolean", + "description": "%java.debugger.configuration.showStaticVariables.description%", + "default": false + }, + "java.debug.settings.showQualifiedNames": { + "type": "boolean", + "description": "%java.debugger.configuration.showQualifiedNames.description%", + "default": false + }, + "java.debug.settings.showLogicalStructure": { + "type": "boolean", + "description": "%java.debugger.configuration.showLogicalStructure.description%", + "default": true + }, + "java.debug.settings.showToString": { + "type": "boolean", + "description": "%java.debugger.configuration.showToString.description%", + "default": true + }, + "java.debug.settings.maxStringLength": { + "type": "number", + "description": "%java.debugger.configuration.maxStringLength.description%", + "default": 0 + }, + "java.debug.settings.numericPrecision": { + "type": "number", + "description": "%java.debugger.configuration.numericPrecision.description%", + "default": 0 + }, + "java.debug.settings.hotCodeReplace": { + "type": "string", + "default": "manual", + "description": "%java.debugger.configuration.hotCodeReplace.description%", + "enum": [ + "auto", + "manual", + "never" + ] + }, + "java.debug.settings.enableRunDebugCodeLens": { + "type": "boolean", + "description": "%java.debugger.configuration.enableRunDebugCodeLens.description%", + "default": true + }, + "java.debug.settings.forceBuildBeforeLaunch": { + "type": "boolean", + "description": "%java.debugger.configuration.forceBuildBeforeLaunch%", + "default": true + }, + "java.debug.settings.onBuildFailureProceed": { + "type": "boolean", + "description": "%java.debugger.configuration.onBuildFailureProceed%", + "default": false + }, + "java.debug.settings.console": { + "type": "string", + "enum": [ + "internalConsole", + "integratedTerminal", + "externalTerminal" + ], + "enumDescriptions": [ + "%java.debugger.launch.internalConsole.description%", + "%java.debugger.launch.integratedTerminal.description%", + "%java.debugger.launch.externalTerminal.description%" + ], + "description": "%java.debugger.configuration.console%", + "default": "integratedTerminal" + }, + "java.debug.settings.exceptionBreakpoint.exceptionTypes": { + "type": "array", + "description": "%java.debugger.configuration.exceptionBreakpoint.exceptionTypes%", + "items": { + "type": "string" + }, + "default": [] + }, + "java.debug.settings.exceptionBreakpoint.allowClasses": { + "type": "array", + "description": "%java.debugger.configuration.exceptionBreakpoint.allowClasses%", + "items": { + "type": "string" + }, + "default": [] + }, + "java.debug.settings.exceptionBreakpoint.skipClasses": { + "type": "array", + "description": "%java.debugger.configuration.exceptionBreakpoint.skipClasses%", + "items": { + "anyOf": [ + { + "enum": [ + "$JDK", + "$Libraries", + "java.lang.ClassLoader", + "" + ], + "enumDescriptions": [ + "%java.debugger.launch.skipClasses.skipJDK%", + "%java.debugger.launch.skipClasses.skipLibraries%", + "%java.debugger.launch.skipClasses.skipClassLoader%", + "%java.debugger.launch.skipClasses.skipClassPattern%" + ] + }, + "string" + ] + }, + "default": [] + }, + "java.debug.settings.stepping.skipClasses": { + "type": "array", + "description": "%java.debugger.launch.skipClasses.description%", + "items": { + "anyOf": [ + { + "enum": [ + "$JDK", + "$Libraries", + "java.lang.ClassLoader", + "" + ], + "enumDescriptions": [ + "%java.debugger.launch.skipClasses.skipJDK%", + "%java.debugger.launch.skipClasses.skipLibraries%", + "%java.debugger.launch.skipClasses.skipClassLoader%", + "%java.debugger.launch.skipClasses.skipClassPattern%" + ] + }, + "string" + ] + }, + "default": [] + }, + "java.debug.settings.stepping.skipSynthetics": { + "type": "boolean", + "description": "%java.debugger.launch.skipSynthetics.description%", + "default": false + }, + "java.debug.settings.stepping.skipStaticInitializers": { + "type": "boolean", + "description": "%java.debugger.launch.skipStaticInitializers.description%", + "default": false + }, + "java.debug.settings.stepping.skipConstructors": { + "type": "boolean", + "description": "%java.debugger.launch.skipConstructors.description%", + "default": false + }, + "java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest": { + "type": "number", + "description": "%java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description%", + "default": 100, + "minimum": 1 + }, + "java.debug.settings.jdwp.requestTimeout": { + "type": "number", + "description": "%java.debugger.configuration.jdwp.requestTimeout.description%", + "default": 3000, + "minimum": 100 + }, + "java.debug.settings.jdwp.async": { + "type": "string", + "enum": [ + "auto", + "on", + "off" + ], + "description": "%java.debugger.configuration.jdwp.async.description%", + "default": "auto" + }, + "java.debug.settings.vmArgs": { + "type": "string", + "description": "%java.debugger.configuration.vmArgs.description%", + "default": "" + }, + "java.debug.settings.debugSupportOnDecompiledSource": { + "type": "string", + "enum": [ + "on", + "off" + ], + "description": "%java.debugger.configuration.debugSupportOnDecompiledSource.description%", + "default": "on" + }, + "java.debug.settings.suspendAllThreads": { + "type": "boolean", + "description": "%java.debugger.configuration.suspendAllThreads.description%", + "default": false + }, + "java.silentNotification": { + "type": "boolean", + "description": "%java.debugger.configuration.silentNotification%", + "default": false + } + } + }, + "languageModelTools": [ + { + "name": "debug_java_application", + "displayName": "Debug Java Application", + "modelDescription": "Launch or attach to a Java application in debug mode with automatic compilation and classpath resolution. The tool handles building the project, resolving dependencies, starting the JVM with JDWP enabled, and auto-attaching the VS Code debugger. Use this as the first step to establish a debug session. The debug process runs in the background until stopped. Example usage: Debug a main class ('com.example.Main'), a JAR file ('target/app.jar'), or with program arguments (['--port=8080']).", + "toolReferenceName": "debugJavaApplication", + "tags": [ + "java", + "debug", + "debugger", + "build", + "compile" + ], + "icon": "$(debug-alt)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "target": { + "type": "string", + "description": "What to debug: 1) Main class name - simple ('App') or fully qualified ('com.example.Main'). Tool auto-detects package from source files. 2) JAR file path ('target/app.jar'). 3) Raw Java command arguments ('-cp bin com.example.Main'). The tool automatically finds the .class file for simple class names." + }, + "workspacePath": { + "type": "string", + "description": "Absolute path to the Java project root directory containing pom.xml, build.gradle, or .java source files. This is the working directory for compilation and debugging." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional command-line arguments to pass to the Java main method (e.g., ['arg1', 'arg2', '--flag=value']). These are program arguments, not JVM arguments." + }, + "skipBuild": { + "type": "boolean", + "description": "Whether to skip compilation before debugging. DEFAULT: false (tool will automatically compile the project). Set to true only when you have already compiled the project and want to use an explicit classpath. In most cases, leave this as false to let the tool handle compilation automatically.", + "default": false + }, + "classpath": { + "type": "string", + "description": "Explicit classpath to use for debugging. REQUIRED when skipBuild is true. Format: absolute paths separated by system path delimiter (';' on Windows, ':' on Unix). Example: 'C:\\project\\target\\classes;C:\\project\\lib\\dep.jar' or '/project/target/classes:/project/lib/dep.jar'. If not provided and skipBuild is false, the tool will automatically resolve the classpath." + }, + "waitForSession": { + "type": "boolean", + "description": "Whether to wait for the debug session to start before returning. DEFAULT: false (returns immediately after sending debug command). Set to true to wait up to 30 seconds for VS Code to confirm the debug session has started and is ready. Useful when you need to ensure the debugger is attached before proceeding with breakpoint operations.", + "default": false + } + }, + "required": [ + "target", + "workspacePath" + ] + } + }, + { + "name": "set_java_breakpoint", + "displayName": "Set Java Breakpoint", + "modelDescription": "Set a breakpoint at a specific line in Java source code to pause execution and inspect program state. Supports conditional breakpoints (break only when condition is true), hit count conditions (break after N hits), and logpoints (log messages without stopping). REQUIRES: Active debug session. Start with 1-2 strategic breakpoints; prefer stepping over setting multiple breakpoints.", + "toolReferenceName": "setJavaBreakpoint", + "tags": [ + "java", + "debug", + "breakpoint" + ], + "icon": "$(debug-breakpoint)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "filePath": { + "type": "string", + "description": "Absolute path to the Java source file where the breakpoint should be set. Example: 'C:/project/src/main/java/com/example/Main.java' or use ${workspaceFolder} variable." + }, + "lineNumber": { + "type": "number", + "description": "The line number (1-based) where the breakpoint should be set. Must be a valid executable line (not a comment or blank line)." + }, + "condition": { + "type": "string", + "description": "Optional condition expression. Breakpoint only triggers when condition evaluates to true. Example: 'count > 10' or 'userName.equals(\"admin\")'. Leave empty for unconditional breakpoint." + }, + "hitCondition": { + "type": "string", + "description": "Optional hit count condition. Example: '>5' (break after 5th hit), '==3' (break on 3rd hit), '%2' (break every 2nd hit). Leave empty to break on every hit." + }, + "logMessage": { + "type": "string", + "description": "Optional log message. If provided, instead of breaking, the message will be logged to debug console. Use {expression} for interpolation. Example: 'Counter value: {count}'. This creates a logpoint instead of a breakpoint." + } + }, + "required": [ + "filePath", + "lineNumber" + ] + } + }, + { + "name": "debug_step_operation", + "displayName": "Debug Step Operation", + "modelDescription": "Control program execution flow: stepIn (enter method calls), stepOut (exit current method), stepOver (execute current line), continue (run to next breakpoint), pause (halt execution). REQUIRES: Active debug session in paused state. Prefer stepping through code over setting multiple breakpoints for efficient debugging.", + "toolReferenceName": "debugStepOperation", + "tags": [ + "java", + "debug", + "step", + "continue" + ], + "icon": "$(debug-step-over)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "operation": { + "type": "string", + "enum": [ + "stepIn", + "stepOut", + "stepOver", + "continue", + "pause" + ], + "description": "The step operation to perform: 'stepIn' - step into method calls, 'stepOut' - step out of current method, 'stepOver' - execute current line and move to next, 'continue' - resume execution until next breakpoint, 'pause' - pause running execution." + }, + "threadId": { + "type": "number", + "description": "Optional thread ID to perform operation on. If not specified, operates on the currently selected thread. Use get_debug_threads to get available thread IDs." + } + }, + "required": [ + "operation" + ] + } + }, + { + "name": "get_debug_variables", + "displayName": "Get Debug Variables", + "modelDescription": "Inspect variables in a specific thread's stack frame: local variables, method parameters, static fields, and instance fields. Returns variable names, types, and values. Supports filtering by scope type or name pattern. REQUIRES: Active debug session with at least one SUSPENDED thread. For multi-threaded debugging, use threadId to specify which thread's variables to inspect. If no threadId is provided, uses the first suspended thread.", + "toolReferenceName": "getDebugVariables", + "tags": [ + "java", + "debug", + "variables", + "inspect" + ], + "icon": "$(symbol-variable)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "threadId": { + "type": "number", + "description": "Thread ID to inspect. Use get_debug_threads() to list available threads with their IDs and states. Only SUSPENDED threads can be inspected. If omitted, uses the first suspended thread found." + }, + "frameId": { + "type": "number", + "description": "Optional stack frame ID. Default is 0 (current/top frame). Use get_debug_stack_trace to get available frame IDs. Higher numbers are deeper in the call stack." + }, + "scopeType": { + "type": "string", + "enum": [ + "local", + "static", + "all" + ], + "description": "Type of variables to retrieve: 'local' - only local variables and parameters, 'static' - only static class variables, 'all' - both local and static. Default: 'all'." + }, + "filter": { + "type": "string", + "description": "Optional filter pattern to match variable names. Supports wildcards (*). Example: 'user*' matches 'userName', 'userId'. Leave empty to get all variables." + } + }, + "required": [] + } + }, + { + "name": "get_debug_stack_trace", + "displayName": "Get Debug Stack Trace", + "modelDescription": "Retrieve the call stack showing all method calls leading to the current execution point. Returns method names, source files, and line numbers for each frame. REQUIRES: Active debug session in paused state. Essential for understanding program flow, tracing how code was reached, and identifying unexpected execution paths.", + "toolReferenceName": "getDebugStackTrace", + "tags": [ + "java", + "debug", + "stack", + "callstack" + ], + "icon": "$(call-hierarchy)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "threadId": { + "type": "number", + "description": "Optional thread ID. If not specified, uses the currently selected thread. Use get_debug_threads to list available threads." + }, + "maxDepth": { + "type": "number", + "description": "Maximum number of stack frames to retrieve. Default: 50. Use smaller values for shallow inspection, larger for deep call stacks.", + "default": 50 + } + }, + "required": [] + } + }, + { + "name": "evaluate_debug_expression", + "displayName": "Evaluate Debug Expression", + "modelDescription": "Evaluate a Java expression in a specific thread's debug context. Access local variables, parameters, fields, and invoke methods. Returns the result with type information. REQUIRES: Active debug session with at least one SUSPENDED thread. For multi-threaded debugging, use threadId to specify which thread's context to use. If no threadId is provided, uses the first suspended thread. Examples: 'user.getName()', 'list.size() > 10', 'counter == null'.", + "toolReferenceName": "evaluateDebugExpression", + "tags": [ + "java", + "debug", + "evaluate", + "expression" + ], + "icon": "$(symbol-method)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "expression": { + "type": "string", + "description": "The Java expression to evaluate. Can be a variable name, field access, method call, or complex expression. Example: 'user.age', 'calculateTotal()', 'count > 0 && !items.isEmpty()'." + }, + "threadId": { + "type": "number", + "description": "Thread ID for evaluation context. Use get_debug_threads() to list available threads with their IDs and states. Only SUSPENDED threads can evaluate expressions. If omitted, uses the first suspended thread found." + }, + "frameId": { + "type": "number", + "description": "Optional stack frame ID for evaluation context. Default: 0 (current frame). Variables and methods from the specified frame will be accessible.", + "default": 0 + }, + "context": { + "type": "string", + "enum": [ + "watch", + "repl", + "hover" + ], + "description": "Evaluation context: 'watch' - for watch expressions, 'repl' - for debug console input, 'hover' - for hover tooltips. Affects how side effects are handled. Default: 'repl'.", + "default": "repl" + } + }, + "required": [ + "expression" + ] + } + }, + { + "name": "get_debug_threads", + "displayName": "Get Debug Threads", + "modelDescription": "List all threads in the debugged Java application with their IDs, names, and states (🔴 SUSPENDED or 🟢 RUNNING). For SUSPENDED threads, also shows the current location (file:line). REQUIRES: Active debug session. IMPORTANT: Only SUSPENDED threads can have their variables inspected or expressions evaluated. Use the returned thread IDs with get_debug_variables(threadId=X) or evaluate_debug_expression(threadId=X) to inspect specific threads.", + "toolReferenceName": "getDebugThreads", + "tags": [ + "java", + "debug", + "threads", + "concurrent" + ], + "icon": "$(list-tree)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": {}, + "required": [] + } + }, + { + "name": "remove_java_breakpoints", + "displayName": "Remove Java Breakpoints", + "modelDescription": "Remove breakpoints: specific breakpoint by file and line, all breakpoints in a file, or all breakpoints globally. Use this to clean up after investigation or before setting new breakpoints. Best practice: keep only 1-2 active breakpoints at a time; remove old ones before adding new ones.", + "toolReferenceName": "removeJavaBreakpoints", + "tags": [ + "java", + "debug", + "breakpoint" + ], + "icon": "$(debug-breakpoint-unverified)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "filePath": { + "type": "string", + "description": "Absolute path to the Java source file. If not provided, removes all breakpoints from all files." + }, + "lineNumber": { + "type": "number", + "description": "Optional line number. If provided, removes only the breakpoint at this line. If omitted, removes all breakpoints in the specified file." + } + }, + "required": [] + } + }, + { + "name": "stop_debug_session", + "displayName": "Stop Debug Session", + "modelDescription": "Stop the active Java debug session when investigation is complete or when you need to restart debugging. This terminates the running Java process and closes the debug session. Use this to clean up after debugging or when you've identified the root cause and want to end the session. Optional: Provide a reason for stopping (e.g., 'Investigation complete', 'Root cause identified').", + "toolReferenceName": "stopDebugSession", + "tags": [ + "java", + "debug", + "stop", + "terminate" + ], + "icon": "$(debug-stop)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "Optional reason for stopping the debug session (e.g., 'Investigation complete', 'Root cause identified', 'Need to restart'). Default: 'Investigation complete'." + } + }, + "required": [] + } + }, + { + "name": "get_debug_session_info", + "displayName": "Get Debug Session Info", + "modelDescription": "Get information about the currently active Java debug session, including whether it's PAUSED at a breakpoint or RUNNING. CRITICAL: Check status before using inspection tools (get_debug_variables, get_debug_stack_trace, evaluate_debug_expression) or control operations (continue, step). PAUSED status (🔴) means stopped at breakpoint - inspection and control tools available. RUNNING status (🟢) means executing code - only breakpoint setting or session stop available. Returns session ID, name, type, configuration details, and status-specific available actions.", + "toolReferenceName": "getDebugSessionInfo", + "tags": [ + "java", + "debug", + "session", + "info", + "status", + "paused", + "running" + ], + "icon": "$(info)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": {}, + "required": [] } } - } + ] }, "scripts": { - "vscode:prepublish": "tsc -p ./", - "compile": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "node ./node_modules/vscode/bin/test" + "vscode:prepublish": "npm run build", + "compile": "tsc -p . && webpack --config webpack.config.js", + "watch": "webpack --config webpack.config.js --watch", + "build": "webpack --config webpack.config.js --mode=\"production\"", + "tslint": "tslint -t verbose --project tsconfig.json", + "build-server": "node scripts/build/buildJdtlsExt.js", + "test": "npm run compile && node ./out/test/index.js" }, - "extensionDependencies": [ - "redhat.java" - ], "devDependencies": { - "@types/mocha": "^2.2.32", - "@types/node": "^6.0.40", - "gulp": "^3.9.1", - "gulp-copy": "^1.0.1", - "gulp-tslint": "^8.1.2", - "mocha": "^2.3.3", - "tslint": "^5.7.0", - "typescript": "^2.0.3", - "vscode": "^1.1.5" + "@types/glob": "^7.2.0", + "@types/lodash": "^4.17.13", + "@types/mocha": "^10.0.9", + "@types/node": "^14.18.63", + "@types/uuid": "^8.3.4", + "@types/vscode": "1.95.0", + "@vscode/test-electron": "^2.4.1", + "mocha": "^10.8.2", + "ts-loader": "^9.5.1", + "tslint": "^6.1.3", + "typescript": "^4.9.5", + "webpack": "^5.105.0", + "webpack-cli": "^4.10.0" }, "dependencies": { - "vscode-extension-telemetry": "0.0.8" + "compare-versions": "^4.1.4", + "dotenv": "^16.4.5", + "lodash": "^4.17.23", + "uuid": "^8.3.2", + "vscode-extension-telemetry-wrapper": "^0.14.0", + "vscode-languageclient": "6.0.0-next.9", + "vscode-languageserver-types": "3.16.0", + "vscode-tas-client": "^0.1.84" } } diff --git a/package.nls.es.json b/package.nls.es.json new file mode 100644 index 00000000..06b87c18 --- /dev/null +++ b/package.nls.es.json @@ -0,0 +1,63 @@ +{ + "java.debugger.launch.projectName.description": "El proyecto preferido en el que el depurador busca clases. Podría haber nombres de clases duplicados en diferentes proyectos. Esta configuración también funciona cuando el depurador busca la clase principal especificada al lanzar un programa. Es necesario para la evaluación de la expresión.", + "java.debugger.launch.mainClass.description": "El nombre de la clase totalmente cualificado (por ejemplo, [nombre del módulo de java/]com.xyz.MainApp) o la ruta del archivo Java de la entrada del programa.", + "java.debugger.launch.args.description": "Los argumentos de la línea de comandos pasados al programa.", + "java.debugger.launch.vmArgs.description": "Las opciones extra y las propiedades del sistema para la JVM (por ejemplo -Xms -Xmx -D=).", + "java.debugger.launch.modulePaths.description": "Los modulepaths para el lanzamiento de la JVM. Si no se especifica, el depurador se resolverá automáticamente a partir del proyecto actual.", + "java.debugger.launch.classPaths.description": "Los classpath para el lanzamiento de la JVM. Si no se especifica, el depurador se resolverá automáticamente a partir del proyecto actual.", + "java.debugger.launch.sourcePaths.description": "Los directorios de fuentes extras del programa. El depurador busca el código fuente de los ajustes del proyecto por defecto. Esta opción permite al depurador buscar el código fuente en directorios extra.", + "java.debugger.launch.encoding.description": "La configuración de codificación de archivos para la JVM. Los posibles valores se pueden encontrar en https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html.", + "java.debugger.launch.cwd.description": "El directorio de trabajo del programa. Por defecto es la raíz del área de trabajo actual.", + "java.debugger.launch.env.description": "Las variables de entorno adicionales para el programa.", + "java.debugger.launch.stopOnEntry.description": "Pausar automáticamente el programa después del lanzamiento.", + "java.debugger.launch.internalConsole.description": "Consola de Depuración de VS Code (flujo de entrada no soportado).", + "java.debugger.launch.integratedTerminal.description": "Terminal integrado de VS Code.", + "java.debugger.launch.externalTerminal.description": "Terminal externo que puede ser configurado en la configuración del usuario.", + "java.debugger.launch.console.description": "La consola establecida para iniciar el programa.", + "java.debugger.launch.shortenCommandLine.auto": "Detectar automáticamente la longitud de la línea de comando y determinar si acortar la línea de comando mediante un enfoque apropiado.", + "java.debugger.launch.shortenCommandLine.none": "Lanza el programa con la línea de comandos estándar 'java [opciones] nombredeclase [args]'.", + "java.debugger.launch.shortenCommandLine.jarmanifest": "Generar los parámetros de classpath a un archivo temporal classpath.jar, y lanzar el programa con la línea de comandos 'java -cp classpath.jar nombre de clase [args]'.", + "java.debugger.launch.shortenCommandLine.argfile": "Generar los parámetros de classpath en un archivo de argumentos temporal, y lanzar el programa con la línea de comandos 'java @argfile [args]'. Este valor sólo se aplica a Java 9 y superiores.", + "java.debugger.launch.shortenCommandLine.description": "Cuando el proyecto tiene classpath largos o argumentos de la VM grandes, la línea de comandos para lanzar el programa puede exceder el límite máximo de string en la consola permitido por el SO. Este elemento de configuración proporciona múltiples enfoques para acortar la línea de comandos.", + "java.debugger.launch.stepFilters.description": "Omitir clases o métodos especificados al avanzar pasos.", + "java.debugger.launch.skipClasses.description": "Omitir las clases especificadas al avanzar pasos. Puedes usar las variables incorporadas como '$JDK' y '$Libraries' para omitir un grupo de clases, o añadir una expresión específica de nombre de clase, por ejemplo, java.*, *.Pepe", + "java.debugger.launch.skipClasses.skipJDK": "Omitir las clases del JDK del classpath del sistema predeterminado, como rt.jar, jrt-fs.jar.", + "java.debugger.launch.skipClasses.skipLibraries": "Omite las clases de las bibliotecas de aplicaciones, como las dependencias de Maven y Gradle.", + "java.debugger.launch.skipClasses.skipClassLoader": "Omitir los cargadores de clase.", + "java.debugger.launch.skipClasses.skipClassPattern": "Omitir las clases especificadas. Los nombres de las clases deben estar completamente calificados. Se admite el uso de comodines, por ejemplo, java.*, *.Pepe", + "java.debugger.launch.skipSynthetics.description": "Omitir los métodos sintéticos al avanzar pasos.", + "java.debugger.launch.skipStaticInitializers.description": "Omitir los métodos de inicialización static al avanzar pasos.", + "java.debugger.launch.skipConstructors.description": "Omitir los métodos constructores al avanzar pasos.", + "java.debugger.attach.hostName.description": "El nombre del host o la dirección ip del depurador remoto.", + "java.debugger.attach.port.description": "El puerto de depuración del depurador remoto.", + "java.debugger.attach.processPicker.description": "Utilice el selector de procesos para seleccionar un proceso al que acoplarse, o el ID del proceso como un número entero.", + "java.debugger.attach.processId.description": "ID del proceso local al que acoplarse.", + "java.debugger.attach.timeout.description": "Límite de tiempo de espera antes de reconectarse, en milisegundos (por defecto a 30000ms).", + "java.debugger.attach.projectName.description": "El proyecto preferido en el que el depurador busca clases. Podría haber nombres de clases duplicados en diferentes proyectos.", + "java.debugger.snippet.launch.description": "Añade una nueva configuración para lanzar un programa Java.", + "java.debugger.snippet.launchInExternalTerminal.description": "Añade una nueva configuración para lanzar un programa Java en la terminal externa.", + "java.debugger.snippet.launchCurrentFile.description": "Añade una nueva configuración para lanzar el archivo Java actual.", + "java.debugger.snippet.launchWithArgumentsPrompt.description": "Añade una nueva configuración para lanzar un programa Java con argumentos.", + "java.debugger.snippet.attach.description": "Añade una nueva configuración para acoplarse a un programa Java en ejecución.", + "java.debugger.snippet.attachProcess.description": "Utilice el selector de procesos para seleccionar un proceso Java al que acoplarse.", + "java.debugger.snippet.attachRemote.description": "Añade una nueva configuración para acoplarse a un programa Java remoto.", + "java.debugger.configuration.title": "Depurador de Java", + "java.debugger.configuration.logLevel.description": "Nivel mínimo de registros de depuración que se envían a VS Code.", + "java.debugger.configuration.showHex.description": "Mostrar los números en formato hexadecimal en la vista \"Variables\".", + "java.debugger.configuration.showStaticVariables.description": "Muestra las variables estáticas en la vista \"Variables\".", + "java.debugger.configuration.showQualifiedNames.description": "Mostrar los nombres de las clases totalmente cualificados en la vista de \"Variables\".", + "java.debugger.configuration.showLogicalStructure.description": "Mostrar la estructura lógica de las clases Collection y Map en la vista de \"Variables\".", + "java.debugger.configuration.showToString.description": "Mostrar el valor 'toString()' en la vista \"Variables\" para todas las clases que sobrescriban el método 'toString'.", + "java.debugger.configuration.maxStringLength.description": "La longitud máxima de los strings mostrados en la vista \"Variables\" o \"Consola de Depuración\", los strings más largos que esta longitud serán recortados, si es 0 no se realiza recorte.", + "java.debugger.configuration.numericPrecision.description": "La precisión en el formato de números reales en la vista \"Variables\" o \"Consola de Depuración\".", + "java.debugger.configuration.hotCodeReplace.description": "Recargar las clases de Java modificadas durante la depuración. Asegúrate de que 'java.autobuild.enabled' no esté desactivado.", + "java.debugger.configuration.enableRunDebugCodeLens.description": "Habilitar proveedores de CodeLens para la ejecución y depuración sobre los métodos principales.", + "java.debugger.configuration.forceBuildBeforeLaunch": "Forzar la compilación del área de trabajo antes de lanzar el programa Java.", + "java.debugger.configuration.onBuildFailureProceed": "Forzar continuar cuando falla la compilación.", + "java.debugger.configuration.console": "La consola establecida para lanzar el programa Java. Si quieres personalizar la consola para una sesión de depuración específica, por favor modifica la configuración de la 'console' en launch.json.", + "java.debugger.configuration.exceptionBreakpoint.skipClasses": "Omitir las clases especificadas al parar por una excepción. Puedes usar las variables incorporadas como '$JDK' y '$Libraries' para omitir un grupo de clases, o añadir una expresión específica de nombre de clase, por ejemplo, java.*, *.Pepe", + "java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description": "El máximo número de variables o campos que pueden ser solicitados en una solicitud de JDWP. Cuanto más alto sea el valor, menos frecuentemente se solicitará la depuración al expandir la vista de la variable. Además, un número grande puede causar un límite de tiempo de espera de la solicitud JDWP.", + "java.debugger.configuration.jdwp.requestTimeout.description": "El límite de tiempo (ms) de la solicitud de JDWP cuando el depurador se comunica con el JVM objetivo.", + "java.debugger.configuration.vmArgs.description": "Los argumentos por defecto de la VM para lanzar el programa Java. Por ejemplo, usa '-Xmx1G -ea' para aumentar el tamaño de la pila a 1GB y habilitar los asertos. Si quieres personalizar los argumentos de la máquina virtual para una sesión de depuración específica, modifica la configuración de 'vmArgs' en launch.json.", + "java.debugger.configuration.suspendAllThreads.description": "Suspenda todos los hilos al alcanzar un punto de interrupción o detenerse por una excepción. Solo tiene efecto en nuevas sesiones de depuración; los cambios durante una sesión en ejecución no se aplican." +} \ No newline at end of file diff --git a/package.nls.it.json b/package.nls.it.json new file mode 100644 index 00000000..9279a2bd --- /dev/null +++ b/package.nls.it.json @@ -0,0 +1,10 @@ +{ + "java.debugger.configuration.title": "Java Debugger", + "java.debugger.configuration.logLevel.description": "Livello dei log di debug minimo inviato a VS Code.", + "java.debugger.configuration.showHex.description": "Mostra numeri in formato esadecimale nella scheda \"variabili\".", + "java.debugger.configuration.showStaticVariables.description": "Mostra variabili statiche nella scheda \"variabili\".", + "java.debugger.configuration.showQualifiedNames.description": "Mostra nome completo delle classi nella scheda \"variabili\".", + "java.debugger.configuration.maxStringLength.description": "Lunghezza massima delle stringhe visualizzate nella scheda \"Variabili\" o \"Console di Debug\", stringhe più lunghe di questo numero verranno tagliate, se 0 nessun taglio viene eseguito.", + "java.debugger.configuration.enableRunDebugCodeLens.description": "Abilitare i provider di lenti di codice run e debug sui metodi principali.", + "java.debugger.configuration.suspendAllThreads.description": "Sospende tutti i thread quando si raggiunge un punto di interruzione o ci si ferma per un'eccezione. Ha effetto solo nelle nuove sessioni di debug; le modifiche durante una sessione in esecuzione non si applicano." +} diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 00000000..8634a297 --- /dev/null +++ b/package.nls.json @@ -0,0 +1,78 @@ +{ + "java.debugger.launch.projectName.description": "The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. It is required for expression evaluation.", + "java.debugger.launch.mainClass.description": "The fully qualified class name (e.g. [java module name/]com.xyz.MainApp) or the java file path of the program entry.", + "java.debugger.launch.javaExec.description": "The path to java executable to use. If unset project JDK's java executable is used.", + "java.debugger.launch.args.description": "The command line arguments passed to the program.", + "java.debugger.launch.vmArgs.description": "The extra options and system properties for the JVM (e.g. -Xms -Xmx -D=).", + "java.debugger.launch.modulePaths.description": "The modulepaths for launching the JVM. If not specified, the debugger will automatically resolve from current project.", + "java.debugger.launch.modulePaths.auto": "Automatically resolve the module paths of current project.", + "java.debugger.launch.modulePaths.runtime": "The module paths within 'runtime' scope of current project.", + "java.debugger.launch.modulePaths.test": "The module paths within 'test' scope of current project.", + "java.debugger.launch.modulePaths.exclude": "The path after '!' will be excluded from the modulePaths.", + "java.debugger.launch.classPaths.description": "The classpaths for launching the JVM. If not specified, the debugger will automatically resolve from current project.", + "java.debugger.launch.classPaths.auto": "Automatically resolve the classpaths of current project.", + "java.debugger.launch.classPaths.runtime": "The classpaths within 'runtime' scope of current project.", + "java.debugger.launch.classPaths.test": "The classpaths within 'test' scope of current project.", + "java.debugger.launch.classPaths.exclude": "The path after '!' will be excluded from the classpaths.", + "java.debugger.launch.sourcePaths.description": "The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories.", + "java.debugger.launch.encoding.description": "The file.encoding setting for the JVM. Possible values can be found in https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html.", + "java.debugger.launch.cwd.description": "The working directory of the program. Defaults to the current workspace root.", + "java.debugger.launch.env.description": "The extra environment variables for the program.", + "java.debugger.launch.envFile.description": "Absolute path to a file containing environment variable definitions. Multiple files can be specified by providing an array of absolute paths.", + "java.debugger.launch.stopOnEntry.description": "Automatically pause the program after launching.", + "java.debugger.launch.internalConsole.description": "VS Code debug console (input stream not supported).", + "java.debugger.launch.integratedTerminal.description": "VS Code integrated terminal.", + "java.debugger.launch.externalTerminal.description": "External terminal that can be configured in user settings.", + "java.debugger.launch.console.description": "The specified console to launch the program.", + "java.debugger.launch.shortenCommandLine.auto": "Automatically detect the command line length and determine whether to shorten the command line via an appropriate approach.", + "java.debugger.launch.shortenCommandLine.none": "Launch the program with the standard command line 'java [options] classname [args]'.", + "java.debugger.launch.shortenCommandLine.jarmanifest": "Generate the classpath parameters to a temporary classpath.jar file, and launch the program with the command line 'java -cp classpath.jar classname [args]'.", + "java.debugger.launch.shortenCommandLine.argfile": "Generate the classpath parameters to a temporary argument file, and launch the program with the command line 'java @argfile [args]'. This value only applies to Java 9 and higher.", + "java.debugger.launch.shortenCommandLine.description": "When the project has long classpath or big VM arguments, the command line to launch the program may exceed the maximum command line string limitation allowed by the OS. This configuration item provides multiple approaches to shorten the command line.", + "java.debugger.launch.stepFilters.description": "Skip specified classes or methods when stepping.", + "java.debugger.launch.skipClasses.description": "Skip the specified classes when stepping. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo", + "java.debugger.launch.skipClasses.skipJDK": "Skip the JDK classes from the default system bootstrap classpath, such as rt.jar, jrt-fs.jar.", + "java.debugger.launch.skipClasses.skipLibraries": "Skip the classes from application libraries, such as Maven, Gradle dependencies.", + "java.debugger.launch.skipClasses.skipClassLoader": "Skip the class loaders.", + "java.debugger.launch.skipClasses.skipClassPattern": "Skip the specified classes. Class names should be fully qualified. Wildcard is supported, e.g. java.*, *.Foo", + "java.debugger.launch.skipSynthetics.description": "Skip synthetic methods when stepping.", + "java.debugger.launch.skipStaticInitializers.description": "Skip static initializer methods when stepping.", + "java.debugger.launch.skipConstructors.description": "Skip constructor methods when stepping.", + "java.debugger.attach.hostName.description": "The host name or ip address of remote debuggee.", + "java.debugger.attach.port.description": "The debug port of remote debuggee.", + "java.debugger.attach.processPicker.description": "Use process picker to select a process to attach, or Process ID as integer.", + "java.debugger.attach.processId.description": "ID of the local process to attach to.", + "java.debugger.attach.timeout.description": "Timeout value before reconnecting, in milliseconds (default to 30000ms).", + "java.debugger.attach.projectName.description": "The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects.", + "java.debugger.snippet.launch.description": "Add a new configuration for launching a java program.", + "java.debugger.snippet.launchInExternalTerminal.description": "Add a new configuration for launching a java program in the external terminal.", + "java.debugger.snippet.launchCurrentFile.description": "Add a new configuration for launching current java file.", + "java.debugger.snippet.launchWithArgumentsPrompt.description": "Add a new configuration for launching a java program with arguments prompt.", + "java.debugger.snippet.attach.description": "Add a new configuration for attaching to a running java program.", + "java.debugger.snippet.attachProcess.description": "Use process picker to select a Java process to attach to.", + "java.debugger.snippet.attachRemote.description": "Add a new configuration for attaching to a remote java program.", + "java.debugger.configuration.title": "Java Debugger", + "java.debugger.configuration.logLevel.description": "Minimum level of debugger logs that are sent to VS Code.", + "java.debugger.configuration.showHex.description": "Show numbers in hex format in \"Variables\" viewlet.", + "java.debugger.configuration.showStaticVariables.description": "Show static variables in \"Variables\" viewlet.", + "java.debugger.configuration.showQualifiedNames.description": "Show fully qualified class names in \"Variables\" viewlet.", + "java.debugger.configuration.showLogicalStructure.description": "Show the logical structure for the Collection and Map classes in \"Variables\" viewlet.", + "java.debugger.configuration.showToString.description": "Show 'toString()' value for all classes that override 'toString' method in \"Variables\" viewlet.", + "java.debugger.configuration.maxStringLength.description": "The maximum length of strings displayed in \"Variables\" or \"Debug Console\" viewlet, strings longer than this length will be trimmed, if 0 no trim is performed.", + "java.debugger.configuration.numericPrecision.description": "The precision when formatting doubles in \"Variables\" or \"Debug Console\" viewlet.", + "java.debugger.configuration.hotCodeReplace.description": "Reload the changed Java classes during debugging.", + "java.debugger.configuration.enableRunDebugCodeLens.description": "Enable the run and debug code lens providers over main methods.", + "java.debugger.configuration.forceBuildBeforeLaunch": "Force building the workspace before launching java program.", + "java.debugger.configuration.onBuildFailureProceed": "Force to proceed when build fails", + "java.debugger.configuration.console": "The specified console to launch Java program. If you want to customize the console for a specific debug session, please modify the 'console' config in launch.json.", + "java.debugger.configuration.exceptionBreakpoint.exceptionTypes": "Specifies a set of exception types you want to break on, e.g. java.lang.NullPointerException. A specific exception type and its subclasses can be selected for caught exceptions, uncaught exceptions, or both can be selected.", + "java.debugger.configuration.exceptionBreakpoint.allowClasses": "Specifies the allowed locations where the exception breakpoint can break on. Wildcard is supported, e.g. java.*, *.Foo", + "java.debugger.configuration.exceptionBreakpoint.skipClasses": "Skip the specified classes when breaking on exception. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo", + "java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description": "The maximum number of variables or fields that can be requested in one JDWP request. The higher the value, the less frequently debuggee will be requested when expanding the variable view. Also a large number can cause JDWP request timeout.", + "java.debugger.configuration.jdwp.requestTimeout.description": "The timeout (ms) of JDWP request when the debugger communicates with the target JVM.", + "java.debugger.configuration.vmArgs.description": "The default VM arguments to launch the Java program. Eg. Use '-Xmx1G -ea' to increase the heap size to 1GB and enable assertions. If you want to customize the VM arguments for a specific debug session, please modify the 'vmArgs' config in launch.json.", + "java.debugger.configuration.silentNotification": "Controls whether notifications can be used to report progress. If true, use status bar to report progress instead.", + "java.debugger.configuration.jdwp.async.description": "Experimental: Controls whether the debugger is allowed to send JDWP commands asynchronously. Async mode can improve remote debugging response speed on high-latency networks.", + "java.debugger.configuration.debugSupportOnDecompiledSource.description": "[Experimental]: Enable debugging support on the decompiled source code. Be aware that this feature may affect the loading speed of Call Stack Viewlet.", + "java.debugger.configuration.suspendAllThreads.description": "Suspend all threads when hitting a breakpoint or stopping for an exception. Takes effect only for new debug sessions; changes during a running session don’t apply." +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json new file mode 100644 index 00000000..75d1406a --- /dev/null +++ b/package.nls.zh-cn.json @@ -0,0 +1,75 @@ +{ + "java.debugger.launch.projectName.description": "调试器搜索类名时的首选工程。不同工程中可能存在重复的类名。当调试器在启动应用程序时查找指定的主类,此设置也有效。当使用表达式求值功能时,需要此配置项。", + "java.debugger.launch.mainClass.description": "主类的全名(例如[java module name /] com.xyz.MainApp)或主类对应的java文件路径。", + "java.debugger.launch.args.description": "启动应用程序的命令行参数。", + "java.debugger.launch.vmArgs.description": "用于启动JVM的额外选项和系统属性(例如-Xms -Xmx -D = )。", + "java.debugger.launch.modulePaths.description": "用于启动JVM的模块路径。如果未指定,调试器将自动从当前工程中解析。", + "java.debugger.launch.modulePaths.auto": "自动从当前工程中解析模块路径。", + "java.debugger.launch.modulePaths.runtime": "当前工程中属于 runtime 作用域的模块路径。", + "java.debugger.launch.modulePaths.test": "当前工程中属于 test 作用域的模块路径。", + "java.debugger.launch.modulePaths.exclude": "'!' 之后的路径将会从模块路径中去除。", + "java.debugger.launch.classPaths.description": "用于启动JVM的类路径。如果未指定,调试器将自动从当前工程中解析。", + "java.debugger.launch.classPaths.auto": "自动从当前工程中解析类路径。", + "java.debugger.launch.classPaths.runtime": "当前工程中属于 runtime 作用域的类路径。", + "java.debugger.launch.classPaths.test": "当前工程中属于 test 作用域的类路径。", + "java.debugger.launch.classPaths.exclude": "'!' 之后的路径将会从类路径中去除。", + "java.debugger.launch.sourcePaths.description": "应用程序的额外源代码目录。调试器默认从工程配置中查找源代码。此选项允许调试器在额外目录中查找源代码。", + "java.debugger.launch.encoding.description": "JVM的file.encoding设置。可以在http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html中找到可能的值。", + "java.debugger.launch.cwd.description": "应用程序的工作目录。默认为当前工作空间根目录。", + "java.debugger.launch.env.description": "启动应用程序时自定义的环境变量。", + "java.debugger.launch.envFile.description": "环境变量文件绝对路径。", + "java.debugger.launch.stopOnEntry.description": "启动后自动暂停应用程序。", + "java.debugger.launch.internalConsole.description": "VS Code调试控制台(不支持输入流)。", + "java.debugger.launch.integratedTerminal.description": "VS Code集成终端。", + "java.debugger.launch.externalTerminal.description": "外部终端(可在用户设置中修改)。", + "java.debugger.launch.console.description": "用于启动应用程序的控制台。", + "java.debugger.launch.shortenCommandLine.auto": "自动检测命令行长度并决定是否通过适当的方法缩短命令行。", + "java.debugger.launch.shortenCommandLine.none": "使用标准命令行 'java [options] classname [args]' 启动应用程序。", + "java.debugger.launch.shortenCommandLine.jarmanifest": "将类路径参数生成到临时 classpath.jar 文件中,并使用命令行 'java -cp classpath.jar classname [args]' 启动应用程序。", + "java.debugger.launch.shortenCommandLine.argfile": "将类路径参数生成到临时 argument 文件中, 并使用命令行 'java @argfile [args]' 启动应用程序。该值仅适用于 Java 9 及以上版本。", + "java.debugger.launch.shortenCommandLine.description": "当项目具有较长的类路径或较大的VM参数时,启动程序的命令行可能会超出OS允许的最大命令行字符串限制。此配置项提供了多种缩短命令行的方法。", + "java.debugger.launch.stepFilters.description": "Step时跳过指定的类或方法。", + "java.debugger.launch.skipClasses.description": "Step时跳过指定的类。你可以使用内置变量,如'$JDK'和'$Libraries'来跳过一组类,或者添加一个特定的类名表达式,如java.*,*.Foo。", + "java.debugger.launch.skipClasses.skipJDK": "跳过系统默认的启动路径中的JDK类,如rt.jar、jrt-fs.jar。", + "java.debugger.launch.skipClasses.skipLibraries": "跳过应用库中的类,如Maven、Gradle依赖。", + "java.debugger.launch.skipClasses.skipClassLoader": "跳过类加载器。", + "java.debugger.launch.skipClasses.skipClassPattern": "跳过指定的类。仅支持全名,以及通配符,如java.*,*.Foo。", + "java.debugger.launch.skipSynthetics.description": "Step时跳过合成方法。", + "java.debugger.launch.skipStaticInitializers.description": "Step时跳过静态初始化方法。", + "java.debugger.launch.skipConstructors.description": "Step时跳过构造函数。", + "java.debugger.attach.hostName.description": "远程调试进程所在的主机名或IP地址。", + "java.debugger.attach.port.description": "远程调试进程的调试端口。", + "java.debugger.attach.processPicker.description": "使用进程选取器选择要附加的进程,或直接配置进程ID。", + "java.debugger.attach.processId.description": "要附加到的本地进程的ID。", + "java.debugger.attach.timeout.description": "重新连接前的超时值,以毫秒为单位(默认为30000ms)。", + "java.debugger.attach.projectName.description": "调试器搜索类的首选工程。不同工程中可能存在重复的类名。", + "java.debugger.snippet.launch.description": "启动java程序。", + "java.debugger.snippet.launchInExternalTerminal.description": "在外部终端中启动java程序。", + "java.debugger.snippet.launchCurrentFile.description": "启动当前java文件中的程序。", + "java.debugger.snippet.launchWithArgumentsPrompt.description": "启动java程序时动态提示命令行参数。", + "java.debugger.snippet.attach.description": "附加到正在运行的java程序。", + "java.debugger.snippet.attachProcess.description": "使用进程选择器选择要附加的Java进程。", + "java.debugger.snippet.attachRemote.description": "附加到远程java程序。", + "java.debugger.configuration.title": "Java调试器", + "java.debugger.configuration.logLevel.description": "Java调试器的日志级别。", + "java.debugger.configuration.showHex.description": "在“变量”视图中以十六进制格式显示数值。", + "java.debugger.configuration.showStaticVariables.description": "在“变量”视图中显示静态变量。", + "java.debugger.configuration.showQualifiedNames.description": "在“变量”视图中显示类的全名。", + "java.debugger.configuration.showLogicalStructure.description": "在“变量”视图中显示Collection和Map类的逻辑结构。", + "java.debugger.configuration.showToString.description": "在“变量”视图中显示所有重载过'toString'方法的类的'toString()'值。", + "java.debugger.configuration.maxStringLength.description": "设定“变量”或“调试控制台”视图中显示的字符串最大长度,长度超过部分将被剪掉。如果值为0,则不执行修剪。", + "java.debugger.configuration.hotCodeReplace.description": "在调试期间重新加载已更改的Java类。", + "java.debugger.configuration.enableRunDebugCodeLens.description": "在main方法上启用CodeLens标记。", + "java.debugger.configuration.forceBuildBeforeLaunch": "在启动java程序之前强制编译整个工作空间。", + "java.debugger.configuration.console": "指定的控制台用于启动Java程序。如果要为特定的调试会话自定义控制台,请修改launch.json中的“console”配置。", + "java.debugger.configuration.exceptionBreakpoint.exceptionTypes": "指定要中断的一组异常类型,例如 java.lang.NullPointerException。可以为捕获的异常、未捕获的异常或两者都选择一个特定的异常类型及其子类。", + "java.debugger.configuration.exceptionBreakpoint.allowClasses": "指定允许异常断点中断的位置。支持通配符,例如 java.,.Foo", + "java.debugger.configuration.exceptionBreakpoint.skipClasses": "当发生异常时,跳过指定的类。你可以使用内置变量,如'$JDK'和'$Libraries'来跳过一组类,或者添加一个特定的类名表达式,如java.*,*.Foo。", + "java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description": "一次JDWP请求中可以请求的变量或字段的最大数量。该值越高,在展开变量视图时,请求debuggee的频率就越低。同时数量过大也会导致JDWP请求超时。", + "java.debugger.configuration.jdwp.requestTimeout.description": "调试器与目标JVM通信时JDWP请求的超时时间(ms)。", + "java.debugger.configuration.vmArgs.description": "启动Java程序的默认VM参数。例如,使用'-Xmx1G -ea'将堆大小增加到1GB并启用断言。如果要为特定的调试会话定制VM参数,请修改launch.json中的'vmArgs'配置。", + "java.debugger.configuration.silentNotification": "控制是否可以使用通知来报告进度。如果为真,则使用状态栏来报告进度。", + "java.debugger.configuration.jdwp.async.description": "实验性的:控制是否允许调试器以异步方式发送JDWP命令。异步模式可以提高高延迟网络上的远程调试响应速度。", + "java.debugger.configuration.debugSupportOnDecompiledSource.description": "[实验性的]: 在反编译的源代码上启用调试支持。请注意,该功能可能会影响Call Stack试图的加载速度。", + "java.debugger.configuration.suspendAllThreads.description": "当命中断点或因异常停止时暂停所有线程。仅对新的调试会话生效;在运行中的会话内更改不会生效。" +} \ No newline at end of file diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json new file mode 100644 index 00000000..4261c873 --- /dev/null +++ b/package.nls.zh-tw.json @@ -0,0 +1,71 @@ +{ + "java.debugger.launch.projectName.description": "偵錯器搜索類別名時的偏好專案。不同專案中可能存在重復的類別名。當偵錯器在啟動應用程式時查找指定的主類別,此設定也有效。當使用表達式求值功能時,需要此選項。", + "java.debugger.launch.mainClass.description": "主類別的全名(例如 [java module name /] com.xyz.MainApp)或主類別對應的 Java 檔案路徑。", + "java.debugger.launch.args.description": "啟動應用程式的命令列參數。", + "java.debugger.launch.vmArgs.description": "用於啟動 JVM 的額外選項和系統屬性(例如-Xms -Xmx -D = )。", + "java.debugger.launch.modulePaths.description": "用於啟動 JVM 的模組路徑。如果未指定,偵錯器將自動從當前專案中解析。", + "java.debugger.launch.modulePaths.auto": "自動從當前專案中解析模組路徑。", + "java.debugger.launch.modulePaths.runtime": "當前專案中屬於 runtime 範圍的模組路徑。", + "java.debugger.launch.modulePaths.test": "當前專案中屬於 test 範圍的模組路徑。", + "java.debugger.launch.modulePaths.exclude": "'!' 之後的路徑將會從模組路徑中去除。", + "java.debugger.launch.classPaths.description": "用於啟動 JVM 的類別路徑。如果未指定,偵錯器將自動從當前專案中解析。", + "java.debugger.launch.classPaths.auto": "自動從當前專案中解析類別路徑。", + "java.debugger.launch.classPaths.runtime": "當前專案中屬於 runtime 範圍的類別路徑。", + "java.debugger.launch.classPaths.test": "當前專案中屬於 test 範圍的類別路徑。", + "java.debugger.launch.classPaths.exclude": "'!' 之後的路徑將會從類別路徑中去除。", + "java.debugger.launch.sourcePaths.description": "應用程式的額外原始碼目錄。偵錯器預設從專案設定中查找原始碼。此選項允許偵錯器在額外目錄中查找原始碼。", + "java.debugger.launch.encoding.description": "JVM 的 file.encoding 設定。可以在 http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html 中找到可能的值。", + "java.debugger.launch.cwd.description": "應用程式的工作目錄。預設為當前工作空間根目錄。", + "java.debugger.launch.env.description": "啟動應用程式時自定義的環境變數。", + "java.debugger.launch.envFile.description": "環境變數檔案絕對路徑。", + "java.debugger.launch.stopOnEntry.description": "啟動後自動暫停應用程式。", + "java.debugger.launch.internalConsole.description": "VS Code 偵錯主控台(不支援輸入串流)。", + "java.debugger.launch.integratedTerminal.description": "VS Code 整合終端。", + "java.debugger.launch.externalTerminal.description": "外部終端(可在用戶設定中修改)。", + "java.debugger.launch.console.description": "用於啟動應用程式的主控台。", + "java.debugger.launch.shortenCommandLine.auto": "自動檢測命令列長度並決定是否通過適當的方法縮短命令列。", + "java.debugger.launch.shortenCommandLine.none": "使用標準命令列 'java [options] classname [args]' 啟動應用程式。", + "java.debugger.launch.shortenCommandLine.jarmanifest": "將類別路徑參數生成到臨時 classpath.jar 檔案中,並使用命令列 'java -cp classpath.jar classname [args]' 啟動應用程式。", + "java.debugger.launch.shortenCommandLine.argfile": "將類別路徑參數生成到臨時 argument 檔案中, 並使用命令列 'java @argfile [args]' 啟動應用程式。該值僅適用於 Java 9 及以上版本。", + "java.debugger.launch.shortenCommandLine.description": "當項目具有較長的類別路徑或較大的 VM 參數時,啟動程式的命令列可能會超出OS允許的最大命令列字元串限制。此選項提供了多種縮短命令列的方法。", + "java.debugger.launch.stepFilters.description": "Step 時跳過指定的類別或方法。", + "java.debugger.launch.skipClasses.description": "Step 時跳過指定的類別。你可以使用內建變數,如 '$JDK' 和 '$Libraries' 來跳過一組類別,或者添加一個特定的類別名表達式,如 java.*,*.Foo。", + "java.debugger.launch.skipClasses.skipJDK": "跳過系統預設的啟動路徑中的 JDK 類別,如 rt.jar、jrt-fs.jar。", + "java.debugger.launch.skipClasses.skipLibraries": "跳過應用程式庫中的類別,如 Maven、Gradle 相依性。", + "java.debugger.launch.skipClasses.skipClassLoader": "跳過類別載入器。", + "java.debugger.launch.skipClasses.skipClassPattern": "跳過指定的類別。僅支援全名,以及萬用字元,如 java.*,*.Foo。", + "java.debugger.launch.skipSynthetics.description": "Step 時跳過合成方法。", + "java.debugger.launch.skipStaticInitializers.description": "Step 時跳過靜態初始化方法。", + "java.debugger.launch.skipConstructors.description": "Step 時跳過建構函數。", + "java.debugger.attach.hostName.description": "遠端偵錯程序所在的主機名或 IP 地址。", + "java.debugger.attach.port.description": "遠端偵錯程序的偵錯埠。", + "java.debugger.attach.processPicker.description": "使用程序選取器選擇要附加的程序,或直接設定程序 ID。", + "java.debugger.attach.processId.description": "要附加到的本地程序的 ID。", + "java.debugger.attach.timeout.description": "重新連接前的超時值,以毫秒為單位(預設為 30000ms)。", + "java.debugger.attach.projectName.description": "偵錯器搜索類別的偏好專案。不同專案中可能存在重復的類別名。", + "java.debugger.snippet.launch.description": "啟動 Java 程式。", + "java.debugger.snippet.launchInExternalTerminal.description": "在外部終端中啟動 Java 程式。", + "java.debugger.snippet.launchCurrentFile.description": "啟動當前 Java 檔案中的程式。", + "java.debugger.snippet.launchWithArgumentsPrompt.description": "啟動 Java 程式時動態提示命令列參數。", + "java.debugger.snippet.attach.description": "附加到正在運行的 Java 程式。", + "java.debugger.snippet.attachProcess.description": "使用程序選擇器選擇要附加的 Java 程序。", + "java.debugger.snippet.attachRemote.description": "附加到遠端 Java 程式。", + "java.debugger.configuration.title": "Java 偵錯器", + "java.debugger.configuration.logLevel.description": "Java 偵錯器的記錄級別。", + "java.debugger.configuration.showHex.description": "在「變數」視圖中以十六進位格式顯示數值。", + "java.debugger.configuration.showStaticVariables.description": "在「變數」視圖中顯示靜態變數。", + "java.debugger.configuration.showQualifiedNames.description": "在「變數」視圖中顯示類別的全名。", + "java.debugger.configuration.showLogicalStructure.description": "在「變數」視圖中顯示 Collection 和 Map 類別的邏輯結構。", + "java.debugger.configuration.showToString.description": "在「變數」視圖中顯示所有覆寫過 'toString' 方法的類別的 'toString()' 值。", + "java.debugger.configuration.maxStringLength.description": "設定「變數」或「偵錯主控台」視圖中顯示的字元串最大長度,長度超過部分將被剪掉。如果值為0,則不執行修剪。", + "java.debugger.configuration.hotCodeReplace.description": "在偵錯期間重新載入已更改的 Java 類別。確保未停用 'java.autobuild.enabled'。", + "java.debugger.configuration.enableRunDebugCodeLens.description": "在 main 方法上啟用 CodeLens 標記。", + "java.debugger.configuration.forceBuildBeforeLaunch": "在啟動 Java 程式之前強制編譯整個工作空間。", + "java.debugger.configuration.console": "指定用於啟動 Java 程式的主控台。如果要為特定的偵錯會話自訂義主控台,請修改 launch.json 中的「console」設定。", + "java.debugger.configuration.exceptionBreakpoint.skipClasses": "當發生異常時,跳過指定的類別。你可以使用內建變數,如 '$JDK' 和 '$Libraries' 來跳過一組類別,或者添加一個特定的類別名表達式,如 java.*,*.Foo。", + "java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description": "一次 JDWP 請求中可以請求的變數或欄位的最大數量。該值越高,在展開變數視圖時,請求偵錯對象的頻率就越低。同時數量過大也會導致 JDWP 請求超時。", + "java.debugger.configuration.jdwp.requestTimeout.description": "偵錯器與目標 JVM 連線時 JDWP 請求的超時時間(ms)。", + "java.debugger.configuration.vmArgs.description": "啟動 Java 程式的預設 VM 參數。例如,使用 '-Xmx1G -ea' 將堆大小增加到 1GB 並啟用斷言。如果要為特定的偵錯會話定製 VM 參數,請修改launch.json 中的 'vmArgs' 設定。", + "java.debugger.configuration.silentNotification": "控制是否可以使用通知來回報進度。如果為真,則使用狀態欄來回報進度。", + "java.debugger.configuration.suspendAllThreads.description": "當命中斷點或因異常停止時暫停所有執行緒。僅對新的偵錯工作階段生效;在執行中的工作階段內變更不會生效。" +} \ No newline at end of file diff --git a/scripts/build/buildJdtlsExt.js b/scripts/build/buildJdtlsExt.js new file mode 100644 index 00000000..fb323b87 --- /dev/null +++ b/scripts/build/buildJdtlsExt.js @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +const cp = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const server_dir = path.resolve('../java-debug'); + +cp.execSync(mvnw() + ' clean package', { + cwd: server_dir, + stdio: [0, 1, 2] +}); +copy(path.join(server_dir, 'com.microsoft.java.debug.plugin/target'), path.resolve('server'), (file) => { + return /^com.microsoft.java.debug.*.jar$/.test(file); +}); + +function copy(sourceFolder, targetFolder, fileFilter) { + const jars = fs.readdirSync(sourceFolder).filter(file => fileFilter(file)); + if (!fs.existsSync(targetFolder)) { + fs.mkdirSync(targetFolder); + } + for (const jar of jars) { + fs.copyFileSync(path.join(sourceFolder, jar), path.join(targetFolder, path.basename(jar))); + } +} + +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/scripts/build/prepare-nightly-build.js b/scripts/build/prepare-nightly-build.js new file mode 100644 index 00000000..8dcbf3f2 --- /dev/null +++ b/scripts/build/prepare-nightly-build.js @@ -0,0 +1,25 @@ +const fs = require("fs"); + +const json = JSON.parse(fs.readFileSync("./package.json").toString()); +const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/); +const major = stableVersion[1]; +const minor = stableVersion[2]; + +function prependZero(number) { + if (number > 99) { + throw "Unexpected value to prepend with zero"; + } + return `${number < 10 ? "0" : ""}${number}`; +} + +const date = new Date(); +const month = date.getMonth() + 1; +const day = date.getDate(); +const hours = date.getHours(); +patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`; + +const insiderPackageJson = Object.assign(json, { + version: `${major}.${minor}.${patch}`, +}); + +fs.writeFileSync("./package.json", JSON.stringify(insiderPackageJson, null, 2)); diff --git a/src/JavaInlineValueProvider.ts b/src/JavaInlineValueProvider.ts new file mode 100644 index 00000000..87979c75 --- /dev/null +++ b/src/JavaInlineValueProvider.ts @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { debug, InlineValue, InlineValueContext, InlineValueEvaluatableExpression, InlineValuesProvider, InlineValueText, InlineValueVariableLookup, + Range, TextDocument } from "vscode"; +import { instrumentOperation, instrumentOperationStep, sendInfo } from "vscode-extension-telemetry-wrapper"; +import * as CodeConverter from "vscode-languageclient/lib/codeConverter"; +import * as ProtocolConverter from "vscode-languageclient/lib/protocolConverter"; +import { InlineKind, InlineVariable, resolveInlineVariables } from "./languageServerPlugin"; + +const protoConverter: ProtocolConverter.Converter = ProtocolConverter.createConverter(); +const codeConverter: CodeConverter.Converter = CodeConverter.createConverter(); + +export class JavaInlineValuesProvider implements InlineValuesProvider { + + public async provideInlineValues(document: TextDocument, viewPort: Range, context: InlineValueContext): Promise { + const provideInlineValuesOperation = instrumentOperation("provideInlineValues", async (operationId) => { + const resolveInlineVariablesStep = instrumentOperationStep(operationId, "resolveInlineVariables", async () => { + return (await resolveInlineVariables({ + uri: document.uri.toString(), + viewPort: codeConverter.asRange(viewPort), + stoppedLocation: codeConverter.asRange(context.stoppedLocation), + })); + }); + const variables: InlineVariable[] = await resolveInlineVariablesStep(); + + const resolveInlineValuesStep = instrumentOperationStep(operationId, "resolveInlineValues", async () => { + if (!variables || !variables.length) { + sendInfo(operationId, { + inlineVariableCount: 0, + }); + return []; + } + + const unresolvedVariables: any[] = variables.filter((variable) => variable.kind === InlineKind.Evaluation).map((variable) => { + return { + expression: variable.expression || variable.name, + declaringClass: variable.declaringClass, + }; + }); + sendInfo(operationId, { + inlineVariableCount: variables.length, + inlineVariableLookupCount: variables.length - unresolvedVariables.length, + inlineVariableEvaluationCount: unresolvedVariables.length, + }); + + let resolvedVariables: any; + if (unresolvedVariables.length && debug.activeDebugSession) { + const response = await debug.activeDebugSession.customRequest("inlineValues", { + frameId: context.frameId, + variables: unresolvedVariables, + }); + resolvedVariables = response?.variables; + } + + const result: InlineValue[] = []; + let next = 0; + for (const variable of variables) { + if (variable.kind === InlineKind.VariableLookup) { + result.push(new InlineValueVariableLookup(protoConverter.asRange(variable.range), variable.name, true)); + } else if (resolvedVariables && resolvedVariables.length > next) { + const resolvedValue = resolvedVariables[next++]; + if (resolvedValue) { + result.push(new InlineValueText(protoConverter.asRange(variable.range), `${variable.name} = ${resolvedValue.value}`)); + } else { + result.push(new InlineValueEvaluatableExpression(protoConverter.asRange(variable.range), variable.name)); + } + } else { + result.push(new InlineValueEvaluatableExpression(protoConverter.asRange(variable.range), variable.name)); + } + } + + return result; + }); + return resolveInlineValuesStep(); + }); + + return provideInlineValuesOperation(); + } + +} diff --git a/src/anchor.ts b/src/anchor.ts new file mode 100644 index 00000000..22e2d195 --- /dev/null +++ b/src/anchor.ts @@ -0,0 +1,10 @@ + +export const LS_FAILS_TO_START = "java-language-support-extension-fails-to-start"; +export const FAILED_TO_RESOLVE_CLASSPATH = "failed-to-resolve-classpath"; +export const REQUEST_TYPE_NOT_SUPPORTED = "request-type-xyz-is-not-supported-only-launch-and-attach-are-supported"; +export const FAILED_TO_COMPLETE_HCR = "failed-to-complete-hot-code-replace"; +export const ATTACH_CONFIG_ERROR = "please-specify-the-host-name-and-the-port-of-the-remote-debuggee-in-the-launchjson"; +export const EVALUATE_ON_RUNNING_THREAD = "failed-to-evaluate-reason-cannot-evaluate-because-the-thread-is-resumed"; +export const CANNOT_FIND_MAIN_CLASS = "cannot-find-a-class-with-the-main-method"; +export const BUILD_FAILED = "build-failed-do-you-want-to-continue"; +export const UNSUPPORTED_CLASS_VERSION_ERROR = "program-throws-unsupportedclassversionerror"; diff --git a/src/breakpointCommands.ts b/src/breakpointCommands.ts new file mode 100644 index 00000000..84ee9e22 --- /dev/null +++ b/src/breakpointCommands.ts @@ -0,0 +1,124 @@ +import * as vscode from "vscode"; + +export function registerBreakpointCommands(context: vscode.ExtensionContext): void { + context.subscriptions.push(vscode.commands.registerCommand('java.debug.breakpoints.exceptionTypes', exceptionTypes)); +} + +async function exceptionTypes() { + const config = vscode.workspace.getConfiguration('java.debug.settings.exceptionBreakpoint'); + let currentTypes = config.get('exceptionTypes', []); + const addExceptionTypeItem: vscode.QuickPickItem = { + label: '$(add) Add Exception Types...', + alwaysShow: true, + }; + const removeExceptionTypeItem: any = (type: string): any => ({ + label: type, + buttons: [{ + iconPath: new vscode.ThemeIcon('close'), + tooltip: 'Remove this Exception Type' + }] + }); + + // Step 1: Show Breakpoint Exception Types + const pickStep = async (state: any) => { + return new Promise((resolve) => { + const items: vscode.QuickPickItem[] = [ + addExceptionTypeItem, + ...currentTypes.map(type => removeExceptionTypeItem(type)) + ]; + const quickPick = vscode.window.createQuickPick(); + quickPick.items = items; + quickPick.title = 'Breakpoint Exception Types'; + quickPick.canSelectMany = false; + quickPick.matchOnDescription = false; + quickPick.matchOnDetail = false; + + quickPick.onDidAccept(() => { + const selected = quickPick.selectedItems[0]; + if (selected.label.includes('Add Exception Types')) { + quickPick.hide(); + // go to next step + resolve(state); + } + }); + + quickPick.onDidTriggerItemButton(async (e) => { + const typeToRemove = e.item.label; + currentTypes = currentTypes.filter(type => type !== typeToRemove); + await config.update('exceptionTypes', currentTypes, vscode.ConfigurationTarget.Global); + quickPick.items = [ + addExceptionTypeItem, + ...currentTypes.map(type => removeExceptionTypeItem(type)) + ]; + }); + quickPick.onDidHide(() => { + quickPick.dispose(); + }); + quickPick.show(); + }); + }; + + // Step 2: Add Exception Type(s) + const inputStep = async (state: any) => { + return new Promise((resolve, reject) => { + const input = vscode.window.createInputBox(); + input.title = 'Add Breakpoint Exception Type(s)'; + input.placeholder = 'Enter exception type(s) (comma or space separated). "java.lang.NullPointerException" e.g.'; + input.prompt = 'Input exception types'; + input.buttons = [vscode.QuickInputButtons.Back]; + input.onDidAccept(async () => { + const exceptionType = input.value; + if (exceptionType) { + const types = exceptionType.split(/[,\s]+/).map(type => type.trim()).filter(type => type.length > 0); + let updated = false; + for (const type of types) { + if (!currentTypes.includes(type)) { + currentTypes.push(type); + updated = true; + } + } + if (updated) { + await config.update('exceptionTypes', currentTypes, vscode.ConfigurationTarget.Global); + } + } + input.hide(); + // go back to pick step + resolve(state); + }); + input.onDidTriggerButton((btn) => { + if (btn === vscode.QuickInputButtons.Back) { + input.hide(); + reject({ stepBack: true }); + } + }); + input.onDidHide(() => { + input.dispose(); + }); + input.show(); + }); + }; + + while (true) { + await multiStepInput([pickStep, inputStep], {}); + } +} + +async function multiStepInput(steps: ((input: T) => Promise)[], initial: T): Promise { + let state = initial; + let currentStep = 0; + while (currentStep < steps.length) { + try { + state = await steps[currentStep](state); + currentStep++; + } catch (err) { + if (err?.stepBack) { + if (currentStep > 0) { + currentStep--; + } + } else { + throw err; + } + } + } + return state; +} diff --git a/src/build.ts b/src/build.ts new file mode 100644 index 00000000..ebf38e7e --- /dev/null +++ b/src/build.ts @@ -0,0 +1,182 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. +import * as vscode from "vscode"; +import { instrumentOperation, sendInfo, sendOperationError, setErrorCode } from "vscode-extension-telemetry-wrapper"; + +import * as anchor from "./anchor"; +import * as commands from "./commands"; +import * as lsPlugin from "./languageServerPlugin"; +import { IProgressReporter } from "./progressAPI"; +import * as utility from "./utility"; + +const JAVA_DEBUG_CONFIGURATION = "java.debug.settings"; +const ON_BUILD_FAILURE_PROCEED = "onBuildFailureProceed"; +const CANCELLED_CODE = -32800; + +enum CompileWorkspaceStatus { + FAILED = 0, + SUCCEED = 1, + WITHERROR = 2, + CANCELLED = 3, + GRADLE_BS_COMPILATION_ERROR = 100, +} + +export interface BuildParams { + readonly mainClass: string; + readonly projectName?: string; + readonly filePath?: string; + readonly isFullBuild: boolean; +} + +export async function buildWorkspace(params: BuildParams, progressReporter: IProgressReporter): Promise { + const startAt = new Date().getTime(); + const buildResult = await instrumentOperation("build", async (operationId: string) => { + let status; + try { + status = await commands.executeJavaLanguageServerCommand(commands.JAVA_BUILD_WORKSPACE, + JSON.stringify(params), + progressReporter.getCancellationToken()); + } catch (err) { + status = (err && err.code === CANCELLED_CODE) ? CompileWorkspaceStatus.CANCELLED : err; + } + + return { + status, + operationId, + }; + })(); + + if (progressReporter.isCancelled() || buildResult.status === CompileWorkspaceStatus.CANCELLED) { + return false; + } else if (buildResult.status === CompileWorkspaceStatus.SUCCEED) { + return true; + } else { + const elapsed = new Date().getTime() - startAt; + const humanVisibleDelay = elapsed < 150 ? 150 : 0; + await new Promise(resolve => { + setTimeout(() => { // set a timeout so user still can see a compiling message. + resolve(null); + }, humanVisibleDelay); + }); + return handleBuildFailure(buildResult.operationId, buildResult.status, progressReporter); + } +} + +async function handleBuildFailure(operationId: string, err: any, progressReporter: IProgressReporter): Promise { + const configuration = vscode.workspace.getConfiguration(JAVA_DEBUG_CONFIGURATION); + const onBuildFailureProceed = configuration.get(ON_BUILD_FAILURE_PROCEED); + + if (err instanceof utility.JavaExtensionNotEnabledError) { + utility.guideToInstallJavaExtension(); + return false; + } + + const error: Error = new utility.UserError({ + message: "Build failed", + }); + setErrorCode(error, Number(err)); + sendOperationError(operationId, "build", error); + const errorDiagnostics = traceErrorTypes(operationId); + if (!onBuildFailureProceed && err) { + // build failure information is not displayed in PROBLEMS panel for build server project. + if (errorDiagnostics && err !== CompileWorkspaceStatus.GRADLE_BS_COMPILATION_ERROR) { + vscode.commands.executeCommand("workbench.actions.view.problems"); + } + + progressReporter.hide(true); + const ans = await vscode.window.showErrorMessage("Build failed, do you want to continue?", "Continue", "Always Continue", "Fix..."); + sendInfo(operationId, { + operationName: "build", + choiceForBuildError: ans || "esc", + }); + if (ans === "Continue") { + return true; + } else if (ans === "Always Continue") { + const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + debugSettings?.update("onBuildFailureProceed", true); + return true; + } else if (ans === "Fix...") { + showFixSuggestions(operationId); + } + + return false; + } + + return true; +} + +function traceErrorTypes(operationId: string): boolean { + const problems = vscode.languages.getDiagnostics() || []; + const errorTypes: {[key: string]: number} = {}; + let errorCount = 0; + for (const problem of problems) { + for (const diagnostic of problem[1]) { + if (diagnostic.severity === vscode.DiagnosticSeverity.Error && diagnostic.source === "Java") { + const errorCode = typeof diagnostic.code === 'object' ? String(diagnostic.code.value) : String(diagnostic.code); + errorTypes[errorCode] = (errorTypes[errorCode] || 0) + 1; + errorCount++; + } + } + } + + if (errorCount) { + sendInfo(operationId, { + buildErrorTypes: JSON.stringify(errorTypes), + buildErrorCount: errorCount, + }); + } + + return errorCount > 0; +} + +async function showFixSuggestions(operationId: string) { + let buildFiles: string[] = []; + try { + buildFiles = await lsPlugin.resolveBuildFiles(); + } catch (error) { + // do nothing + } + + const pickitems = []; + pickitems.push({ + label: "Clean workspace cache", + detail: "Clean the stale workspace and reload the window", + }); + if (buildFiles.length) { + pickitems.push({ + label: "Update project configuration", + detail: "Force the language server to update the project configuration/classpath", + }); + } + pickitems.push({ + label: "Open log file", + detail: "Open log file to view more details for the build errors", + }); + pickitems.push({ + label: "Troubleshooting guide", + detail: "Find more detail about the troubleshooting steps", + }); + + const ans = await vscode.window.showQuickPick(pickitems, { + placeHolder: "Please fix the errors in PROBLEMS first, then try the fix suggestions below.", + }); + sendInfo(operationId, { + operationName: "build", + choiceForBuildFix: ans ? ans.label : "esc", + }); + if (!ans) { + return; + } + + if (ans.label === "Clean workspace cache") { + vscode.commands.executeCommand("java.clean.workspace"); + } else if (ans.label === "Update project configuration") { + for (const buildFile of buildFiles) { + await vscode.commands.executeCommand("java.projectConfiguration.update", vscode.Uri.parse(buildFile)); + } + } else if (ans.label === "Open log file") { + vscode.commands.executeCommand("java.open.serverLog"); + } else if (ans.label === "Troubleshooting guide") { + utility.openTroubleshootingPage("Build failed", anchor.BUILD_FAILED); + } +} diff --git a/src/classFilter.ts b/src/classFilter.ts new file mode 100644 index 00000000..7ddf4af4 --- /dev/null +++ b/src/classFilter.ts @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { resolveClassFilters } from "./languageServerPlugin"; + +export async function populateStepFilters(config: vscode.DebugConfiguration) { + if (!config.stepFilters) { + return; + } + + const skipClasses = await substituteFilterVariables(config.stepFilters.skipClasses); + // Migrate classNameFilters to skipClasses. + if (Array.isArray(config.stepFilters.classNameFilters)) { + mergeResult(config.stepFilters.classNameFilters, skipClasses); + } + config.stepFilters.classNameFilters = undefined; + config.stepFilters.skipClasses = skipClasses; +} + +export async function substituteFilterVariables(skipClasses: string[]): Promise { + if (!skipClasses) { + return []; + } + + try { + // Preprocess skipClasses configurations. + if (Array.isArray(skipClasses)) { + const hasReservedName = skipClasses.some((filter) => filter === "$JDK" || filter === "$Libraries"); + return hasReservedName ? await resolveClassFilters(skipClasses) : skipClasses; + } else { + // tslint:disable-next-line:no-console + console.error("Invalid type for skipClasses config:" + skipClasses); + } + } catch (e) { + // tslint:disable-next-line:no-console + console.error(e); + } + + return []; +} + +function mergeResult(newItems: any[], result: string[]) { + newItems.forEach((item) => { + if (result.indexOf(item) < 0) { + result.push(String(item)); + } + }); +} diff --git a/src/commands.ts b/src/commands.ts index 7d8e4eb8..2419ec8f 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +import * as vscode from "vscode"; +import * as utility from "./utility"; + export const VSCODE_STARTDEBUG = "vscode.startDebug"; export const VSCODE_ADD_DEBUGCONFIGURATION = "debug.addConfiguration"; @@ -9,10 +12,52 @@ export const JAVA_START_DEBUGSESSION = "vscode.java.startDebugSession"; export const JAVA_RESOLVE_CLASSPATH = "vscode.java.resolveClasspath"; +export const JAVA_RESOLVE_MAINCLASS = "vscode.java.resolveMainClass"; + +export const JAVA_VALIDATE_LAUNCHCONFIG = "vscode.java.validateLaunchConfig"; + export const JAVA_BUILD_WORKSPACE = "vscode.java.buildWorkspace"; export const JAVA_EXECUTE_WORKSPACE_COMMAND = "java.execute.workspaceCommand"; export const JAVA_FETCH_USAGE_DATA = "vscode.java.fetchUsageData"; -export const JAVA_CONFIG_LOG_LEVEL = "vscode.java.configLogLevel"; +export const JAVA_UPDATE_DEBUG_SETTINGS = "vscode.java.updateDebugSettings"; + +export const JAVA_RESOLVE_MAINMETHOD = "vscode.java.resolveMainMethod"; + +export const JAVA_INFER_LAUNCH_COMMAND_LENGTH = "vscode.java.inferLaunchCommandLength"; + +export const JAVA_CHECK_PROJECT_SETTINGS = "vscode.java.checkProjectSettings"; + +export const JAVA_RESOLVE_ELEMENT_AT_SELECTION = "vscode.java.resolveElementAtSelection"; + +export const JAVA_RESOLVE_BUILD_FILES = "vscode.java.resolveBuildFiles"; + +export const JAVA_IS_ON_CLASSPATH = "vscode.java.isOnClasspath"; + +export const JAVA_RESOLVE_JAVAEXECUTABLE = "vscode.java.resolveJavaExecutable"; + +export const JAVA_FETCH_PLATFORM_SETTINGS = "vscode.java.fetchPlatformSettings"; + +export const JAVA_RESOLVE_CLASSFILTERS = "vscode.java.resolveClassFilters"; + +export const JAVA_RESOLVE_SOURCE_URI = "vscode.java.resolveSourceUri"; + +export const JAVA_RESOLVE_INLINE_VARIABLES = "vscode.java.resolveInlineVariables"; + +export function executeJavaLanguageServerCommand(...rest: any[]) { + return executeJavaExtensionCommand(JAVA_EXECUTE_WORKSPACE_COMMAND, ...rest); +} + +export async function executeJavaExtensionCommand(commandName: string, ...rest: any[]) { + // TODO: need to handle error and trace telemetry + const javaExtension = utility.getJavaExtension(); + if (!javaExtension) { + throw new utility.JavaExtensionNotEnabledError(`Cannot execute command ${commandName}, VS Code Java Extension is not enabled.`); + } + if (!javaExtension.isActive) { + await javaExtension.activate(); + } + return vscode.commands.executeCommand(commandName, ...rest); +} diff --git a/src/configurationProvider.ts b/src/configurationProvider.ts new file mode 100644 index 00000000..92db8e11 --- /dev/null +++ b/src/configurationProvider.ts @@ -0,0 +1,865 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. +import * as fs from "fs"; +import * as _ from "lodash"; +import * as os from "os"; +import * as path from "path"; +import * as vscode from "vscode"; + +import * as dotenv from 'dotenv'; + +import { instrumentOperation, sendError, sendInfo, setUserError } from "vscode-extension-telemetry-wrapper"; +import * as anchor from "./anchor"; +import { buildWorkspace } from "./build"; +import { populateStepFilters, substituteFilterVariables } from "./classFilter"; +import * as commands from "./commands"; +import { ClasspathVariable } from "./constants"; +import { Type } from "./javaLogger"; +import * as lsPlugin from "./languageServerPlugin"; +import { addMoreHelpfulVMArgs, getJavaVersion, getShortenApproachForCLI, validateRuntimeCompatibility } from "./launchCommand"; +import { mainClassPicker } from "./mainClassPicker"; +import { resolveJavaProcess } from "./processPicker"; +import { IProgressReporter } from "./progressAPI"; +import { progressProvider } from "./progressImpl"; +import * as utility from "./utility"; + +const platformNameMappings: { [key: string]: string } = { + win32: "windows", + linux: "linux", + darwin: "osx", +}; +const platformName = platformNameMappings[process.platform]; + +export let lastUsedLaunchConfig: vscode.DebugConfiguration | undefined; + +export class JavaDebugConfigurationProvider implements vscode.DebugConfigurationProvider { + private isUserSettingsDirty: boolean = true; + constructor() { + const packageJson: {[key: string]: any} = require("../package.json"); + const debugConfigNames = Object.keys(packageJson?.contributes?.configuration?.properties || {}); + vscode.workspace.onDidChangeConfiguration((event) => { + if (event.affectsConfiguration("java.debug")) { + for (const key of debugConfigNames) { + if (event.affectsConfiguration(key)) { + sendInfo("", { + operationName: "changeJavaDebugSettings", + configName: key, + }); + } + } + + if (vscode.debug.activeDebugSession) { + this.isUserSettingsDirty = false; + return updateDebugSettings(event); + } else { + this.isUserSettingsDirty = true; + } + } + return undefined; + }); + } + + // Returns an initial debug configurations based on contextual information. + public provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): + vscode.ProviderResult { + const provideDebugConfigurationsHandler = instrumentOperation("provideDebugConfigurations", (_operationId: string) => { + return >this.provideDebugConfigurationsAsync(folder, token); + }); + return provideDebugConfigurationsHandler(); + } + + // Try to add all missing attributes to the debug configuration being launched. + public resolveDebugConfiguration(_folder: vscode.WorkspaceFolder | undefined, + config: vscode.DebugConfiguration, _token?: vscode.CancellationToken): + vscode.ProviderResult { + // If no debug configuration is provided, then generate one in memory. + if (this.isEmptyConfig(config)) { + config.type = "java"; + config.name = "Java Debug"; + config.request = "launch"; + config.__origin = "internal"; + } + + return config; + } + + // Try to add all missing attributes to the debug configuration being launched. + public resolveDebugConfigurationWithSubstitutedVariables( + folder: vscode.WorkspaceFolder | undefined, + config: vscode.DebugConfiguration, + token?: vscode.CancellationToken): vscode.ProviderResult { + const resolveDebugConfigurationHandler = instrumentOperation("resolveDebugConfiguration", (_operationId: string) => { + try { + // See https://github.com/microsoft/vscode-java-debug/issues/778 + // Merge the platform specific properties to the global config to simplify the subsequent resolving logic. + this.mergePlatformProperties(config, folder); + return this.resolveAndValidateDebugConfiguration(folder, config, token); + } catch (ex) { + utility.showErrorMessage({ + type: Type.EXCEPTION, + message: String((ex && ex.message) || ex), + }); + return undefined; + } + }); + return resolveDebugConfigurationHandler(); + } + + private provideDebugConfigurationsAsync(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken) { + return new Promise(async (resolve, _reject) => { + const progressReporter = progressProvider.createProgressReporter("Create launch.json", vscode.ProgressLocation.Window); + progressReporter.observe(token); + const defaultLaunchConfig = { + type: "java", + name: "Current File", + request: "launch", + // tslint:disable-next-line + mainClass: "${file}", + }; + try { + const isOnStandardMode = await utility.waitForStandardMode(progressReporter); + if (!isOnStandardMode) { + resolve([defaultLaunchConfig]); + return; + } + + if (progressReporter.isCancelled()) { + resolve([defaultLaunchConfig]); + return; + } + progressReporter.report("Generating Java configuration..."); + const mainClasses = await lsPlugin.resolveMainClass(folder ? folder.uri : undefined); + const cache = {}; + const launchConfigs = mainClasses.map((item) => { + return { + ...defaultLaunchConfig, + name: this.constructLaunchConfigName(item.mainClass, cache), + mainClass: item.mainClass, + projectName: item.projectName, + }; + }); + if (progressReporter.isCancelled()) { + resolve([defaultLaunchConfig]); + return; + } + resolve([defaultLaunchConfig, ...launchConfigs]); + } catch (ex) { + if (ex instanceof utility.JavaExtensionNotEnabledError) { + utility.guideToInstallJavaExtension(); + } else { + // tslint:disable-next-line + console.error(ex); + } + + resolve([defaultLaunchConfig]); + } finally { + progressReporter.done(); + } + }); + } + + private mergePlatformProperties(config: vscode.DebugConfiguration, _folder?: vscode.WorkspaceFolder) { + if (config && platformName && config[platformName]) { + try { + for (const key of Object.keys(config[platformName])) { + config[key] = config[platformName][key]; + } + config[platformName] = undefined; + } catch { + // do nothing + } + } + } + + private constructLaunchConfigName(mainClass: string, cache: { [key: string]: any }) { + const name = `${mainClass.substr(mainClass.lastIndexOf(".") + 1)}`; + if (cache[name] === undefined) { + cache[name] = 0; + return name; + } else { + cache[name] += 1; + return `${name}(${cache[name]})`; + } + } + + private mergeEnvFile(config: vscode.DebugConfiguration) { + const baseEnv = config.env || {}; + let result = baseEnv; + if (config.envFile) { + try { + if (typeof config.envFile === 'string') { + result = { + ...result, + ...readEnvFile(config.envFile) + }; + } + if (Array.isArray(config.envFile)) { + config.envFile.forEach((f) => { + result = { + ...result, + ...readEnvFile(f) + }; + }); + } + } catch (e) { + throw new utility.UserError({ + message: "Cannot load environment file.", + type: Type.USAGEERROR, + }); + } + } + config.env = result; + } + + private async resolveAndValidateDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, + token?: vscode.CancellationToken) { + let configCopy: vscode.DebugConfiguration | undefined; + const isConfigFromInternal = config.__origin === "internal" /** in-memory configuration from debugger */ + || config.__configurationTarget /** configuration from launch.json */; + if (config.request === "launch" && isConfigFromInternal) { + configCopy = _.cloneDeep(config); + delete configCopy.__progressId; + delete configCopy.noDebug; + } + + let progressReporter = progressProvider.getProgressReporter(config.__progressId); + if (!progressReporter && config.__progressId) { + return undefined; + } else if (!progressReporter) { + progressReporter = progressProvider.createProgressReporter(utility.launchJobName(config.name, config.noDebug)); + } + + progressReporter.observe(token); + if (progressReporter.isCancelled()) { + return undefined; + } + + try { + const isOnStandardMode = await utility.waitForStandardMode(progressReporter); + if (!isOnStandardMode || progressReporter.isCancelled()) { + return undefined; + } + + if (this.isUserSettingsDirty) { + this.isUserSettingsDirty = false; + await updateDebugSettings(); + } + + // If no debug configuration is provided, then generate one in memory. + if (this.isEmptyConfig(config)) { + config.type = "java"; + config.name = "Java Debug"; + config.request = "launch"; + } + + if (config.request === "launch") { + const mainClassOption = await this.resolveAndValidateMainClass(folder && folder.uri, config, progressReporter); + if (!mainClassOption || !mainClassOption.mainClass) { // Exit silently if the user cancels the prompt fix by ESC. + // Exit the debug session. + return undefined; + } + + config.mainClass = mainClassOption.mainClass; + config.projectName = mainClassOption.projectName; + if (config.__workspaceFolder && config.__workspaceFolder !== folder) { + folder = config.__workspaceFolder; + } + // Update the job name if the main class is changed during the resolving of configuration provider. + if (configCopy && configCopy.mainClass !== config.mainClass) { + config.name = config.mainClass.substr(config.mainClass.lastIndexOf(".") + 1); + progressReporter.setJobName(utility.launchJobName(config.name, config.noDebug)); + } + if (progressReporter.isCancelled()) { + return undefined; + } + + if (needsBuildWorkspace()) { + progressReporter.report("Compiling..."); + const proceed = await buildWorkspace({ + mainClass: mainClassOption.mainClass, + projectName: mainClassOption.projectName, + isFullBuild: false, + }, progressReporter); + if (!proceed) { + return undefined; + } + } + + if (progressReporter.isCancelled()) { + return undefined; + } + + progressReporter.report("Resolving launch configuration..."); + this.mergeEnvFile(config); + // If the user doesn't specify 'vmArgs' in launch.json, use the global setting to get the default vmArgs. + if (config.vmArgs === undefined) { + const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + config.vmArgs = debugSettings.vmArgs; + } + // If the user doesn't specify 'console' in launch.json, use the global setting to get the launch console. + if (!config.console) { + const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + config.console = debugSettings.console; + } + // If the console is integratedTerminal, don't auto switch the focus to DEBUG CONSOLE. + if (config.console === "integratedTerminal" && !config.internalConsoleOptions) { + config.internalConsoleOptions = "neverOpen"; + } + + if (progressReporter.isCancelled()) { + return undefined; + } + + if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) { + const result = (await lsPlugin.resolveClasspath(config.mainClass, config.projectName)); + config.modulePaths = result[0]; + config.classPaths = result[1]; + } else { + config.modulePaths = await this.resolvePath(folder, config.modulePaths, config.mainClass, + config.projectName, true /*isModulePath*/); + config.classPaths = await this.resolvePath(folder, config.classPaths, config.mainClass, + config.projectName, false /*isModulePath*/); + } + if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) { + throw new utility.UserError({ + message: "Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.", + type: Type.USAGEERROR, + }); + } + + if (_.isEmpty(config.javaExec)) { + config.javaExec = await lsPlugin.resolveJavaExecutable(config.mainClass, config.projectName); + } else { + if (!fs.existsSync(config.javaExec)) { + throw new utility.UserError({ + message: "Java executable file path cannot be accessed, please specify a valid path in the launch.json.", + type: Type.USAGEERROR, + }); + } + } + + // Add the default launch options to the config. + config.cwd = config.cwd || _.get(folder, "uri.fsPath"); + if (Array.isArray(config.args)) { + config.args = this.concatArgs(config.args); + } + + if (Array.isArray(config.vmArgs)) { + config.vmArgs = this.concatArgs(config.vmArgs); + } + + if (progressReporter.isCancelled()) { + return undefined; + } + // Populate the class filters to the debug configuration. + await populateStepFilters(config); + + const targetJavaVersion: number = await getJavaVersion(config.javaExec); + // Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag. + if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) { + config.vmArgs = (config.vmArgs || "") + " --enable-preview"; + validateRuntimeCompatibility(targetJavaVersion); + } + + // Add more helpful vmArgs. + await addMoreHelpfulVMArgs(config, targetJavaVersion); + + if (!config.shortenCommandLine || config.shortenCommandLine === "auto") { + config.shortenCommandLine = await getShortenApproachForCLI(config, targetJavaVersion); + } + + // VS Code internal console uses UTF-8 to display output by default. + if (config.console === "internalConsole" && !config.encoding) { + config.encoding = "UTF-8"; + } + } else if (config.request === "attach") { + if (config.hostName && config.port && Number.isInteger(Number(config.port))) { + config.port = Number(config.port); + config.processId = undefined; + // Continue if the hostName and port are configured. + } else if (config.processId !== undefined) { + // tslint:disable-next-line + if (config.processId === "${command:PickJavaProcess}") { + return undefined; + } + + const pid: number = Number(config.processId); + if (Number.isNaN(pid)) { + vscode.window.showErrorMessage(`The processId config '${config.processId}' is not a valid process id.`); + return undefined; + } + + const javaProcess = await resolveJavaProcess(pid); + if (!javaProcess) { + vscode.window.showErrorMessage(`Attach to process: pid '${config.processId}' is not a debuggable Java process. ` + + `Please make sure the process has turned on debug mode using vmArgs like ` + + `'-agentlib:jdwp=transport=dt_socket,server=y,address=5005.'`); + return undefined; + } + + config.processId = undefined; + config.hostName = javaProcess.hostName; + config.port = javaProcess.debugPort; + } else { + throw new utility.UserError({ + message: "Please specify the hostName/port directly, or provide the processId of the remote debuggee in the launch.json.", + type: Type.USAGEERROR, + anchor: anchor.ATTACH_CONFIG_ERROR, + }); + } + + // Populate the class filters to the debug configuration. + await populateStepFilters(config); + } else { + throw new utility.UserError({ + message: `Request type "${config.request}" is not supported. Only "launch" and "attach" are supported.`, + type: Type.USAGEERROR, + anchor: anchor.REQUEST_TYPE_NOT_SUPPORTED, + }); + } + + if (token?.isCancellationRequested || progressReporter.isCancelled()) { + return undefined; + } + + delete config.__progressId; + return config; + } catch (ex) { + if (ex instanceof utility.JavaExtensionNotEnabledError) { + utility.guideToInstallJavaExtension(); + return undefined; + } + if (ex instanceof utility.UserError) { + utility.showErrorMessageWithTroubleshooting(ex.context); + return undefined; + } + + utility.showErrorMessageWithTroubleshooting(utility.convertErrorToMessage(ex)); + return undefined; + } finally { + if (configCopy && config.mainClass) { + configCopy.name = config.name; + configCopy.mainClass = config.mainClass; + configCopy.projectName = config.projectName; + configCopy.__workspaceFolder = folder; + lastUsedLaunchConfig = configCopy; + } + + progressReporter.done(); + } + } + + private async resolvePath(folder: vscode.WorkspaceFolder | undefined, pathArray: string[], mainClass: string, + projectName: string, isModulePath: boolean): Promise { + if (_.isEmpty(pathArray)) { + return []; + } + + const pathVariables: string[] = [ClasspathVariable.Auto, ClasspathVariable.Runtime, ClasspathVariable.Test]; + const containedVariables: string[] = pathArray.filter((cp: string) => pathVariables.includes(cp)); + if (_.isEmpty(containedVariables)) { + return this.filterExcluded(folder, pathArray); + } + + const scope: string | undefined = this.mergeScope(containedVariables); + const response: any[] = await lsPlugin.resolveClasspath(mainClass, projectName, scope); + const resolvedPaths: string[] = isModulePath ? response?.[0] : response?.[1]; + if (!resolvedPaths) { + // tslint:disable-next-line:no-console + console.log("The Java Language Server failed to resolve the classpaths/modulepaths"); + } + const paths: string[] = []; + let replaced: boolean = false; + for (const p of pathArray) { + for (const splitPath of p.split(process.platform === 'win32' ? ';' : ':')) { + if (pathVariables.includes(splitPath)) { + if (!replaced) { + paths.push(...resolvedPaths); + replaced = true; + } + continue; + } + paths.push(splitPath); + } + } + return this.filterExcluded(folder, paths); + } + + private async filterExcluded(folder: vscode.WorkspaceFolder | undefined, paths: string[]): Promise { + const result: string[] = []; + const excludes: Map = new Map(); + for (const p of paths) { + if (p.startsWith("!")) { + let exclude = p.substr(1); + if (!path.isAbsolute(exclude)) { + exclude = path.join(folder?.uri.fsPath || "", exclude); + } + // use Uri to normalize the fs path + excludes.set(vscode.Uri.file(exclude).fsPath, this.isFilePath(exclude)); + continue; + } + + result.push(vscode.Uri.file(p).fsPath); + } + + return result.filter((r) => { + for (const [excludedPath, isFile] of excludes.entries()) { + if (isFile && r === excludedPath) { + return false; + } + + if (!isFile && r.startsWith(excludedPath)) { + return false; + } + } + + return true; + }); + } + + private mergeScope(scopes: string[]): string | undefined { + if (scopes.includes(ClasspathVariable.Test)) { + return "test"; + } + + if (scopes.includes(ClasspathVariable.Auto)) { + return undefined; + } + + if (scopes.includes(ClasspathVariable.Runtime)) { + return "runtime"; + } + + return undefined; + } + + /** + * Converts an array of arguments to a string as the args and vmArgs. + */ + private concatArgs(args: any[]): string { + return _.join(_.map(args, (arg: any): string => { + const str = String(arg); + // if it has quotes or spaces, use double quotes to wrap it + if (/["\s]/.test(str)) { + return "\"" + str.replace(/(["\\])/g, "\\$1") + "\""; + } + return str; + + // if it has only single quotes + }), " "); + } + + /** + * When VS Code cannot find any available DebugConfiguration, it passes a { noDebug?: boolean } to resolve. + * This function judges whether a DebugConfiguration is empty by filtering out the field "noDebug". + */ + private isEmptyConfig(config: vscode.DebugConfiguration): boolean { + return Object.keys(config).filter((key: string) => key !== "noDebug").length === 0; + } + + private async resolveAndValidateMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration, + progressReporter: IProgressReporter): Promise { + // Validate it if the mainClass is already set in launch configuration. + if (config.mainClass && !this.isFilePath(config.mainClass)) { + progressReporter.report("Resolving main class..."); + const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths); + const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder); + if (progressReporter.isCancelled()) { + return undefined; + } else if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) { + return this.fixMainClass(folder, config, validationResponse, progressReporter); + } + + return { + mainClass: config.mainClass, + projectName: config.projectName, + }; + } + + return this.resolveMainClass(config, progressReporter); + } + + private async resolveMainClass(config: vscode.DebugConfiguration, progressReporter: IProgressReporter): + Promise { + if (config.projectName) { + progressReporter.report("Resolving main class..."); + if (this.isFilePath(config.mainClass)) { + const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(config.mainClass)); + if (progressReporter.isCancelled()) { + return undefined; + } else if (mainEntries.length) { + if (!mainClassPicker.isAutoPicked(mainEntries)) { + progressReporter.hide(true); + } + return mainClassPicker.showQuickPick(mainEntries, "Please select a main class you want to run."); + } + } + + return this.promptMainClassUnderProject(config.projectName, progressReporter, "Please select a main class you wan to run"); + } + + // Try to resolve main class from current file + const currentFile = config.mainClass || vscode.window.activeTextEditor?.document.uri.fsPath; + if (currentFile) { + const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile)); + if (progressReporter.isCancelled()) { + return undefined; + } else if (mainEntries.length) { + if (!mainClassPicker.isAutoPicked(mainEntries)) { + progressReporter.hide(true); + } + return mainClassPicker.showQuickPick(mainEntries, "Please select a main class you want to run."); + } + } + + // If current file is not executable, run previously used launch config. + if (lastUsedLaunchConfig) { + Object.assign(config, lastUsedLaunchConfig); + progressReporter.setJobName(utility.launchJobName(config.name, config.noDebug)); + progressReporter.report("Resolving main class..."); + return { + mainClass: config.mainClass, + projectName: config.projectName, + }; + } + + progressReporter.report("Resolving main class..."); + const hintMessage = currentFile ? + `The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` : + "Please select a main class you want to run."; + return this.promptMainClassUnderPath(undefined, progressReporter, hintMessage); + } + + private isFilePath(filePath: string): boolean { + if (!filePath) { + return false; + } + + try { + return fs.lstatSync(filePath).isFile(); + } catch (error) { + // do nothing + return false; + } + } + + private getValidationErrorMessage(error: lsPlugin.IValidationResult): string { + switch (error.kind) { + case lsPlugin.CONFIGERROR_INVALID_CLASS_NAME: + return "ConfigError: mainClass was configured with an invalid class name."; + case lsPlugin.CONFIGERROR_MAIN_CLASS_NOT_EXIST: + return "ConfigError: mainClass does not exist."; + case lsPlugin.CONFIGERROR_MAIN_CLASS_NOT_UNIQUE: + return "ConfigError: mainClass is not unique in the workspace"; + case lsPlugin.CONFIGERROR_INVALID_JAVA_PROJECT: + return "ConfigError: could not find a Java project with the configured projectName."; + } + + return "ConfigError: Invalid mainClass/projectName configs."; + } + + private async fixMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration, + validationResponse: lsPlugin.ILaunchValidationResponse, progressReporter: IProgressReporter): + Promise { + const errors: string[] = []; + if (!validationResponse.mainClass.isValid) { + errors.push(String(validationResponse.mainClass.message)); + const errorLog: Error = { + name: "error", + message: this.getValidationErrorMessage(validationResponse.mainClass), + }; + setUserError(errorLog); + sendError(errorLog); + } + + if (!validationResponse.projectName.isValid) { + errors.push(String(validationResponse.projectName.message)); + const errorLog: Error = { + name: "error", + message: this.getValidationErrorMessage(validationResponse.projectName), + }; + setUserError(errorLog); + sendError(errorLog); + } + + if (validationResponse.proposals && validationResponse.proposals.length) { + progressReporter.hide(true); + const answer = await utility.showErrorMessageWithTroubleshooting({ + message: errors.join(os.EOL), + type: Type.USAGEERROR, + anchor: anchor.FAILED_TO_RESOLVE_CLASSPATH, + bypassLog: true, // Avoid logging the raw user input in the logger for privacy. + }, "Fix"); + if (answer === "Fix") { + const selectedFix = await mainClassPicker.showQuickPick(validationResponse.proposals, + "Please select main class.", false); + if (selectedFix) { + sendInfo("", { + fix: "yes", + fixMessage: "Fix the configs of mainClass and projectName", + }); + await this.persistMainClassOption(folder, config, selectedFix); + } + + return selectedFix; + } + // return undefined if the user clicks "Learn More". + return undefined; + } + + throw new utility.UserError({ + message: errors.join(os.EOL), + type: Type.USAGEERROR, + anchor: anchor.FAILED_TO_RESOLVE_CLASSPATH, + bypassLog: true, // Avoid logging the raw user input in the logger for privacy. + }); + } + + private async persistMainClassOption(folder: vscode.Uri | undefined, oldConfig: vscode.DebugConfiguration, change: lsPlugin.IMainClassOption): + Promise { + const newConfig: vscode.DebugConfiguration = _.cloneDeep(oldConfig); + newConfig.mainClass = change.mainClass; + newConfig.projectName = change.projectName; + + return this.persistLaunchConfig(folder, oldConfig, newConfig); + } + + private async persistLaunchConfig(folder: vscode.Uri | undefined, oldConfig: vscode.DebugConfiguration, newConfig: vscode.DebugConfiguration): + Promise { + const launchConfigurations: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("launch", folder); + const rawConfigs: vscode.DebugConfiguration[] = launchConfigurations.configurations; + const targetIndex: number = _.findIndex(rawConfigs, (config) => _.isEqual(config, oldConfig)); + if (targetIndex >= 0) { + rawConfigs[targetIndex] = newConfig; + await launchConfigurations.update("configurations", rawConfigs); + } + } + + private async promptMainClassUnderPath(folder: vscode.Uri | undefined, progressReporter: IProgressReporter, hintMessage?: string): + Promise { + const res = await lsPlugin.resolveMainClass(folder); + if (progressReporter.isCancelled()) { + return undefined; + } else if (res.length === 0) { + const workspaceFolder = folder ? vscode.workspace.getWorkspaceFolder(folder) : undefined; + throw new utility.UserError({ + message: `Cannot find a class with the main method${ workspaceFolder ? " in the folder '" + workspaceFolder.name + "'" : ""}.`, + type: Type.USAGEERROR, + anchor: anchor.CANNOT_FIND_MAIN_CLASS, + }); + } + + if (!mainClassPicker.isAutoPicked(res)) { + progressReporter.hide(true); + } + return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class"); + } + + private async promptMainClassUnderProject(projectName: string, progressReporter: IProgressReporter, hintMessage?: string): + Promise { + const res = await lsPlugin.resolveMainClassFromProject(projectName); + if (progressReporter.isCancelled()) { + return undefined; + } else if (res.length === 0) { + throw new utility.UserError({ + message: `Cannot find a class with the main method in the project '${projectName}'.`, + type: Type.USAGEERROR, + anchor: anchor.CANNOT_FIND_MAIN_CLASS, + }); + } + + if (!mainClassPicker.isAutoPicked(res)) { + progressReporter.hide(true); + } + return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class"); + } +} + +async function updateDebugSettings(event?: vscode.ConfigurationChangeEvent) { + const debugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug"); + if (!debugSettingsRoot) { + return; + } + const logLevel = convertLogLevel(debugSettingsRoot.logLevel || ""); + const javaHome = await utility.getJavaHome(); + if (debugSettingsRoot.settings && Object.keys(debugSettingsRoot.settings).length) { + try { + const stepFilters = { + skipClasses: await substituteFilterVariables(debugSettingsRoot.settings.stepping.skipClasses), + skipSynthetics: debugSettingsRoot.settings.stepping.skipSynthetics, + skipStaticInitializers: debugSettingsRoot.settings.stepping.skipStaticInitializers, + skipConstructors: debugSettingsRoot.settings.stepping.skipConstructors, + }; + const exceptionFilters = { + exceptionTypes: debugSettingsRoot.settings.exceptionBreakpoint.exceptionTypes, + allowClasses: debugSettingsRoot.settings.exceptionBreakpoint.allowClasses, + skipClasses: await substituteFilterVariables(debugSettingsRoot.settings.exceptionBreakpoint.skipClasses), + }; + + const asyncJDWP: string = debugSettingsRoot.settings.jdwp.async; + const settings = await commands.executeJavaLanguageServerCommand(commands.JAVA_UPDATE_DEBUG_SETTINGS, JSON.stringify( + { + ...debugSettingsRoot.settings, + logLevel, + javaHome, + stepFilters, + exceptionFilters, + exceptionFiltersUpdated: event && + (event.affectsConfiguration("java.debug.settings.exceptionBreakpoint.skipClasses") + || event.affectsConfiguration("java.debug.settings.exceptionBreakpoint.allowClasses") + || event.affectsConfiguration("java.debug.settings.exceptionBreakpoint.exceptionTypes")), + limitOfVariablesPerJdwpRequest: Math.max(debugSettingsRoot.settings.jdwp.limitOfVariablesPerJdwpRequest, 1), + jdwpRequestTimeout: Math.max(debugSettingsRoot.settings.jdwp.requestTimeout, 100), + asyncJDWP, + })); + if (logLevel === "FINE") { + // tslint:disable-next-line:no-console + console.log("settings:", settings); + } + } catch (err) { + // log a warning message and continue, since update settings failure should not block debug session + // tslint:disable-next-line:no-console + console.log("Cannot update debug settings.", err); + } + } +} + +function needsBuildWorkspace(): boolean { + const javaConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java"); + return javaConfig?.debug?.settings?.forceBuildBeforeLaunch; +} + +function convertLogLevel(commonLogLevel: string) { + // convert common log level to java log level + switch (commonLogLevel.toLowerCase()) { + case "verbose": + return "FINE"; + case "warn": + return "WARNING"; + case "error": + return "SEVERE"; + case "info": + return "INFO"; + default: + return "FINE"; + } +} + +// from vscode-js-debug https://github.com/microsoft/vscode-js-debug/blob/master/src/targets/node/nodeLauncherBase.ts +function readEnvFile(file: string): { [key: string]: string } { + if (!fs.existsSync(file)) { + return {}; + } + + const buffer = stripBOM(fs.readFileSync(file, "utf8")); + const env = dotenv.parse(Buffer.from(buffer)); + + return env; +} + +function stripBOM(s: string): string { + if (s && s[0] === "\uFEFF") { + s = s.substr(1); + } + return s; +} diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 00000000..206dd470 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +export const JAVA_LANGID: string = "java"; +export const TELEMETRY_EVENT = "telemetry"; +export const HCR_EVENT = "hotcodereplace"; +export const USER_NOTIFICATION_EVENT = "usernotification"; + +export enum ClasspathVariable { + Auto = "$Auto", + Runtime = "$Runtime", + Test = "$Test", +} diff --git a/src/customWidget.ts b/src/customWidget.ts new file mode 100644 index 00000000..a4f4b88e --- /dev/null +++ b/src/customWidget.ts @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; + +export class NotificationBar implements vscode.Disposable { + private statusBar: vscode.StatusBarItem; + private lastUpdateTime: number; + + constructor(id: string, name: string) { + this.statusBar = vscode.window.createStatusBarItem(id, vscode.StatusBarAlignment.Left, 1); + this.statusBar.name = name; + } + + public show(text: string, duration?: number) { + this.statusBar.text = text; + this.statusBar.show(); + const updateTime = Date.now(); + this.lastUpdateTime = updateTime; + if (duration) { + setTimeout(() => { + if (this.lastUpdateTime === updateTime) { + this.statusBar.text = ""; + this.statusBar.hide(); + } + }, duration); + } + } + + public clear() { + this.statusBar.text = ""; + this.statusBar.hide(); + } + + public dispose() { + this.statusBar.dispose(); + } +} diff --git a/src/debugCodeLensProvider.ts b/src/debugCodeLensProvider.ts new file mode 100644 index 00000000..110d2946 --- /dev/null +++ b/src/debugCodeLensProvider.ts @@ -0,0 +1,231 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as _ from "lodash"; +import * as path from "path"; +import * as vscode from "vscode"; +import { instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper"; + +import { JAVA_LANGID } from "./constants"; +import { initializeHoverProvider } from "./hoverProvider"; +import { IMainMethod, isOnClasspath, resolveMainMethod } from "./languageServerPlugin"; +import { IProgressReporter } from "./progressAPI"; +import { getJavaExtensionAPI, isJavaExtEnabled, ServerMode } from "./utility"; + +const JAVA_RUN_CODELENS_COMMAND = "java.debug.runCodeLens"; +const JAVA_DEBUG_CODELENS_COMMAND = "java.debug.debugCodeLens"; +const JAVA_DEBUG_CONFIGURATION = "java.debug.settings"; +const ENABLE_CODE_LENS_VARIABLE = "enableRunDebugCodeLens"; + +export function initializeCodeLensProvider(context: vscode.ExtensionContext): void { + // delay registering codelens provider until the Java extension is activated. + if (isActivatedByJavaFile() && isJavaExtEnabled()) { + getJavaExtensionAPI().then((api) => { + if (api && (api.serverMode === ServerMode.LIGHTWEIGHT || api.serverMode === ServerMode.HYBRID)) { + api.onDidServerModeChange((mode: string) => { + if (mode === ServerMode.STANDARD) { + context.subscriptions.push(new DebugCodeLensContainer()); + } + }); + } else { + context.subscriptions.push(new DebugCodeLensContainer()); + } + }); + } else { + context.subscriptions.push(new DebugCodeLensContainer()); + } +} + +function isActivatedByJavaFile(): boolean { + if (vscode.window.activeTextEditor) { + return vscode.window.activeTextEditor.document && vscode.window.activeTextEditor.document.languageId === "java"; + } + + return false; +} + +class DebugCodeLensContainer implements vscode.Disposable { + private runCommand: vscode.Disposable; + private debugCommand: vscode.Disposable; + private lensProvider: vscode.Disposable | undefined; + private hoverProvider: vscode.Disposable | undefined; + private configurationEvent: vscode.Disposable; + + constructor() { + this.runCommand = instrumentOperationAsVsCodeCommand(JAVA_RUN_CODELENS_COMMAND, runJavaProgram); + this.debugCommand = instrumentOperationAsVsCodeCommand(JAVA_DEBUG_CODELENS_COMMAND, debugJavaProgram); + + const configuration = vscode.workspace.getConfiguration(JAVA_DEBUG_CONFIGURATION); + const isCodeLensEnabled = configuration.get(ENABLE_CODE_LENS_VARIABLE); + + if (isCodeLensEnabled) { + this.lensProvider = vscode.languages.registerCodeLensProvider(JAVA_LANGID, new DebugCodeLensProvider()); + } else { + this.hoverProvider = initializeHoverProvider(); + } + + this.configurationEvent = vscode.workspace.onDidChangeConfiguration((event: vscode.ConfigurationChangeEvent) => { + if (event.affectsConfiguration(JAVA_DEBUG_CONFIGURATION)) { + const newConfiguration = vscode.workspace.getConfiguration(JAVA_DEBUG_CONFIGURATION); + const newEnabled = newConfiguration.get(ENABLE_CODE_LENS_VARIABLE); + if (newEnabled && this.lensProvider === undefined) { + this.lensProvider = vscode.languages.registerCodeLensProvider(JAVA_LANGID, new DebugCodeLensProvider()); + } else if (!newEnabled && this.lensProvider !== undefined) { + this.lensProvider.dispose(); + this.lensProvider = undefined; + } + + if (newEnabled && this.hoverProvider) { + this.hoverProvider.dispose(); + this.hoverProvider = undefined; + } else if (!newEnabled && !this.hoverProvider) { + this.hoverProvider = initializeHoverProvider(); + } + } + }, this); + } + + public dispose() { + if (this.lensProvider !== undefined) { + this.lensProvider.dispose(); + } + if (this.hoverProvider) { + this.hoverProvider.dispose(); + } + this.runCommand.dispose(); + this.debugCommand.dispose(); + this.configurationEvent.dispose(); + } + +} + +class DebugCodeLensProvider implements vscode.CodeLensProvider { + + public async provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): Promise { + try { + const mainMethods: IMainMethod[] = await resolveMainMethod(document.uri, token); + return _.flatten(mainMethods.map((method) => { + return [ + new vscode.CodeLens(method.range, { + title: "Run", + command: JAVA_RUN_CODELENS_COMMAND, + tooltip: "Run Java Program", + arguments: [ method.mainClass, method.projectName, document.uri ], + }), + new vscode.CodeLens(method.range, { + title: "Debug", + command: JAVA_DEBUG_CODELENS_COMMAND, + tooltip: "Debug Java Program", + arguments: [ method.mainClass, method.projectName, document.uri ], + }), + ]; + })); + } catch (ex) { + // do nothing. + return []; + } + } +} + +function runJavaProgram(mainClass: string, projectName: string, uri: vscode.Uri): Promise { + return startDebugging(mainClass, projectName, uri, true); +} + +function debugJavaProgram(mainClass: string, projectName: string, uri: vscode.Uri): Promise { + return startDebugging(mainClass, projectName, uri, false); +} + +async function constructDebugConfig(mainClass: string, projectName: string, workspace?: vscode.Uri): Promise { + const launchConfigurations: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("launch", workspace); + const rawConfigs: vscode.DebugConfiguration[] = launchConfigurations.configurations; + + let debugConfig: vscode.DebugConfiguration | undefined = _.find(rawConfigs, (config) => { + return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName); + }); + + if (!debugConfig) { + debugConfig = _.find(rawConfigs, (config) => { + return config.mainClass === mainClass && !config.projectName; + }); + } + + if (!debugConfig) { + debugConfig = { + type: "java", + name: `${mainClass.substr(mainClass.lastIndexOf(".") + 1)}`, + request: "launch", + mainClass, + projectName, + }; + + // Persist the configuration into launch.json only if the launch.json file already exists in the workspace. + if ((rawConfigs && rawConfigs.length) || await launchJsonExists(workspace)) { + try { + // Insert the default debug configuration to the beginning of launch.json. + rawConfigs.splice(0, 0, debugConfig); + await launchConfigurations.update("configurations", rawConfigs, vscode.ConfigurationTarget.WorkspaceFolder); + } catch (error) { + // When launch.json has unsaved changes before invoking the update api, it will throw the error below: + // 'Unable to write into launch configuration file because the file is dirty. Please save it first and then try again.' + // It's safe to ignore it because the only impact is the configuration is not saved, but you can continue to start the debugger. + } + } + } + + return _.cloneDeep(debugConfig); +} + +async function launchJsonExists(workspace?: vscode.Uri): Promise { + if (!workspace) { + return false; + } + + const workspaceFolder = vscode.workspace.getWorkspaceFolder(workspace); + // Excluding "**/node_modules/**" as a common cause of excessive CPU usage. + // https://github.com/microsoft/vscode/issues/75314#issuecomment-503195666 + const results: vscode.Uri[] = await vscode.workspace.findFiles(".vscode/launch.json", "**/node_modules/**"); + return !!results.find((launchJson) => vscode.workspace.getWorkspaceFolder(launchJson) === workspaceFolder); +} + +export async function startDebugging(mainClass: string, projectName: string, uri: vscode.Uri, noDebug: boolean, + progressReporter?: IProgressReporter): Promise { + const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); + const workspaceUri: vscode.Uri | undefined = workspaceFolder ? workspaceFolder.uri : undefined; + const onClasspath = await isOnClasspath(uri.toString()); + if (workspaceUri && onClasspath === false && !(await addToClasspath(uri))) { + return false; + } + + const debugConfig: vscode.DebugConfiguration = await constructDebugConfig(mainClass, projectName, workspaceUri); + debugConfig.projectName = projectName; + debugConfig.noDebug = noDebug; + debugConfig.__progressId = progressReporter?.getId(); + debugConfig.__origin = "internal"; + + return vscode.debug.startDebugging(workspaceFolder, debugConfig); +} + +async function addToClasspath(uri: vscode.Uri): Promise { + const fileName = path.basename(uri.fsPath || ""); + const parentFsPath = path.dirname(uri.fsPath || ""); + if (!parentFsPath) { + return true; + } + + const parentUri = vscode.Uri.file(parentFsPath); + let parentPath = vscode.workspace.asRelativePath(parentUri, true); + if (parentPath === parentUri.fsPath) { + parentPath = path.basename(parentFsPath); + } + sendInfo("", {operationName: "notOnClasspath"}); + const ans = await vscode.window.showWarningMessage(`The file ${fileName} isn't on the classpath, the runtime may throw class not found error. ` + + `Do you want to add the parent folder "${parentPath}" to Java source path?`, "Add to Source Path", "Skip"); + if (ans === "Skip") { + return true; + } else if (ans === "Add to Source Path") { + sendInfo("", {operationName: "addToSourcePath"}); + vscode.commands.executeCommand("java.project.addToSourcePath.command", parentUri); + } + + return false; +} diff --git a/src/experimentationService.ts b/src/experimentationService.ts new file mode 100644 index 00000000..42a1c84a --- /dev/null +++ b/src/experimentationService.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { addContextProperty, sendInfo } from "vscode-extension-telemetry-wrapper"; +import { getExperimentationServiceAsync, IExperimentationService, IExperimentationTelemetry, TargetPopulation } from "vscode-tas-client"; + +class ExperimentationTelemetry implements IExperimentationTelemetry { + + public setSharedProperty(name: string, value: string): void { + addContextProperty(name, value); + } + + public postEvent(eventName: string, props: Map): void { + const payload: any = { __event_name__: eventName }; + for (const [key, value] of props) { + payload[key] = value; + } + + sendInfo("", payload); + } +} + +let expService: IExperimentationService; + +export function getExpService() { + return expService; +} + +export async function initExpService(context: vscode.ExtensionContext): Promise { + const packageJson: {[key: string]: any} = require("../package.json"); + // tslint:disable: no-string-literal + const extensionName = `${packageJson["publisher"]}.${packageJson["name"]}`; + const extensionVersion = packageJson["version"]; + // tslint:enable: no-string-literal + + // The async version will await the initializePromise to make sure shared property is set + expService = await getExperimentationServiceAsync(extensionName, extensionVersion, + TargetPopulation.Public, new ExperimentationTelemetry(), context.globalState); +} diff --git a/src/extension.ts b/src/extension.ts index 606e32b0..e3a75eb0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,166 +1,496 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +import * as compareVersions from "compare-versions"; +import * as _ from "lodash"; import * as path from "path"; import * as vscode from "vscode"; -import TelemetryReporter from "vscode-extension-telemetry"; +import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation, + instrumentOperationAsVsCodeCommand, sendInfo, setUserError } from "vscode-extension-telemetry-wrapper"; import * as commands from "./commands"; +import { JavaDebugConfigurationProvider, lastUsedLaunchConfig } from "./configurationProvider"; +import { HCR_EVENT, JAVA_LANGID, TELEMETRY_EVENT, USER_NOTIFICATION_EVENT } from "./constants"; +import { NotificationBar } from "./customWidget"; +import { initializeCodeLensProvider, startDebugging } from "./debugCodeLensProvider"; +import { initExpService } from "./experimentationService"; +import { registerNoConfigDebug } from "./noConfigDebugInit"; +import { handleHotCodeReplaceCustomEvent, initializeHotCodeReplace, NO_BUTTON, YES_BUTTON } from "./hotCodeReplace"; +import { JavaDebugAdapterDescriptorFactory } from "./javaDebugAdapterDescriptorFactory"; +import { JavaInlineValuesProvider } from "./JavaInlineValueProvider"; +import { logJavaException, logJavaInfo } from "./javaLogger"; +import { registerLanguageModelTool, registerDebugSessionTools } from "./languageModelTool"; +import { IMainClassOption, IMainMethod, resolveMainMethod } from "./languageServerPlugin"; +import { mainClassPicker } from "./mainClassPicker"; +import { pickJavaProcess } from "./processPicker"; +import { IProgressReporter } from "./progressAPI"; +import { progressProvider } from "./progressImpl"; +import { JavaTerminalLinkProvder } from "./terminalLinkProvider"; +import { initializeThreadOperations } from "./threadOperations"; +import * as utility from "./utility"; +import { registerBreakpointCommands } from "./breakpointCommands"; +import { registerVariableMenuCommands } from "./variableMenu"; +import { promisify } from "util"; -const status: any = {}; +export async function activate(context: vscode.ExtensionContext): Promise { + await initializeFromJsonFile(context.asAbsolutePath("./package.json")); + await initExpService(context); -export function activate(context: vscode.ExtensionContext) { - // The reporter will be initialized by the later telemetry handler. - let reporter: TelemetryReporter = null; + // Register No-Config Debug functionality + const noConfigDisposable = await registerNoConfigDebug( + context.environmentVariableCollection, + context.extensionPath + ); + context.subscriptions.push(noConfigDisposable); - vscode.commands.registerCommand(commands.JAVA_START_DEBUGSESSION, async (config) => { + // Register Language Model Tools after Java Language Server is ready + registerLanguageModelToolsWhenReady(context); - if (!status.debugging) { - status.debugging = "startDebugSession"; + return instrumentOperation("activation", initializeExtension)(context); +} + +function initializeExtension(_operationId: string, context: vscode.ExtensionContext): any { + registerDebugEventListener(context); + registerBreakpointCommands(context); + registerVariableMenuCommands(context); + context.subscriptions.push(vscode.window.registerTerminalLinkProvider(new JavaTerminalLinkProvder())); + context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("java", new JavaDebugConfigurationProvider())); + context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory("java", new JavaDebugAdapterDescriptorFactory())); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("JavaDebug.SpecifyProgramArgs", async () => { + return specifyProgramArguments(context); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("JavaDebug.PickJavaProcess", async () => { + let javaProcess; + try { + javaProcess = await pickJavaProcess(); + } catch (error) { + vscode.window.showErrorMessage(error.message ? error.message : String(error)); + } + + // tslint:disable-next-line + return javaProcess ? String(javaProcess.pid) : "${command:PickJavaProcess}"; + })); + const hcrStatusBar: NotificationBar = new NotificationBar("java.hcrStatusBar", "Java HotCodeReplace"); + context.subscriptions.push(hcrStatusBar); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.hotCodeReplace", async () => { + await applyHCR(hcrStatusBar); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.runJavaFile", async (uri: vscode.Uri) => { + await runJavaFile(uri, true); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.debugJavaFile", async (uri: vscode.Uri) => { + await runJavaFile(uri, false); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.runFromProjectView", async (node: any) => { + await runJavaProject(node, true); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.debugFromProjectView", async (node: any) => { + await runJavaProject(node, false); + })); + initializeHotCodeReplace(context); + initializeCodeLensProvider(context); + initializeThreadOperations(context); + subscribeToJavaExtensionEvents(); + + context.subscriptions.push(vscode.languages.registerInlineValuesProvider("java", new JavaInlineValuesProvider())); + return { + progressProvider, + }; +} + +// this method is called when your extension is deactivated +export async function deactivate() { + await disposeTelemetryWrapper(); +} + +const delay = promisify(setTimeout); + +/** + * Register Language Model Tools after Java Language Server is ready. + * The debug tools depend on JDT.LS for compilation, classpath resolution, + * and executing debug server commands. + */ +async function registerLanguageModelToolsWhenReady(context: vscode.ExtensionContext): Promise { + // Check if Language Model API is available + if (!vscode.lm || typeof vscode.lm.registerTool !== 'function') { + return; + } + + const javaExt = vscode.extensions.getExtension("redhat.java"); + if (!javaExt) { + return; + } - try { - try { - const level = await configLogLevel(vscode.workspace.getConfiguration().get("java.debug.logLevel")); - console.log("setting log level to ", level); - } catch (err) { - // log a warning message and continue, since logger failure should not block debug session - console.log("Cannot set log level to java debuggeer.") + // Register Language Model Tools for AI-assisted debugging + registerLanguageModelTool(context); + const debugToolsDisposables = registerDebugSessionTools(context); + context.subscriptions.push(...debugToolsDisposables); +} + +async function subscribeToJavaExtensionEvents(): Promise { + const javaExt = vscode.extensions.getExtension("redhat.java"); + if (!javaExt) { + return; + } + + // wait javaExt to activate + const timeout = 30 * 60 * 1000; // wait 30 min at most + let count = 0; + while (!javaExt.isActive && count < timeout) { + await delay(1000); + count += 1000; + } + + if (javaExt.isActive) { + javaExt.exports?.onDidSourceInvalidate?.((event: any) => { + if (event?.affectedRootPaths?.length) { + const activeDebugSession = vscode.debug.activeDebugSession; + if (activeDebugSession?.type === "java") { + activeDebugSession.customRequest("refreshFrames", { + affectedRootPaths: event.affectedRootPaths, + }); } - if (Object.keys(config).length === 0) { // No launch.json in current workspace. - const ans = await vscode.window.showInformationMessage( - "\"launch.json\" is needed to start the debugger. Do you want to create it now?", "Yes", "No"); - if (ans === "Yes") { - vscode.commands.executeCommand(commands.VSCODE_ADD_DEBUGCONFIGURATION); - } - return; - } else if (config.request === "launch") { - if (!config.mainClass) { - vscode.window.showErrorMessage("Please specify the mainClass in the launch.json."); - return; - } else if (!config.classPaths || !Array.isArray(config.classPaths) || !config.classPaths.length) { - config.classPaths = await resolveClasspath(config.mainClass, config.projectName); - } - if (!config.classPaths || !Array.isArray(config.classPaths) || !config.classPaths.length) { - vscode.window.showErrorMessage("Cannot resolve the classpaths automatically, please specify the value in the launch.json."); - return; - } - } else if (config.request === "attach") { - if (!config.hostName || !config.port) { - vscode.window.showErrorMessage("Please specify the host name and the port of the remote debuggee in the launch.json."); - return; - } - } else { - const ans = await vscode.window.showErrorMessage( - // tslint:disable-next-line:max-line-length - "Request type \"" + config.request + "\" is not supported. Only \"launch\" and \"attach\" are supported.", "Open launch.json"); - if (ans === "Open launch.json") { - await vscode.commands.executeCommand(commands.VSCODE_ADD_DEBUGCONFIGURATION); + } + }); + } +} + +function registerDebugEventListener(context: vscode.ExtensionContext) { + const measureKeys = ["duration"]; + context.subscriptions.push(vscode.debug.onDidTerminateDebugSession((e) => { + if (e.type !== "java") { + return; + } + fetchUsageData().then((ret) => { + if (Array.isArray(ret) && ret.length) { + ret.forEach((entry) => { + const commonProperties: any = {}; + const measureProperties: any = {}; + for (const key of Object.keys(entry)) { + if (measureKeys.indexOf(key) >= 0) { + measureProperties[key] = entry[key]; + } else { + commonProperties[key] = String(entry[key]); + } } - return; - } - const debugServerPort = await startDebugSession(); - if (debugServerPort) { - config.debugServer = debugServerPort; - await vscode.commands.executeCommand(commands.VSCODE_STARTDEBUG, config); - } else { - // Information for diagnostic: - console.log("Cannot find a port for debugging session"); - } - } catch (ex) { - const errorMessage = (ex && ex.message) || ex; - vscode.window.showErrorMessage(errorMessage); - if (reporter) { - const exception = (ex && ex.data && ex.data.cause) - || { stackTrace: [], detailMessage: String((ex && ex.message) || ex || "Unknown exception") }; - const properties = { - message: "", - stackTrace: "", - }; - if (exception && typeof exception === "object") { - properties.message = exception.detailMessage; - properties.stackTrace = (Array.isArray(exception.stackTrace) && JSON.stringify(exception.stackTrace)) - || String(exception.stackTrace); + if (entry.scope === "exception") { + logJavaException(commonProperties); } else { - properties.message = String(exception); + logJavaInfo(commonProperties, measureProperties); } - reporter.sendTelemetryEvent("exception", properties); - } - } finally { - delete status.debugging; + }); } - } - }); + }); + })); - // Telemetry. - const extensionPackage = require(context.asAbsolutePath("./package.json")); - if (extensionPackage) { - const packageInfo = { - name: extensionPackage.name, - version: extensionPackage.version, - aiKey: extensionPackage.aiKey, - }; - if (packageInfo.aiKey) { - reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey); - reporter.sendTelemetryEvent("activateExtension", {}); - const measureKeys = ["duration"]; - vscode.debug.onDidTerminateDebugSession(() => { - fetchUsageData().then((ret) => { - if (Array.isArray(ret) && ret.length) { - ret.forEach((entry) => { - const commonProperties: any = {}; - const measureProperties: any = {}; - for (const key of Object.keys(entry)) { - if (measureKeys.indexOf(key) >= 0) { - measureProperties[key] = entry[key]; - } else { - commonProperties[key] = String(entry[key]); - } - } - reporter.sendTelemetryEvent(entry.scope === "exception" ? "exception" : "usageData", commonProperties, measureProperties); - }); - } - }); + context.subscriptions.push(vscode.debug.onDidReceiveDebugSessionCustomEvent((customEvent) => { + const t = customEvent.session ? customEvent.session.type : undefined; + if (t !== JAVA_LANGID) { + return; + } + if (customEvent.event === TELEMETRY_EVENT) { + sendInfo("", { + operationName: customEvent.body?.name, + ...customEvent.body?.properties, }); + } else if (customEvent.event === HCR_EVENT) { + handleHotCodeReplaceCustomEvent(customEvent); + } else if (customEvent.event === USER_NOTIFICATION_EVENT) { + handleUserNotification(customEvent); } + })); +} + +function handleUserNotification(customEvent: vscode.DebugSessionCustomEvent) { + if (customEvent.body.notificationType === "ERROR") { + utility.showErrorMessageWithTroubleshooting({ + message: customEvent.body.message, + }); + } else if (customEvent.body.notificationType === "WARNING") { + utility.showWarningMessageWithTroubleshooting({ + message: customEvent.body.message, + }); + } else { + vscode.window.showInformationMessage(customEvent.body.message); } } -// this method is called when your extension is deactivated -export function deactivate() { +function fetchUsageData() { + return commands.executeJavaLanguageServerCommand(commands.JAVA_FETCH_USAGE_DATA); +} + +function specifyProgramArguments(context: vscode.ExtensionContext): Thenable { + const javaDebugProgramArgsKey = "JavaDebugProgramArgs"; + + const options: vscode.InputBoxOptions = { + ignoreFocusOut: true, + placeHolder: "Enter program arguments or leave empty to pass no args", + }; + + const prevArgs = context.workspaceState.get(javaDebugProgramArgsKey, ""); + if (prevArgs.length > 0) { + options.value = prevArgs; + } + + return vscode.window.showInputBox(options).then((text) => { + // When user cancels the input box (by pressing Esc), the text value is undefined. + if (text !== undefined) { + context.workspaceState.update(javaDebugProgramArgsKey, text); + } + + return text || " "; + }); +} + +async function applyHCR(hcrStatusBar: NotificationBar) { + const debugSession: vscode.DebugSession | undefined = vscode.debug.activeDebugSession; + if (!debugSession) { + return; + } + + if (debugSession.configuration.noDebug) { + vscode.window.showWarningMessage("Failed to apply the changes because hot code replace is not supported by run mode, " + + "would you like to restart the program?", YES_BUTTON, NO_BUTTON).then((res) => { + if (res === YES_BUTTON) { + vscode.commands.executeCommand("workbench.action.debug.restart"); + } + }); + + return; + } + + const autobuildConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.autobuild"); + if (!autobuildConfig.enabled) { + // If autobuild is disabled, force an incremental build before HCR. + try { + hcrStatusBar.show("$(sync~spin)Compiling..."); + await commands.executeJavaExtensionCommand(commands.JAVA_BUILD_WORKSPACE, JSON.stringify({ + isFullBuild: false + })); + } catch (err) { + // do nothing. + } + } + + hcrStatusBar.show("$(sync~spin)Applying code changes..."); + const start = new Date().getTime(); + const response = await debugSession.customRequest("redefineClasses"); + const elapsed = new Date().getTime() - start; + const humanVisibleDelay = elapsed < 150 ? 150 : 0; + if (humanVisibleDelay) { + await new Promise((resolve) => { + setTimeout(resolve, humanVisibleDelay); + }); + } + + if (response && response.errorMessage) { + // The detailed error message is handled by hotCodeReplace#handleHotCodeReplaceCustomEvent + hcrStatusBar.clear(); + return; + } + + if (!response || !response.changedClasses || !response.changedClasses.length) { + hcrStatusBar.clear(); + vscode.window.showWarningMessage("Cannot find any changed classes for hot replace!"); + return; + } + + const changed = response.changedClasses.length; + hcrStatusBar.show("$(check)" + `${changed} changed class${changed > 1 ? "es are" : " is"} reloaded`, 5 * 1000); } -function startDebugSession() { - return executeJavaLanguageServerCommand(commands.JAVA_START_DEBUGSESSION); +async function runJavaFile(uri: vscode.Uri, noDebug: boolean) { + const progressReporter = progressProvider.createProgressReporter(noDebug ? "Run" : "Debug"); + try { + // Wait for Java Language Support extension being on Standard mode. + const isOnStandardMode = await utility.waitForStandardMode(progressReporter); + if (!isOnStandardMode) { + throw new utility.OperationCancelledError(""); + } + + const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + if (!uri && activeEditor && _.endsWith(path.basename(activeEditor.document.fileName), ".java")) { + uri = activeEditor.document.uri; + } + + if (!uri) { + vscode.window.showErrorMessage(`${noDebug ? "Run" : "Debug"} failed. Please open a Java file with main method first.`); + throw new utility.OperationCancelledError(""); + } + + const mainMethods: IMainMethod[] = await resolveMainMethod(uri); + const hasMainMethods: boolean = mainMethods.length > 0; + const canRunTests: boolean = await canDelegateToJavaTestRunner(uri); + const defaultPlaceHolder: string = "Select the main class to run"; + + if (!hasMainMethods && !canRunTests) { + // If current file is not a main class, "Run Java" will run previously used launch config. + if (lastUsedLaunchConfig) { + progressReporter.setJobName(utility.launchJobName(lastUsedLaunchConfig.name, noDebug)); + progressReporter.report("Resolving launch configuration..."); + lastUsedLaunchConfig.noDebug = noDebug; + lastUsedLaunchConfig.__progressId = progressReporter.getId(); + vscode.debug.startDebugging(lastUsedLaunchConfig.__workspaceFolder, lastUsedLaunchConfig); + } else { + progressReporter.report("Resolving main class..."); + const mainClasses: IMainClassOption[] = await utility.searchMainMethods(); + if (progressReporter.isCancelled()) { + throw new utility.OperationCancelledError(""); + } + + const placeHolder: string = `The file '${path.basename(uri.fsPath)}' is not executable, please select a main class you want to run.`; + await launchMain(mainClasses, uri, noDebug, progressReporter, placeHolder, false /*autoPick*/); + } + } else if (hasMainMethods && !canRunTests) { + await launchMain(mainMethods, uri, noDebug, progressReporter, defaultPlaceHolder); + } else if (!hasMainMethods && canRunTests) { + launchTesting(uri, noDebug, progressReporter); + } else { + const launchMainChoice: string = "main() method"; + const launchTestChoice: string = "unit tests"; + const choice: string | undefined = await vscode.window.showQuickPick( + [launchMainChoice, launchTestChoice], + { placeHolder: "Please select which kind of task you would like to launch" }, + ); + if (choice === launchMainChoice) { + await launchMain(mainMethods, uri, noDebug, progressReporter, defaultPlaceHolder); + } else if (choice === launchTestChoice) { + launchTesting(uri, noDebug, progressReporter); + } + } + } catch (ex) { + progressReporter.done(); + if (ex instanceof utility.OperationCancelledError) { + return; + } + + if (ex instanceof utility.JavaExtensionNotEnabledError) { + utility.guideToInstallJavaExtension(); + return; + } + + vscode.window.showErrorMessage(String((ex && ex.message) || ex)); + } } -function resolveClasspath(mainClass, projectName) { - return executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_CLASSPATH, mainClass, projectName); +async function canDelegateToJavaTestRunner(uri: vscode.Uri): Promise { + const fsPath: string = uri.fsPath; + const isTestFile: boolean = /.*[\/\\]src[\/\\]test[\/\\]java[\/\\].*[Tt]ests?\.java/.test(fsPath); + if (!isTestFile) { + return false; + } + return (await vscode.commands.getCommands()).includes("java.test.editor.run"); } -function fetchUsageData() { - return executeJavaLanguageServerCommand(commands.JAVA_FETCH_USAGE_DATA); +function launchTesting(uri: vscode.Uri, noDebug: boolean, progressReporter: IProgressReporter) { + const command: string = noDebug ? "java.test.editor.run" : "java.test.editor.debug"; + vscode.commands.executeCommand(command, uri, progressReporter); + if (compareVersions.compare(getTestExtensionVersion(), "0.26.1", "<=")) { + throw new utility.OperationCancelledError(""); + } } -function executeJavaLanguageServerCommand(...rest) { - // TODO: need to handle error and trace telemetry - return vscode.commands.executeCommand(commands.JAVA_EXECUTE_WORKSPACE_COMMAND, ...rest); +function getTestExtensionVersion(): string { + const extension: vscode.Extension | undefined = vscode.extensions.getExtension("vscjava.vscode-java-test"); + return extension?.packageJSON.version || "0.0.0"; } -function configLogLevel(level) { - return executeJavaLanguageServerCommand(commands.JAVA_CONFIG_LOG_LEVEL, convertLogLevel(level)); +async function launchMain(mainMethods: IMainClassOption[], uri: vscode.Uri, noDebug: boolean, progressReporter: IProgressReporter, + placeHolder: string, autoPick: boolean = true): Promise { + if (!mainMethods || !mainMethods.length) { + vscode.window.showErrorMessage( + "Error: Main method not found in the file, please define the main method as: public static void main(String[] args)"); + throw new utility.OperationCancelledError(""); + } + + if (!mainClassPicker.isAutoPicked(mainMethods, autoPick)) { + progressReporter.hide(true); + } + + const pick = await mainClassPicker.showQuickPickWithRecentlyUsed(mainMethods, placeHolder, autoPick); + if (!pick) { + throw new utility.OperationCancelledError(""); + } + + const existConfig: vscode.DebugConfiguration | undefined = findLaunchConfiguration( + pick.mainClass, pick.projectName, uri.fsPath); + if (existConfig) { + progressReporter.setJobName(utility.launchJobName(existConfig.name, noDebug)); + } else { + progressReporter.setJobName(utility.launchJobNameByMainClass(pick.mainClass, noDebug)); + } + progressReporter.report("Launching main class..."); + startDebugging(pick.mainClass, pick.projectName || "", uri, noDebug, progressReporter); } -function convertLogLevel(commonLogLevel: string) { - // convert common log level to java log level - switch (commonLogLevel.toLowerCase()) { - case "verbose" : - return "FINE"; - case "warn" : - return "WARNING"; - case "error" : - return "SEVERE"; - case "info" : - return "INFO"; - default: - return "FINE"; +async function runJavaProject(node: any, noDebug: boolean) { + if (!node || !node.name || !node.uri) { + vscode.window.showErrorMessage(`Failed to ${noDebug ? "run" : "debug"} the project because of invalid project node. ` + + "This command only applies to Project Explorer view."); + const error = new Error(`Failed to ${noDebug ? "run" : "debug"} the project because of invalid project node.`); + setUserError(error); + throw error; + } + + const progressReporter = progressProvider.createProgressReporter(noDebug ? "Run" : "Debug"); + try { + progressReporter.report("Resolving main class..."); + const mainClassesOptions: IMainClassOption[] = await utility.searchMainMethods(vscode.Uri.parse(node.uri)); + if (progressReporter.isCancelled()) { + throw new utility.OperationCancelledError(""); + } + + if (!mainClassesOptions || !mainClassesOptions.length) { + vscode.window.showErrorMessage(`Failed to ${noDebug ? "run" : "debug"} this project '${node._nodeData.displayName || node.name}' ` + + "because it does not contain any main class."); + throw new utility.OperationCancelledError(""); + } + + if (!mainClassPicker.isAutoPicked(mainClassesOptions)) { + progressReporter.hide(true); + } + const pick = await mainClassPicker.showQuickPickWithRecentlyUsed(mainClassesOptions, + "Select the main class to run."); + if (!pick || progressReporter.isCancelled()) { + throw new utility.OperationCancelledError(""); + } + + const projectName: string | undefined = pick.projectName; + const mainClass: string = pick.mainClass; + const filePath: string | undefined = pick.filePath; + const workspaceFolder: vscode.WorkspaceFolder | undefined = + filePath ? vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath)) : undefined; + const existConfig: vscode.DebugConfiguration | undefined = findLaunchConfiguration(mainClass, projectName, filePath); + const debugConfig = existConfig || { + type: "java", + name: `${mainClass.substr(mainClass.lastIndexOf(".") + 1)}`, + request: "launch", + mainClass, + projectName, + }; + debugConfig.noDebug = noDebug; + debugConfig.__progressId = progressReporter.getId(); + debugConfig.__origin = "internal"; + progressReporter.setJobName(utility.launchJobName(debugConfig.name, noDebug)); + progressReporter.report("Launching main class..."); + vscode.debug.startDebugging(workspaceFolder, debugConfig); + } catch (ex) { + progressReporter.done(); + if (ex instanceof utility.OperationCancelledError) { + return; + } + + throw ex; } } + +function findLaunchConfiguration(mainClass: string, projectName: string | undefined, filePath?: string): vscode.DebugConfiguration | undefined { + const workspaceFolder: vscode.WorkspaceFolder | undefined = + filePath ? vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath)) : undefined; + const launchConfigurations: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("launch", workspaceFolder); + const existingConfigs: vscode.DebugConfiguration[] = launchConfigurations.configurations; + const existConfig: vscode.DebugConfiguration | undefined = _.find(existingConfigs, (config) => { + return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName); + }); + + return existConfig; +} diff --git a/src/hotCodeReplace.ts b/src/hotCodeReplace.ts new file mode 100644 index 00000000..03ee077b --- /dev/null +++ b/src/hotCodeReplace.ts @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; + +import * as anchor from "./anchor"; +import { JAVA_LANGID } from "./constants"; +import * as utility from "./utility"; + +const suppressedReasons: Set = new Set(); + +export const YES_BUTTON: string = "Yes"; + +export const NO_BUTTON: string = "No"; + +const NEVER_BUTTON: string = "Do not show again"; + +enum HcrChangeType { + ERROR = "ERROR", + WARNING = "WARNING", + STARTING = "STARTING", + END = "END", + BUILD_COMPLETE = "BUILD_COMPLETE", +} + +export function initializeHotCodeReplace(context: vscode.ExtensionContext) { + vscode.commands.executeCommand("setContext", "javaHotReload", getHotReloadFlag()); + vscode.workspace.onDidChangeConfiguration((event) => { + if (event.affectsConfiguration("java.debug.settings.hotCodeReplace")) { + vscode.commands.executeCommand("setContext", "javaHotReload", getHotReloadFlag()); + } + }); + vscode.debug.onDidStartDebugSession((session) => { + if (session?.configuration.noDebug && !vscode.debug.activeDebugSession) { + vscode.commands.executeCommand("setContext", "javaHotReloadOn", false); + } + }); + vscode.debug.onDidChangeActiveDebugSession((session) => { + vscode.commands.executeCommand("setContext", "javaHotReloadOn", session && !session.configuration.noDebug); + }); + context.subscriptions.push(vscode.debug.onDidTerminateDebugSession((session) => { + const t = session ? session.type : undefined; + if (t === JAVA_LANGID) { + suppressedReasons.clear(); + } + })); +} + +export function handleHotCodeReplaceCustomEvent(hcrEvent: vscode.DebugSessionCustomEvent) { + if (hcrEvent.body.changeType === HcrChangeType.BUILD_COMPLETE) { + if (getHotReloadFlag() === "auto") { + return vscode.window.withProgress({ location: vscode.ProgressLocation.Window }, (progress) => { + progress.report({ message: "Applying code changes..." }); + return hcrEvent.session.customRequest("redefineClasses"); + }); + } + } + + if (hcrEvent.body.changeType === HcrChangeType.ERROR || hcrEvent.body.changeType === HcrChangeType.WARNING) { + if (!suppressedReasons.has(hcrEvent.body.message)) { + utility.showWarningMessageWithTroubleshooting({ + message: `Hot code replace failed - ${hcrEvent.body.message}. Would you like to restart the debug session?`, + anchor: anchor.FAILED_TO_COMPLETE_HCR, + }, YES_BUTTON, NO_BUTTON, NEVER_BUTTON).then((res) => { + if (res === NEVER_BUTTON) { + suppressedReasons.add(hcrEvent.body.message); + } else if (res === YES_BUTTON) { + vscode.commands.executeCommand("workbench.action.debug.restart"); + } + }); + } + } + return undefined; +} + +function getHotReloadFlag(): string { + return vscode.workspace.getConfiguration("java.debug.settings").get("hotCodeReplace") || "manual"; +} diff --git a/src/hoverProvider.ts b/src/hoverProvider.ts new file mode 100644 index 00000000..2a44ffa9 --- /dev/null +++ b/src/hoverProvider.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { CancellationToken, Command, Disposable, Hover, HoverProvider, languages, MarkdownString, Position, ProviderResult, TextDocument, + Uri, window } from "vscode"; +import { instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper"; +import { JAVA_LANGID } from "./constants"; +import { startDebugging } from "./debugCodeLensProvider"; +import { resolveElementAtSelection } from "./languageServerPlugin"; + +const JAVA_HOVER_RUN_COMMAND = "java.debug.runHover"; +const MAIN_METHOD_REGEX = /^(public|static|final|synchronized|\s+){4,}void\s+main\s*\(\s*String\s*\[\s*\]\s*\w+\s*\)\s*($|\{)/; + +export function initializeHoverProvider(): Disposable { + return new DebugHoverProvider(); +} + +class DebugHoverProvider implements Disposable { + private runHoverCommand: Disposable; + private hoverProvider: Disposable | undefined; + + constructor() { + this.runHoverCommand = instrumentOperationAsVsCodeCommand(JAVA_HOVER_RUN_COMMAND, async (noDebug: boolean, uri: string, position: any) => { + const element = await resolveElementAtSelection(uri, position.line, position.character); + if (element && element.hasMainMethod) { + startDebugging(element.declaringType, element.projectName, Uri.parse(uri), noDebug); + } else { + window.showErrorMessage("The hovered element is not a main method."); + } + }); + this.hoverProvider = languages.registerHoverProvider(JAVA_LANGID, new InternalDebugHoverProvider()); + } + + public dispose() { + if (this.runHoverCommand) { + this.runHoverCommand.dispose(); + } + + if (this.hoverProvider) { + this.hoverProvider.dispose(); + } + } +} + +class InternalDebugHoverProvider implements HoverProvider { + public provideHover(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult { + const range = document.getWordRangeAtPosition(position, /\w+/); + if (!range || document.getText(range) !== "main") { + return undefined; + } + + const line = document.lineAt(position); + if (MAIN_METHOD_REGEX.test(line.text.trim()) && this.isMainMethod(line.text.trim())) { + const commands: Command[] = [ + { + title: "Run", + command: JAVA_HOVER_RUN_COMMAND, + tooltip: "Run Java Program", + arguments: [ true, document.uri.toString(), { line: position.line, character: position.character }], + }, + { + title: "Debug", + command: JAVA_HOVER_RUN_COMMAND, + tooltip: "Debug Java Program", + arguments: [ false, document.uri.toString(), { line: position.line, character: position.character }], + }, + ]; + const contributed = new MarkdownString(commands.map((command) => this.convertCommandToMarkdown(command)).join(" | ")); + contributed.isTrusted = true; + return new Hover(contributed); + } + + return undefined; + } + + private isMainMethod(line: string): boolean { + const modifier: string = line.substring(0, line.indexOf("main")); + const modifiers: string[] = modifier.split(/\s+/); + return modifiers.indexOf("public") >= 0 && modifiers.indexOf("static") >= 0; + } + + private convertCommandToMarkdown(command: Command): string { + return `[${command.title}](command:${command.command}?` + + `${encodeURIComponent(JSON.stringify(command.arguments || []))} "${command.tooltip || command.command}")`; + } +} diff --git a/src/javaDebugAdapterDescriptorFactory.ts b/src/javaDebugAdapterDescriptorFactory.ts new file mode 100644 index 00000000..99bd78c0 --- /dev/null +++ b/src/javaDebugAdapterDescriptorFactory.ts @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { DebugAdapterDescriptor, DebugAdapterDescriptorFactory, DebugAdapterExecutable, DebugAdapterServer, DebugSession } from "vscode"; +import { Type } from "./javaLogger"; +import { startDebugSession } from "./languageServerPlugin"; +import { convertErrorToMessage, showErrorMessageWithTroubleshooting } from "./utility"; + +export class JavaDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { + public async createDebugAdapterDescriptor(_session: DebugSession, + _executable: DebugAdapterExecutable): Promise { + let error: Error| undefined; + try { + const debugServerPort = (await startDebugSession()); + if (debugServerPort) { + return new DebugAdapterServer(debugServerPort); + } else { + // Information for diagnostic: + // tslint:disable-next-line:no-console + console.log("Cannot find a port for debugging session"); + } + } catch (err) { + error = err; + } + + const message = error ? convertErrorToMessage(error) : { + type: Type.EXCEPTION, + message: "Failed to start debug server.", + }; + showErrorMessageWithTroubleshooting(message); + return undefined; + } +} diff --git a/src/javaLogger.ts b/src/javaLogger.ts new file mode 100644 index 00000000..a7631d32 --- /dev/null +++ b/src/javaLogger.ts @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { sendInfo, sendOperationError } from "vscode-extension-telemetry-wrapper"; + +export enum Type { + EXCEPTION = "exception", + USAGEDATA = "usageData", + USAGEERROR = "usageError", + ACTIVATEEXTENSION = "activateExtension", // TODO: Activation belongs to usage data, remove this category. +} + +export function logJavaException(errorProperties: any): void { + /** + * A sample errorProperties from Java code. + * { + * "description": "Failed to attach to remote debuggee VM. Reason: java.net.ConnectException: Connection refused: connect", + * "message": "Failed to attach to remote debuggee VM. Reason: java.net.ConnectException: Connection refused: connect", + * "stackTrace": "[{\"declaringClass\":\"com.microsoft.java.debug.core.adapter.AdapterUtils\", ...]", + * "debugSessionid": "5680f12b-5b5f-4ac0-bda3-d1dbc3c12c10", + * } + */ + const { debugSessionId, description, message, stackTrace } = errorProperties; + sendOperationError(debugSessionId, "debugSession", { + name: "JavaException", + message: description || message, + stack: stackTrace, + }); +} + +export function logJavaInfo(commonProperties: any, measureProperties?: any): void { + if (measureProperties && measureProperties.duration !== undefined) { + sendInfo(commonProperties.debugSessionId, commonProperties, measureProperties); + } else { + sendInfo(commonProperties.debugSessionId, commonProperties); + } +} diff --git a/src/languageModelTool.ts b/src/languageModelTool.ts new file mode 100644 index 00000000..ad803d25 --- /dev/null +++ b/src/languageModelTool.ts @@ -0,0 +1,1577 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as fs from 'fs'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { sendError, sendInfo } from "vscode-extension-telemetry-wrapper"; + +// ============================================================================ +// Constants +// ============================================================================ +const CONSTANTS = { + /** Timeout for waitForSession mode (ms) */ + SESSION_WAIT_TIMEOUT: 45000, + /** Maximum wait time for smart polling (ms) */ + SMART_POLLING_MAX_WAIT: 15000, + /** Interval between polling checks (ms) */ + SMART_POLLING_INTERVAL: 300, + /** Timeout for build tasks (ms) */ + BUILD_TIMEOUT: 60000, + /** Maximum number of Java files to check for compilation errors */ + MAX_JAVA_FILES_TO_CHECK: 100, + /** Default stack trace depth */ + DEFAULT_STACK_DEPTH: 50, + /** Maximum depth for recursive file search */ + MAX_FILE_SEARCH_DEPTH: 10 +}; + +interface DebugJavaApplicationInput { + target: string; + workspacePath: string; + args?: string[]; + skipBuild?: boolean; + classpath?: string; + waitForSession?: boolean; +} + +interface DebugJavaApplicationResult { + success: boolean; + message: string; + terminalName?: string; + status?: 'started' | 'timeout' | 'sent'; // More specific status + sessionId?: string; // Session ID if detected +} + +// Type definitions for Language Model API (these will be in future VS Code versions) +// For now, we use 'any' to allow compilation with older VS Code types +interface LanguageModelTool { + invoke(options: { input: T }, token: vscode.CancellationToken): Promise; +} + +/** + * Registers the Language Model Tool for debugging Java applications. + * This allows AI assistants to help users debug Java code by invoking the debugjava command. + */ +export function registerLanguageModelTool(context: vscode.ExtensionContext): vscode.Disposable | undefined { + // Check if the Language Model API is available + const lmApi = (vscode as any).lm; + if (!lmApi || typeof lmApi.registerTool !== 'function') { + // Language Model API not available in this VS Code version + return undefined; + } + + const tool: LanguageModelTool = { + async invoke(options: { input: DebugJavaApplicationInput }, token: vscode.CancellationToken): Promise { + sendInfo('', { + operationName: 'languageModelTool.debugJavaApplication.invoke', + target: options.input.target, + skipBuild: options.input.skipBuild?.toString() || 'false', + }); + + try { + const result = await debugJavaApplication(options.input, token); + + // Format the message for AI - use simple text, not JSON + const message = result.success + ? `✓ ${result.message}` + : `✗ ${result.message}`; + + // Return result in the expected format - simple text part + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(message) + ]); + } catch (error) { + sendError(error as Error); + + const errorMessage = error instanceof Error ? error.message : String(error); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Debug failed: ${errorMessage}`) + ]); + } + } + }; + + const disposable = lmApi.registerTool('debug_java_application', tool); + context.subscriptions.push(disposable); + return disposable; +} + +/** + * Main function to debug a Java application. + * This function handles: + * 1. Cleanup any existing debug session (to avoid port conflicts) + * 2. Project type detection + * 3. Building the project if needed + * 4. Executing the debugjava command + */ +async function debugJavaApplication( + input: DebugJavaApplicationInput, + token: vscode.CancellationToken +): Promise { + if (token.isCancellationRequested) { + return { + success: false, + message: 'Operation cancelled by user' + }; + } + + // Step 0: Cleanup any existing Java debug session to avoid port conflicts + const existingSession = vscode.debug.activeDebugSession; + if (existingSession && existingSession.type === 'java') { + sendInfo('', { + operationName: 'languageModelTool.cleanupExistingSession', + sessionId: existingSession.id, + sessionName: existingSession.name + }); + try { + await vscode.debug.stopDebugging(existingSession); + // Give VS Code a moment to clean up the session + await new Promise(resolve => setTimeout(resolve, 500)); + } catch (error) { + // Log but continue - the old session might already be dead + sendInfo('', { + operationName: 'languageModelTool.cleanupExistingSessionFailed', + error: String(error) + }); + } + } + + // Also close any existing "Java Debug" terminals to avoid confusion + for (const existingTerminal of vscode.window.terminals) { + if (existingTerminal.name === 'Java Debug') { + existingTerminal.dispose(); + } + } + + // Validate workspace path + const workspaceUri = vscode.Uri.file(input.workspacePath); + if (!fs.existsSync(input.workspacePath)) { + return { + success: false, + message: `Workspace path does not exist: ${input.workspacePath}` + }; + } + + // Step 1: Detect project type + const projectType = detectProjectType(input.workspacePath); + + // Step 2: Build the project if needed + if (!input.skipBuild) { + const buildResult = await buildProject(workspaceUri, projectType, token); + if (!buildResult.success) { + return buildResult; + } + } + + // Step 3: Construct and execute the debugjava command + const debugCommand = constructDebugCommand(input, projectType); + + // Validate that we can construct a valid command + if (!debugCommand || debugCommand === 'debugjava') { + return { + success: false, + message: 'Failed to construct debug command. Please check the target parameter.' + }; + } + + // Step 4: Execute in terminal and optionally wait for debug session + const terminal = vscode.window.createTerminal({ + name: 'Java Debug', + cwd: input.workspacePath, + hideFromUser: false, + isTransient: false // Keep terminal alive even after process exits + }); + + terminal.show(); + + // Build info message for AI + let targetInfo = input.target; + let warningNote = ''; + + if (input.target.endsWith('.jar')) { + targetInfo = input.target; + } else if (input.target.includes('.')) { + targetInfo = input.target; + } else { + // Simple class name - check if we successfully detected the full name + const detectedClassName = findFullyQualifiedClassName(input.workspacePath, input.target, projectType); + if (detectedClassName) { + targetInfo = `${detectedClassName} (detected from ${input.target})`; + } else { + targetInfo = input.target; + warningNote = ' ⚠️ Note: Could not auto-detect package name. If you see "ClassNotFoundException", please provide the fully qualified class name (e.g., "com.example.App" instead of "App").'; + } + } + + // If waitForSession is true, wait for the debug session to start + if (input.waitForSession) { + return new Promise((resolve) => { + let sessionStarted = false; + + // Listen for debug session start + const sessionDisposable = vscode.debug.onDidStartDebugSession((session) => { + if (session.type === 'java' && !sessionStarted) { + sessionStarted = true; + sessionDisposable.dispose(); + if (timeoutHandle) { + clearTimeout(timeoutHandle); + } + + sendInfo('', { + operationName: 'languageModelTool.debugSessionStarted.eventBased', + sessionId: session.id, + sessionName: session.name + }); + + resolve({ + success: true, + status: 'started', + sessionId: session.id, + message: `✓ Debug session started for ${targetInfo}. Session ID: ${session.id}. The debugger is now attached and ready. Any breakpoints you set will be active.${warningNote}`, + terminalName: terminal.name + }); + } + }); + + // Send the command after setting up the listener + terminal.sendText(debugCommand); + + // Set a timeout for large applications + const timeoutHandle = setTimeout(() => { + if (!sessionStarted) { + sessionDisposable.dispose(); + + sendInfo('', { + operationName: 'languageModelTool.debugSessionTimeout.eventBased', + target: targetInfo + }); + + resolve({ + success: false, + status: 'timeout', + message: `❌ Debug session failed to start within ${CONSTANTS.SESSION_WAIT_TIMEOUT / 1000} seconds for ${targetInfo}.\n\n` + + `This usually indicates a problem:\n` + + `• Compilation errors preventing startup\n` + + `• ClassNotFoundException or NoClassDefFoundError\n` + + `• Application crashed during initialization\n` + + `• Incorrect main class or classpath configuration\n\n` + + `Action required:\n` + + `1. Check terminal '${terminal.name}' for error messages\n` + + `2. Verify the target class name is correct\n` + + `3. Ensure the project is compiled successfully\n` + + `4. Use get_debug_session_info() to confirm session status${warningNote}`, + terminalName: terminal.name + }); + } + }, CONSTANTS.SESSION_WAIT_TIMEOUT); + }); + } else { + // Default behavior: send command and use smart polling to detect session start + terminal.sendText(debugCommand); + + // Smart polling to detect session start + const maxWaitTime = CONSTANTS.SMART_POLLING_MAX_WAIT; + const pollInterval = CONSTANTS.SMART_POLLING_INTERVAL; + const startTime = Date.now(); + + while (Date.now() - startTime < maxWaitTime) { + // Check if debug session has started + const session = vscode.debug.activeDebugSession; + if (session && session.type === 'java') { + const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1); + + sendInfo('', { + operationName: 'languageModelTool.debugSessionDetected', + sessionId: session.id, + elapsedTime + }); + + return { + success: true, + status: 'started', + sessionId: session.id, + message: `✓ Debug session started for ${targetInfo} (detected in ${elapsedTime}s). Session ID: ${session.id}. The debugger is attached and ready.${warningNote}`, + terminalName: terminal.name + }; + } + + // Wait before next check + await new Promise(resolve => setTimeout(resolve, pollInterval)); + } + + // Timeout: session not detected within 15 seconds + sendInfo('', { + operationName: 'languageModelTool.debugSessionTimeout.smartPolling', + target: targetInfo, + maxWaitTime + }); + + return { + success: true, + status: 'timeout', + message: `⚠️ Debug command sent for ${targetInfo}, but session not detected within ${CONSTANTS.SMART_POLLING_MAX_WAIT / 1000} seconds.\n\n` + + `Possible reasons:\n` + + `• Application is still starting (large projects may take longer)\n` + + `• Compilation errors (check terminal '${terminal.name}' for errors)\n` + + `• Application may have started and already terminated\n\n` + + `Next steps:\n` + + `• Use get_debug_session_info() to check if session is now active\n` + + `• Check terminal '${terminal.name}' for error messages\n` + + `• If starting slowly, wait a bit longer and check again${warningNote}`, + terminalName: terminal.name + }; + } +} + +/** + * Detects the type of Java project based on build files present. + */ +function detectProjectType(workspacePath: string): 'maven' | 'gradle' | 'vscode' | 'unknown' { + if (fs.existsSync(path.join(workspacePath, 'pom.xml'))) { + return 'maven'; + } + + if (fs.existsSync(path.join(workspacePath, 'build.gradle')) || + fs.existsSync(path.join(workspacePath, 'build.gradle.kts'))) { + return 'gradle'; + } + + // Check if VS Code Java extension is likely managing compilation + const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(workspacePath)); + if (workspaceFolder) { + const javaExt = vscode.extensions.getExtension('redhat.java'); + if (javaExt?.isActive) { + return 'vscode'; + } + } + + return 'unknown'; +} + +/** + * Builds the Java project based on its type. + */ +async function buildProject( + workspaceUri: vscode.Uri, + projectType: 'maven' | 'gradle' | 'vscode' | 'unknown', + _token: vscode.CancellationToken +): Promise { + switch (projectType) { + case 'maven': + return buildMavenProject(workspaceUri); + + case 'gradle': + return buildGradleProject(workspaceUri); + + case 'vscode': + return ensureVSCodeCompilation(workspaceUri); + + case 'unknown': + // Try to proceed anyway - user might have manually compiled + return { + success: true, + message: 'Unknown project type. Skipping build step. Ensure your Java files are compiled.' + }; + } +} + +/** + * Executes a shell task and waits for completion. + * This is a common function used by both Maven and Gradle builds. + */ +async function executeShellTask( + workspaceUri: vscode.Uri, + taskId: string, + taskName: string, + command: string, + successMessage: string, + timeoutMessage: string, + failureMessagePrefix: string +): Promise { + return new Promise((resolve) => { + const workspaceFolder = vscode.workspace.getWorkspaceFolder(workspaceUri); + if (!workspaceFolder) { + resolve({ + success: false, + message: `Cannot find workspace folder for ${workspaceUri.fsPath}` + }); + return; + } + + const task = new vscode.Task( + { type: 'shell', task: taskId }, + workspaceFolder, + taskName, + 'Java Debug', + new vscode.ShellExecution(command, { cwd: workspaceUri.fsPath }) + ); + + let resolved = false; + let taskDisposable: vscode.Disposable | undefined; + let errorDisposable: vscode.Disposable | undefined; + + const cleanup = () => { + clearTimeout(timeoutHandle); + taskDisposable?.dispose(); + errorDisposable?.dispose(); + }; + + // Set a timeout to avoid hanging indefinitely + const timeoutHandle = setTimeout(() => { + if (!resolved) { + resolved = true; + cleanup(); + resolve({ + success: true, + message: timeoutMessage + }); + } + }, CONSTANTS.BUILD_TIMEOUT); + + vscode.tasks.executeTask(task).then( + (execution) => { + taskDisposable = vscode.tasks.onDidEndTask((e) => { + if (e.execution === execution && !resolved) { + resolved = true; + cleanup(); + resolve({ + success: true, + message: successMessage + }); + } + }); + + errorDisposable = vscode.tasks.onDidEndTaskProcess((e) => { + if (e.execution === execution && e.exitCode !== 0 && !resolved) { + resolved = true; + cleanup(); + resolve({ + success: false, + message: `${failureMessagePrefix} with exit code ${e.exitCode}. Please check the terminal output.` + }); + } + }); + }, + (error: Error) => { + if (!resolved) { + resolved = true; + cleanup(); + resolve({ + success: false, + message: `Failed to execute task: ${error.message}` + }); + } + } + ); + }); +} + +/** + * Builds a Maven project using mvn compile. + */ +async function buildMavenProject( + workspaceUri: vscode.Uri +): Promise { + return executeShellTask( + workspaceUri, + 'maven-compile', + 'Maven Compile', + 'mvn compile', + 'Maven project compiled successfully', + 'Maven compile command sent. Build may still be in progress.', + 'Maven build failed' + ); +} + +/** + * Builds a Gradle project using gradle classes. + */ +async function buildGradleProject( + workspaceUri: vscode.Uri +): Promise { + const gradleWrapper = process.platform === 'win32' ? 'gradlew.bat' : './gradlew'; + const gradleCommand = fs.existsSync(path.join(workspaceUri.fsPath, gradleWrapper)) + ? gradleWrapper + : 'gradle'; + + return executeShellTask( + workspaceUri, + 'gradle-classes', + 'Gradle Classes', + `${gradleCommand} classes`, + 'Gradle project compiled successfully', + 'Gradle compile command sent. Build may still be in progress.', + 'Gradle build failed' + ); +} + +/** + * Ensures VS Code Java Language Server has compiled the files. + */ +async function ensureVSCodeCompilation(workspaceUri: vscode.Uri): Promise { + try { + // Check for compilation errors using VS Code diagnostics + const javaFiles = await vscode.workspace.findFiles( + new vscode.RelativePattern(workspaceUri, '**/*.java'), + '**/node_modules/**', + CONSTANTS.MAX_JAVA_FILES_TO_CHECK + ); + + let hasErrors = false; + for (const file of javaFiles) { + const diagnostics = vscode.languages.getDiagnostics(file); + const errors = diagnostics.filter(d => d.severity === vscode.DiagnosticSeverity.Error); + if (errors.length > 0) { + hasErrors = true; + break; + } + } + + if (hasErrors) { + return { + success: false, + message: 'Compilation errors detected in the project. Please fix the errors before debugging.' + }; + } + + // Check if Java extension is active and in standard mode + const javaExt = vscode.extensions.getExtension('redhat.java'); + if (!javaExt?.isActive) { + return { + success: true, + message: 'Java Language Server is not active. Proceeding with debug, but ensure your code is compiled.' + }; + } + + return { + success: true, + message: 'VS Code Java compilation verified' + }; + } catch (error) { + // If we can't verify, proceed anyway + return { + success: true, + message: 'Unable to verify compilation status. Proceeding with debug.' + }; + } +} + +/** + * Constructs the debugjava command based on input parameters. + */ +function constructDebugCommand( + input: DebugJavaApplicationInput, + projectType: 'maven' | 'gradle' | 'vscode' | 'unknown' +): string { + let command = 'debugjava'; + + // Handle JAR files + if (input.target.endsWith('.jar')) { + command += ` -jar ${input.target}`; + } + // Handle raw java command arguments (starts with - like -cp, -jar, etc) + else if (input.target.startsWith('-')) { + command += ` ${input.target}`; + } + // Handle class name (with or without package) + else { + let className = input.target; + + // If target doesn't contain a dot and we can find the Java file, + // try to detect the fully qualified class name + if (!input.target.includes('.')) { + const detectedClassName = findFullyQualifiedClassName(input.workspacePath, input.target, projectType); + if (detectedClassName) { + sendInfo('', { + operationName: 'languageModelTool.classNameDetection', + simpleClassName: input.target, + detectedClassName, + projectType + }); + className = detectedClassName; + } else { + // No package detected - class is in default package + sendInfo('', { + operationName: 'languageModelTool.classNameDetection.noPackage', + simpleClassName: input.target, + projectType + }); + } + } + + // Use provided classpath if available, otherwise infer it + const classpath = input.classpath || inferClasspath(input.workspacePath, projectType); + + command += ` -cp "${classpath}" ${className}`; + } + + // Add arguments if provided + if (input.args && input.args.length > 0) { + command += ' ' + input.args.join(' '); + } + + return command; +} + +/** + * Tries to find the fully qualified class name by searching for the Java file. + * This helps when user provides just "App" instead of "com.example.App". + */ +function findFullyQualifiedClassName( + workspacePath: string, + simpleClassName: string, + projectType: 'maven' | 'gradle' | 'vscode' | 'unknown' +): string | null { + // Determine source directories based on project type + const sourceDirs: string[] = []; + + switch (projectType) { + case 'maven': + sourceDirs.push(path.join(workspacePath, 'src', 'main', 'java')); + break; + case 'gradle': + sourceDirs.push(path.join(workspacePath, 'src', 'main', 'java')); + break; + case 'vscode': + sourceDirs.push(path.join(workspacePath, 'src')); + break; + case 'unknown': + // Try all common locations + sourceDirs.push( + path.join(workspacePath, 'src', 'main', 'java'), + path.join(workspacePath, 'src'), + workspacePath + ); + break; + } + + // Search for the Java file + for (const srcDir of sourceDirs) { + if (!fs.existsSync(srcDir)) { + continue; + } + + try { + const javaFile = findJavaFile(srcDir, simpleClassName, 0); + if (javaFile) { + // Extract package name from the file + const packageName = extractPackageName(javaFile); + if (packageName) { + return `${packageName}.${simpleClassName}`; + } else { + // No package, use simple name + return simpleClassName; + } + } + } catch (error) { + // Continue searching in other directories + } + } + + return null; +} + +/** + * Recursively searches for a Java file with the given class name. + * @param depth Current recursion depth (for limiting search depth) + */ +function findJavaFile(dir: string, className: string, depth: number = 0): string | null { + // Limit recursion depth to prevent performance issues + if (depth > CONSTANTS.MAX_FILE_SEARCH_DEPTH) { + return null; + } + + try { + const files = fs.readdirSync(dir); + + for (const file of files) { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + // Skip common non-source directories + if (file === 'node_modules' || file === '.git' || file === 'target' || file === 'build') { + continue; + } + const found = findJavaFile(filePath, className, depth + 1); + if (found) { + return found; + } + } else if (file === `${className}.java`) { + return filePath; + } + } + } catch (error) { + // Ignore permission errors or other file system issues + } + + return null; +} + +/** + * Extracts the package name from a Java source file. + */ +function extractPackageName(javaFilePath: string): string | null { + try { + const content = fs.readFileSync(javaFilePath, 'utf-8'); + const packageMatch = content.match(/^\s*package\s+([\w.]+)\s*;/m); + return packageMatch ? packageMatch[1] : null; + } catch (error) { + return null; + } +} + +/** + * Checks if a directory contains any .class files. + * @param depth Current recursion depth (for limiting search depth) + */ +function hasClassFiles(dir: string, depth: number = 0): boolean { + // Limit recursion depth to prevent performance issues + if (depth > CONSTANTS.MAX_FILE_SEARCH_DEPTH) { + return false; + } + + try { + const files = fs.readdirSync(dir); + for (const file of files) { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isFile() && file.endsWith('.class')) { + return true; + } else if (stat.isDirectory()) { + if (hasClassFiles(filePath, depth + 1)) { + return true; + } + } + } + } catch (error) { + // Ignore errors + } + return false; +} + +/** + * Infers the classpath based on project type and common conventions. + */ +function inferClasspath(workspacePath: string, projectType: 'maven' | 'gradle' | 'vscode' | 'unknown'): string { + const classpaths: string[] = []; + + switch (projectType) { + case 'maven': + // Maven standard output directory + const mavenTarget = path.join(workspacePath, 'target', 'classes'); + if (fs.existsSync(mavenTarget)) { + classpaths.push(mavenTarget); + } + break; + + case 'gradle': + // Gradle standard output directories + const gradleMain = path.join(workspacePath, 'build', 'classes', 'java', 'main'); + if (fs.existsSync(gradleMain)) { + classpaths.push(gradleMain); + } + break; + + case 'vscode': + // VS Code Java extension default output + const vscodeOut = path.join(workspacePath, 'bin'); + if (fs.existsSync(vscodeOut)) { + classpaths.push(vscodeOut); + } + break; + } + + // Fallback to common locations + if (classpaths.length === 0) { + const commonPaths = [ + path.join(workspacePath, 'bin'), // VS Code default + path.join(workspacePath, 'out'), // IntelliJ default + path.join(workspacePath, 'target', 'classes'), // Maven + path.join(workspacePath, 'build', 'classes', 'java', 'main'), // Gradle + path.join(workspacePath, 'build', 'classes'), + ]; + + // Check each common path + for (const p of commonPaths) { + if (fs.existsSync(p)) { + // Check if there are actually .class files in this directory + if (hasClassFiles(p)) { + classpaths.push(p); + break; + } + } + } + } + + // If still no classpath found, use current directory + // This is common for simple projects where .class files are alongside .java files + if (classpaths.length === 0) { + classpaths.push('.'); + } + + return classpaths.join(path.delimiter); +} + +// ============================================================================ +// Debug Session Control Tools +// ============================================================================ + +interface SetBreakpointInput { + filePath: string; + lineNumber: number; + condition?: string; + hitCondition?: string; + logMessage?: string; +} + +interface StepOperationInput { + operation: 'stepIn' | 'stepOut' | 'stepOver' | 'continue' | 'pause'; + threadId?: number; +} + +interface GetVariablesInput { + threadId?: number; + frameId?: number; + scopeType?: 'local' | 'static' | 'all'; + filter?: string; +} + +interface GetStackTraceInput { + threadId?: number; + maxDepth?: number; +} + +interface EvaluateExpressionInput { + expression: string; + threadId?: number; + frameId?: number; + context?: 'watch' | 'repl' | 'hover'; +} + +interface RemoveBreakpointsInput { + filePath?: string; + lineNumber?: number; +} + +interface StopDebugSessionInput { + reason?: string; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +type GetDebugSessionInfoInput = Record; + +/** + * Result of finding a suspended thread + */ +interface SuspendedThreadInfo { + threadId: number; + frameId: number; +} + +/** + * Finds the first suspended thread in the debug session. + * Returns the thread ID and top frame ID, or null if no suspended thread is found. + */ +async function findFirstSuspendedThread(session: vscode.DebugSession): Promise { + try { + const threadsResponse = await session.customRequest('threads'); + for (const thread of threadsResponse.threads || []) { + try { + const stackResponse = await session.customRequest('stackTrace', { + threadId: thread.id, + startFrame: 0, + levels: 1 + }); + if (stackResponse?.stackFrames?.length > 0) { + return { + threadId: thread.id, + frameId: stackResponse.stackFrames[0].id + }; + } + } catch { + // Thread is running, continue to next + continue; + } + } + } catch { + // Failed to get threads + } + return null; +} + +/** + * Registers all debug session control tools + */ +export function registerDebugSessionTools(_context: vscode.ExtensionContext): vscode.Disposable[] { + const lmApi = (vscode as any).lm; + if (!lmApi || typeof lmApi.registerTool !== 'function') { + return []; + } + + const disposables: vscode.Disposable[] = []; + + // Tool 1: Set Breakpoint + const setBreakpointTool: LanguageModelTool = { + async invoke(options: { input: SetBreakpointInput }, _token: vscode.CancellationToken): Promise { + try { + const { filePath, lineNumber, condition, hitCondition, logMessage } = options.input; + + // Set breakpoint through VS Code API (no active session required) + const uri = vscode.Uri.file(filePath); + const breakpoint = new vscode.SourceBreakpoint( + new vscode.Location(uri, new vscode.Position(lineNumber - 1, 0)), + true, // enabled + condition, + hitCondition, + logMessage + ); + + vscode.debug.addBreakpoints([breakpoint]); + + const bpType = logMessage ? 'Logpoint' : 'Breakpoint'; + const session = vscode.debug.activeDebugSession; + const sessionInfo = (session && session.type === 'java') + ? ' (active in current session)' + : ' (will activate when debugging starts)'; + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `✓ ${bpType} set at ${path.basename(filePath)}:${lineNumber}${condition ? ` (condition: ${condition})` : ''}${sessionInfo}` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to set breakpoint: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('set_java_breakpoint', setBreakpointTool)); + + // Tool 2: Step Operations + const stepOperationTool: LanguageModelTool = { + async invoke(options: { input: StepOperationInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + if (!session || session.type !== 'java') { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No active Java debug session.') + ]); + } + + const { operation, threadId } = options.input; + + // Map operation to VS Code debug commands + const commandMap: { [key: string]: string } = { + stepIn: 'workbench.action.debug.stepInto', + stepOut: 'workbench.action.debug.stepOut', + stepOver: 'workbench.action.debug.stepOver', + continue: 'workbench.action.debug.continue', + pause: 'workbench.action.debug.pause' + }; + + const command = commandMap[operation]; + if (threadId !== undefined) { + // For thread-specific operations, use custom request + await session.customRequest(operation, { threadId }); + } else { + // Use VS Code command for current thread + await vscode.commands.executeCommand(command); + } + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✓ Executed ${operation}`) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Step operation failed: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('debug_step_operation', stepOperationTool)); + + // Tool 3: Get Variables + const getVariablesTool: LanguageModelTool = { + async invoke(options: { input: GetVariablesInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + if (!session || session.type !== 'java') { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No active Java debug session.') + ]); + } + + const { threadId, frameId = 0, scopeType = 'all', filter } = options.input; + + // Find the target thread - either specified or find first suspended thread + let targetThreadId = threadId; + if (!targetThreadId) { + const suspendedThread = await findFirstSuspendedThread(session); + if (suspendedThread) { + targetThreadId = suspendedThread.threadId; + } + } + + if (!targetThreadId) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No suspended thread found. Use get_debug_threads() to see thread states.') + ]); + } + + // Get stack trace to access frame + const stackResponse = await session.customRequest('stackTrace', { + threadId: targetThreadId, + startFrame: frameId, + levels: 1 + }); + + if (!stackResponse.stackFrames || stackResponse.stackFrames.length === 0) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No stack frame available.') + ]); + } + + const frame = stackResponse.stackFrames[0]; + + // Get scopes for the frame + const scopesResponse = await session.customRequest('scopes', { frameId: frame.id }); + + const variables: string[] = []; + for (const scope of scopesResponse.scopes) { + // Filter by scope type + if (scopeType === 'local' && scope.name !== 'Local' && scope.name !== 'Locals') { + continue; + } + if (scopeType === 'static' && scope.name !== 'Static') { + continue; + } + + // Get variables for this scope + const varsResponse = await session.customRequest('variables', { + variablesReference: scope.variablesReference + }); + + for (const v of varsResponse.variables) { + if (!filter || v.name.includes(filter) || matchWildcard(v.name, filter)) { + variables.push(`${v.name}: ${v.type || ''} = ${v.value}`); + } + } + } + + if (variables.length === 0) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('No variables found.') + ]); + } + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `Variables (Thread #${targetThreadId}, Frame ${frameId}):\n${variables.join('\n')}` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to get variables: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('get_debug_variables', getVariablesTool)); + + // Tool 4: Get Stack Trace + const getStackTraceTool: LanguageModelTool = { + async invoke(options: { input: GetStackTraceInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + if (!session || session.type !== 'java') { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No active Java debug session.') + ]); + } + + const { threadId, maxDepth = CONSTANTS.DEFAULT_STACK_DEPTH } = options.input; + + const stackResponse = await session.customRequest('stackTrace', { + threadId: threadId || (session as any).threadId || 1, + startFrame: 0, + levels: maxDepth + }); + + if (!stackResponse.stackFrames || stackResponse.stackFrames.length === 0) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('No stack frames available.') + ]); + } + + const frames = stackResponse.stackFrames.map((frame: any, index: number) => { + const location = frame.source ? + `${frame.source.name}:${frame.line}` : + 'unknown location'; + return `#${index} ${frame.name} at ${location}`; + }); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `Call Stack:\n${frames.join('\n')}` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to get stack trace: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('get_debug_stack_trace', getStackTraceTool)); + + // Tool 5: Evaluate Expression + const evaluateExpressionTool: LanguageModelTool = { + async invoke(options: { input: EvaluateExpressionInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + if (!session || session.type !== 'java') { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No active Java debug session.') + ]); + } + + const { expression, threadId, frameId = 0, context = 'repl' } = options.input; + + // Find the target thread and frame for evaluation + let targetFrameId: number = frameId; + let targetThreadId = threadId; + + // If no threadId specified, find first suspended thread + if (!targetThreadId) { + const suspendedThread = await findFirstSuspendedThread(session); + if (suspendedThread) { + targetThreadId = suspendedThread.threadId; + // Use the actual frame ID from the stack if frameId is 0 + if (frameId === 0) { + targetFrameId = suspendedThread.frameId; + } + } + } else { + // Get the frame ID for the specified thread + try { + const stackResponse = await session.customRequest('stackTrace', { + threadId: targetThreadId, + startFrame: frameId, + levels: 1 + }); + if (stackResponse?.stackFrames?.length > 0) { + targetFrameId = stackResponse.stackFrames[0].id; + } + } catch { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Thread #${targetThreadId} is not suspended. Cannot evaluate expression.`) + ]); + } + } + + if (!targetThreadId) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No suspended thread found. Use get_debug_threads() to see thread states.') + ]); + } + + const evalResponse = await session.customRequest('evaluate', { + expression, + frameId: targetFrameId, + context + }); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `Expression: ${expression}\n` + + `Thread: #${targetThreadId}\n` + + `Result: ${evalResponse.result}${evalResponse.type ? ` (${evalResponse.type})` : ''}` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Evaluation failed: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('evaluate_debug_expression', evaluateExpressionTool)); + + // Tool 6: Get Threads + const getThreadsTool: LanguageModelTool<{}> = { + async invoke(_options: { input: {} }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + if (!session || session.type !== 'java') { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('✗ No active Java debug session.') + ]); + } + + const threadsResponse = await session.customRequest('threads'); + + if (!threadsResponse.threads || threadsResponse.threads.length === 0) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('No threads found.') + ]); + } + + // Check each thread's state by trying to get its stack trace + const threadInfos: string[] = []; + for (const thread of threadsResponse.threads) { + let state = '🟢 RUNNING'; + let location = ''; + + try { + const stackResponse = await session.customRequest('stackTrace', { + threadId: thread.id, + startFrame: 0, + levels: 1 + }); + + if (stackResponse?.stackFrames?.length > 0) { + state = '🔴 SUSPENDED'; + const topFrame = stackResponse.stackFrames[0]; + if (topFrame.source) { + location = ` at ${topFrame.source.name}:${topFrame.line}`; + } + } + } catch { + // Thread is running, can't get stack + state = '🟢 RUNNING'; + } + + threadInfos.push(`Thread #${thread.id}: ${thread.name} [${state}]${location}`); + } + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `═══════════════════════════════════════════\n` + + `THREADS (${threadsResponse.threads.length} total)\n` + + `═══════════════════════════════════════════\n\n` + + `${threadInfos.join('\n')}\n\n` + + `───────────────────────────────────────────\n` + + `💡 Use threadId parameter to inspect a specific thread:\n` + + `• get_debug_variables(threadId=X)\n` + + `• get_debug_stack_trace(threadId=X)\n` + + `• evaluate_debug_expression(threadId=X, expression="...")\n` + + `───────────────────────────────────────────` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to get threads: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('get_debug_threads', getThreadsTool)); + + // Tool 7: Remove Breakpoints + const removeBreakpointsTool: LanguageModelTool = { + async invoke(options: { input: RemoveBreakpointsInput }, _token: vscode.CancellationToken): Promise { + try { + const { filePath, lineNumber } = options.input; + + const breakpoints = vscode.debug.breakpoints; + + if (!filePath) { + // Remove all breakpoints (no active session required) + const count = breakpoints.length; + vscode.debug.removeBreakpoints(breakpoints); + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✓ Removed all ${count} breakpoint(s).`) + ]); + } + + const uri = vscode.Uri.file(filePath); + const toRemove = breakpoints.filter(bp => { + if (bp instanceof vscode.SourceBreakpoint) { + const match = bp.location.uri.fsPath === uri.fsPath; + if (lineNumber !== undefined) { + return match && bp.location.range.start.line === lineNumber - 1; + } + return match; + } + return false; + }); + + if (toRemove.length > 0) { + vscode.debug.removeBreakpoints(toRemove); + } + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + toRemove.length > 0 + ? `✓ Removed ${toRemove.length} breakpoint(s) from ${path.basename(filePath)}${lineNumber ? `:${lineNumber}` : ''}` + : 'No matching breakpoints found.' + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to remove breakpoints: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('remove_java_breakpoints', removeBreakpointsTool)); + + // Tool 9: Stop Debug Session + const stopDebugSessionTool: LanguageModelTool = { + async invoke(options: { input: StopDebugSessionInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + + if (!session) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('No active debug session to stop.') + ]); + } + + const sessionInfo = `${session.name} (${session.type})`; + const reason = options.input.reason || 'Investigation complete'; + + // Stop the debug session + await vscode.debug.stopDebugging(session); + + sendInfo('', { + operationName: 'languageModelTool.stopDebugSession', + sessionId: session.id, + sessionName: session.name, + reason + }); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `✓ Stopped debug session: ${sessionInfo}. Reason: ${reason}` + ) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to stop debug session: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('stop_debug_session', stopDebugSessionTool)); + + // Tool 10: Get Debug Session Info + const getDebugSessionInfoTool: LanguageModelTool = { + async invoke(_options: { input: GetDebugSessionInfoInput }, _token: vscode.CancellationToken): Promise { + try { + const session = vscode.debug.activeDebugSession; + + if (!session) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + '❌ No active debug session found.\n\n' + + 'You can:\n' + + '• Start a new debug session using debug_java_application\n' + + '• Set breakpoints before or after starting a session\n' + + '• Wait for an existing session to hit a breakpoint' + ) + ]); + } + + // Gather session information + const sessionInfo = { + id: session.id, + name: session.name, + type: session.type, + workspaceFolder: session.workspaceFolder?.name || 'N/A', + configuration: { + name: session.configuration.name, + type: session.configuration.type, + request: session.configuration.request, + mainClass: session.configuration.mainClass, + projectName: session.configuration.projectName + } + }; + + // Check if session is paused and get current location + // Strategy: Get all threads first, then try to get stack trace for each + // A thread is paused if we can successfully get its stack trace + let isPaused = false; + let stoppedReason = 'unknown'; + let currentLocation = ''; + let currentFile = ''; + let currentLine = 0; + let stoppedThreadId: number | undefined; + let stoppedThreadName = ''; + + try { + // Step 1: Get all threads + const threadsResponse = await session.customRequest('threads'); + const threads = threadsResponse?.threads || []; + + // Step 2: Try to get stack trace for each thread to find paused one + // In Java debug, only paused threads can provide stack traces + for (const thread of threads) { + try { + const stackResponse = await session.customRequest('stackTrace', { + threadId: thread.id, + startFrame: 0, + levels: 1 + }); + + // If we got stack frames, this thread is paused + if (stackResponse?.stackFrames?.length > 0) { + isPaused = true; + stoppedThreadId = thread.id; + stoppedThreadName = thread.name || `Thread-${thread.id}`; + + const topFrame = stackResponse.stackFrames[0]; + + // Extract current location details + if (topFrame.source) { + currentFile = topFrame.source.path || topFrame.source.name || 'unknown'; + currentLine = topFrame.line || 0; + const methodName = topFrame.name || 'unknown'; + const fileName = topFrame.source.name || path.basename(currentFile); + currentLocation = `${fileName}:${currentLine} in ${methodName}`; + } + + // Try to determine stop reason from thread name or default to breakpoint + stoppedReason = 'breakpoint'; + + // Found a paused thread, no need to check others for basic info + break; + } + } catch { + // This thread is running, not paused - continue to next + continue; + } + } + + // If no thread had stack frames, all are running + if (!isPaused && threads.length > 0) { + // Session exists but all threads are running + isPaused = false; + } + } catch (error) { + // If we can't even get threads, something is wrong + // But session exists, so mark as running + isPaused = false; + sendInfo('', { + operationName: 'languageModelTool.getDebugSessionInfo.threadError', + error: String(error) + }); + } + + // Build status line with location info + let statusLine: string; + let locationInfo = ''; + + if (isPaused) { + statusLine = `🔴 Status: PAUSED (${stoppedReason})`; + locationInfo = [ + '', + '📍 Current Location:', + `• File: ${currentFile}`, + `• Line: ${currentLine}`, + `• Method: ${currentLocation}`, + `• Thread: ${stoppedThreadName} (ID: ${stoppedThreadId})` + ].join('\n'); + } else { + statusLine = '🟢 Status: RUNNING'; + } + + // Build clear action guidance based on state + let actionGuidance: string; + if (isPaused) { + actionGuidance = [ + '✅ READY FOR INSPECTION - Session is paused at breakpoint', + '', + 'You can now:', + '• evaluate_debug_expression - Test your hypothesis (e.g., "user == null")', + '• get_debug_variables - Inspect specific variables', + '• get_debug_stack_trace - See full call stack', + '• debug_step_operation - Step through code (stepOver, stepIn, stepOut)', + '• debug_step_operation(continue) - Resume to next breakpoint', + '• stop_debug_session - End debugging when done' + ].join('\n'); + } else { + actionGuidance = [ + '⏳ WAITING - Session is running, not yet at breakpoint', + '', + 'The program is executing. To pause:', + '• Wait for it to hit your breakpoint', + '• Or use debug_step_operation(pause) to pause immediately', + '', + 'Inspection tools (get_debug_variables, evaluate_debug_expression) ', + 'will NOT work until the session is PAUSED.' + ].join('\n'); + } + + // Determine if this is a debugjava (No-Config) session that can be safely stopped + const isNoConfigSession = sessionInfo.name.includes('No-Config') || + sessionInfo.name.includes('debugjava'); + const launchMethod = isNoConfigSession + ? 'debugjava (No-Config) - ✅ Can be safely stopped' + : sessionInfo.configuration.request === 'attach' + ? 'External attach - ⚠️ Stopping will disconnect from process' + : 'VS Code launch - ✅ Can be safely stopped'; + + const message = [ + '═══════════════════════════════════════════', + isPaused ? '🔴 DEBUG SESSION PAUSED' : '🟢 DEBUG SESSION RUNNING', + '═══════════════════════════════════════════', + '', + statusLine, + locationInfo, + '', + '───────────────────────────────────────────', + 'Session Details:', + `• Session ID: ${sessionInfo.id}`, + `• Name: ${sessionInfo.name}`, + `• Type: ${sessionInfo.type}`, + `• Request: ${sessionInfo.configuration.request || 'N/A'}`, + `• Launch Method: ${launchMethod}`, + `• Main Class: ${sessionInfo.configuration.mainClass || 'N/A'}`, + '', + '───────────────────────────────────────────', + actionGuidance, + '═══════════════════════════════════════════' + ].join('\n'); + + sendInfo('', { + operationName: 'languageModelTool.getDebugSessionInfo', + sessionId: session.id, + sessionType: session.type, + isPaused: String(isPaused), + stoppedThreadId: String(stoppedThreadId || ''), + currentFile, + currentLine: String(currentLine) + }); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(message) + ]); + } catch (error) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to get debug session info: ${error}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('get_debug_session_info', getDebugSessionInfoTool)); + + return disposables; +} + +/** + * Simple wildcard matching helper + */ +function matchWildcard(text: string, pattern: string): boolean { + const regex = new RegExp('^' + pattern.split('*').map(escapeRegex).join('.*') + '$'); + return regex.test(text); +} + +function escapeRegex(str: string): string { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} diff --git a/src/languageServerPlugin.ts b/src/languageServerPlugin.ts new file mode 100644 index 00000000..bbafd573 --- /dev/null +++ b/src/languageServerPlugin.ts @@ -0,0 +1,154 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { Range } from "vscode-languageserver-types"; + +import * as commands from "./commands"; + +export enum CompileWorkspaceStatus { + FAILED = 0, + SUCCEED = 1, + WITHERROR = 2, + CANCELLED = 3, +} + +export interface IMainClassOption { + readonly mainClass: string; + readonly projectName?: string; + readonly filePath?: string; +} + +export interface IMainMethod extends IMainClassOption { + range: vscode.Range; +} + +export const CONFIGERROR_INVALID_CLASS_NAME = 1; +export const CONFIGERROR_MAIN_CLASS_NOT_EXIST = 2; +export const CONFIGERROR_MAIN_CLASS_NOT_UNIQUE = 3; +export const CONFIGERROR_INVALID_JAVA_PROJECT = 4; +export interface IValidationResult { + readonly isValid: boolean; + readonly message?: string; + readonly kind?: number; +} + +export interface ILaunchValidationResponse { + readonly mainClass: IValidationResult; + readonly projectName: IValidationResult; + readonly proposals?: IMainClassOption[]; +} + +export async function resolveMainMethod(uri: vscode.Uri, token?: vscode.CancellationToken): Promise { + if (token) { + return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINMETHOD, uri.toString(), token); + } + + return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINMETHOD, uri.toString()); +} + +export function startDebugSession() { + return commands.executeJavaLanguageServerCommand(commands.JAVA_START_DEBUGSESSION); +} + +export function resolveClasspath(mainClass: string, projectName: string, scope?: string) { + return commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_CLASSPATH, mainClass, projectName, scope); +} + +export function resolveMainClass(workspaceUri?: vscode.Uri): Promise { + if (workspaceUri) { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS, workspaceUri.toString()); + } + return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS); +} + +export function resolveMainClassFromProject(projectName: string): Promise { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS, projectName); +} + +export function validateLaunchConfig(mainClass: string, projectName: string, containsExternalClasspaths: boolean, workspaceUri?: vscode.Uri): + Promise { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_VALIDATE_LAUNCHCONFIG, + workspaceUri ? workspaceUri.toString() : undefined, mainClass, projectName, containsExternalClasspaths); +} + +export function inferLaunchCommandLength(config: vscode.DebugConfiguration): Promise { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_INFER_LAUNCH_COMMAND_LENGTH, JSON.stringify(config)); +} + +export function checkProjectSettings(className: string, projectName: string, inheritedOptions: boolean, expectedOptions: {[key: string]: string}): +Promise { + return >commands.executeJavaLanguageServerCommand( + commands.JAVA_CHECK_PROJECT_SETTINGS, JSON.stringify({ + className, + projectName, + inheritedOptions, + expectedOptions, + })); +} + +const COMPILER_PB_ENABLE_PREVIEW_FEATURES: string = "org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures"; +export async function detectPreviewFlag(className: string, projectName: string): Promise { + const expectedOptions = { + [COMPILER_PB_ENABLE_PREVIEW_FEATURES]: "enabled", + }; + return checkProjectSettings(className, projectName, true, expectedOptions); +} + +export function resolveElementAtSelection(uri: string, line: number, character: number): Promise { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_ELEMENT_AT_SELECTION, uri, line, character); +} + +export function resolveBuildFiles(): Promise { + return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_BUILD_FILES); +} + +export async function isOnClasspath(uri: string): Promise { + try { + return await commands.executeJavaExtensionCommand(commands.JAVA_IS_ON_CLASSPATH, uri); + } catch (error) { + return true; + } +} + +export function resolveJavaExecutable(mainClass: string, projectName: string) { + return commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_JAVAEXECUTABLE, mainClass, projectName); +} + +export function fetchPlatformSettings(): any { + return commands.executeJavaLanguageServerCommand(commands.JAVA_FETCH_PLATFORM_SETTINGS); +} + +export async function resolveClassFilters(patterns: string[]): Promise { + return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_CLASSFILTERS, ...patterns); +} + +export async function resolveSourceUri(line: string): Promise { + return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_SOURCE_URI, line); +} + +export async function resolveInlineVariables(inlineParams: InlineParams): Promise { + return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_INLINE_VARIABLES, JSON.stringify(inlineParams)); +} + +// tslint:disable-next-line:interface-name +export interface InlineParams { + uri: string; + viewPort?: Range; + stoppedLocation: Range; +} + +// tslint:disable-next-line:interface-name +export enum InlineKind { + VariableLookup = 0, + Evaluation = 1, +} + +// tslint:disable-next-line:interface-name +export interface InlineVariable { + range: Range; + name: string; + kind: InlineKind; + expression: string; + declaringClass: string; +} diff --git a/src/launchCommand.ts b/src/launchCommand.ts new file mode 100644 index 00000000..75a6d201 --- /dev/null +++ b/src/launchCommand.ts @@ -0,0 +1,199 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. +import * as cp from "child_process"; +import * as fs from "fs"; +import * as _ from "lodash"; +import * as path from "path"; +import * as vscode from "vscode"; + +import { UNSUPPORTED_CLASS_VERSION_ERROR } from "./anchor"; +import { fetchPlatformSettings, inferLaunchCommandLength } from "./languageServerPlugin"; +import { getJavaHome, showWarningMessageWithTroubleshooting } from "./utility"; + +enum shortenApproach { + none = "none", + jarmanifest = "jarmanifest", + argfile = "argfile", +} + +const HELPFUL_NPE_VMARGS = "-XX:+ShowCodeDetailsInExceptionMessages"; + +/** + * Returns the recommended approach to shorten the command line length. + * @param config the launch configuration + * @param runtimeVersion the target runtime version + */ +export async function getShortenApproachForCLI(config: vscode.DebugConfiguration, runtimeVersion: number): Promise { + const recommendedShortenApproach = runtimeVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile; + return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none; +} + +/** + * Validates whether the specified runtime version could be supported by the Java tooling. + * @param runtimeVersion the target runtime version + */ +export async function validateRuntimeCompatibility(runtimeVersion: number) { + try { + const platformSettings = await fetchPlatformSettings(); + if (platformSettings && platformSettings.latestSupportedJavaVersion) { + const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion); + if (latestSupportedVersion < runtimeVersion) { + showWarningMessageWithTroubleshooting({ + message: "The compiled classes are not compatible with the runtime JDK. To mitigate the issue, please refer to \"Learn More\".", + anchor: UNSUPPORTED_CLASS_VERSION_ERROR, + }); + } + } + } catch (err) { + // do nothing + } +} + +/** + * Add some helpful VM arguments to the launch configuration based on the target runtime version. + * @param config the launch configuration + * @param runtimeVersion the target runtime version + */ +export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration, runtimeVersion: number) { + try { + if (runtimeVersion >= 14) { + // JEP-358: https://openjdk.java.net/jeps/358 + if (config.vmArgs && config.vmArgs.indexOf(HELPFUL_NPE_VMARGS) >= 0) { + return; + } + + config.vmArgs = (config.vmArgs || "") + " " + HELPFUL_NPE_VMARGS; + } + } catch (error) { + // do nothing. + } +} + +/** + * Returns the target runtime version. If the javaExec is not specified, then return the current Java version + * that the Java tooling used. + * @param javaExec the path of the Java executable + */ +export async function getJavaVersion(javaExec: string): Promise { + javaExec = javaExec || path.join(await getJavaHome(), "bin", "java"); + let javaVersion = await checkVersionInReleaseFile(path.resolve(javaExec, "..", "..")); + if (!javaVersion) { + javaVersion = await checkVersionByCLI(javaExec); + } + return javaVersion; +} + +async function checkVersionInReleaseFile(javaHome: string): Promise { + if (!javaHome) { + return 0; + } + const releaseFile = path.join(javaHome, "release"); + if (!await fs.existsSync(releaseFile)) { + return 0; + } + + try { + const content = fs.readFileSync(releaseFile); + const regexp = /^JAVA_VERSION="(.*)"/gm; + const match = regexp.exec(content.toString()); + if (!match) { + return 0; + } + const majorVersion = flattenMajorVersion(match[1]); + return majorVersion; + } catch (error) { + // ignore + } + + return 0; +} + +/** + * Get version by parsing `JAVA_HOME/bin/java -version` + */ +async function checkVersionByCLI(javaExec: string): Promise { + if (!javaExec) { + return 0; + } + return new Promise((resolve) => { + cp.execFile(javaExec, ["-version"], {}, (_error, _stdout, stderr) => { + const regexp = /version "(.*)"/g; + const match = regexp.exec(stderr); + if (!match) { + return resolve(0); + } + const javaVersion = flattenMajorVersion(match[1]); + resolve(javaVersion); + }); + }); +} + +function flattenMajorVersion(version: string): number { + // Ignore '1.' prefix for legacy Java versions + if (version.startsWith("1.")) { + version = version.substring(2); + } + + // look into the interesting bits now + const regexp = /\d+/g; + const match = regexp.exec(version); + let javaVersion = 0; + if (match) { + javaVersion = parseInt(match[0], 10); + } + + return javaVersion; +} + +async function shouldShortenIfNecessary(config: vscode.DebugConfiguration): Promise { + const cliLength = await inferLaunchCommandLength(config); + const classPaths = config.classPaths || []; + const modulePaths = config.modulePaths || []; + const classPathLength = classPaths.join(path.delimiter).length; + const modulePathLength = modulePaths.join(path.delimiter).length; + if (!config.console || config.console === "internalConsole") { + return cliLength >= getMaxProcessCommandLineLength(config) || classPathLength >= getMaxArgLength() || modulePathLength >= getMaxArgLength(); + } else { + return classPaths.length > 1 || modulePaths.length > 1; + } +} + +function getMaxProcessCommandLineLength(config: vscode.DebugConfiguration): number { + const ARG_MAX_WINDOWS = 32768; + const ARG_MAX_MACOS = 262144; + const ARG_MAX_LINUX = 2097152; + // for Posix systems, ARG_MAX is the maximum length of argument to the exec functions including environment data. + // POSIX suggests to subtract 2048 additionally so that the process may safely modify its environment. + // see https://www.in-ulm.de/~mascheck/various/argmax/ + if (process.platform === "win32") { + // https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553/ + // On windows, the max process commmand line length is 32k (32768) characters. + return ARG_MAX_WINDOWS - 2048; + } else if (process.platform === "darwin") { + return ARG_MAX_MACOS - getEnvironmentLength(config) - 2048; + } else if (process.platform === "linux") { + return ARG_MAX_LINUX - getEnvironmentLength(config) - 2048; + } + + return Number.MAX_SAFE_INTEGER; +} + +function getEnvironmentLength(config: vscode.DebugConfiguration): number { + const env = config.env || {}; + return _.isEmpty(env) ? 0 : Object.keys(env).map((key) => strlen(key) + strlen(env[key]) + 1).reduce((a, b) => a + b); +} + +function strlen(str: string): number { + return str ? str.length : 0; +} + +function getMaxArgLength(): number { + const MAX_ARG_STRLEN_LINUX = 131072; + if (process.platform === "linux") { + // On Linux, MAX_ARG_STRLEN (kernel >= 2.6.23) is the maximum length of a command line argument (or environment variable). Its value + // cannot be changed without recompiling the kernel. + return MAX_ARG_STRLEN_LINUX - 2048; + } + + return Number.MAX_SAFE_INTEGER; +} diff --git a/src/mainClassPicker.ts b/src/mainClassPicker.ts new file mode 100644 index 00000000..d34121d5 --- /dev/null +++ b/src/mainClassPicker.ts @@ -0,0 +1,189 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as _ from "lodash"; +import * as path from "path"; +import { TextEditor, window } from "vscode"; +import { IMainClassOption } from "./languageServerPlugin"; + +const defaultLabelFormatter = (option: IMainClassOption) => { + return option.mainClass; +}; +type Formatter = (option: IMainClassOption) => string; + +class MainClassPicker { + private cache: { [key: string]: number } = {}; + + // tslint:disable-next-line + public async showQuickPick(options: IMainClassOption[], placeHolder: string): Promise; + // tslint:disable-next-line + public async showQuickPick(options: IMainClassOption[], placeHolder: string, labelFormatter: Formatter): Promise; + // tslint:disable-next-line + public async showQuickPick(options: IMainClassOption[], placeHolder: string, autoPick: boolean): Promise; + // tslint:disable-next-line + public async showQuickPick(options: IMainClassOption[], placeHolder: string, parameter3?: Formatter | boolean, + parameter4?: boolean): Promise { + let labelFormatter: Formatter = defaultLabelFormatter; + let autoPick: boolean = true; + if (typeof parameter3 === "function") { + labelFormatter = parameter3; + } else if (typeof parameter3 === "boolean") { + autoPick = parameter3; + } + if (typeof parameter4 === "boolean") { + autoPick = parameter4; + } + + if (!options || !options.length) { + return undefined; + } else if (autoPick && options.length === 1) { + return options[0]; + } + + const pickItems = options.map((option) => { + return { + label: labelFormatter(option), + description: option.filePath ? path.basename(option.filePath) : "", + detail: option.projectName ? `Project: ${option.projectName}` : "", + data: option, + }; + }); + + const selected = await window.showQuickPick(pickItems, { placeHolder }); + if (selected) { + return selected.data; + } + return undefined; + } + + // tslint:disable-next-line + public async showQuickPickWithRecentlyUsed(options: IMainClassOption[], placeHolder: string): Promise; + // tslint:disable-next-line + public async showQuickPickWithRecentlyUsed(options: IMainClassOption[], placeHolder: string, labelFormatter: Formatter): Promise; + // tslint:disable-next-line + public async showQuickPickWithRecentlyUsed(options: IMainClassOption[], placeHolder: string, autoPick: boolean): Promise; + // tslint:disable-next-line + public async showQuickPickWithRecentlyUsed(options: IMainClassOption[], placeHolder: string, parameter3?: Formatter | boolean, + parameter4?: boolean): Promise { + // Record the main class picking history in a most recently used cache. + let labelFormatter: Formatter = defaultLabelFormatter; + let autoPick: boolean = true; + if (typeof parameter3 === "function") { + labelFormatter = parameter3; + } else if (typeof parameter3 === "boolean") { + autoPick = parameter3; + } + if (typeof parameter4 === "boolean") { + autoPick = parameter4; + } + + if (!options || !options.length) { + return undefined; + } else if (autoPick && options.length === 1) { + return options[0]; + } + + // Sort the Main Class options with the recently used timestamp. + options.sort((a: IMainClassOption, b: IMainClassOption) => { + return this.getMRUTimestamp(b) - this.getMRUTimestamp(a); + }); + + const mostRecentlyUsedOption: IMainClassOption | undefined = (options.length && this.contains(options[0])) ? options[0] : undefined; + const isMostRecentlyUsed = (option: IMainClassOption): boolean => { + return !!mostRecentlyUsedOption + && mostRecentlyUsedOption.mainClass === option.mainClass + && mostRecentlyUsedOption.projectName === option.projectName; + }; + const isFromActiveEditor = (option: IMainClassOption): boolean => { + const activeEditor: TextEditor | undefined = window.activeTextEditor; + const currentActiveFile: string | undefined = _.get(activeEditor, "document.uri.fsPath"); + if (option.filePath && currentActiveFile) { + return path.relative(option.filePath, currentActiveFile) === ""; + } + return false; + }; + const isPrivileged = (option: IMainClassOption): boolean => { + return isMostRecentlyUsed(option) || isFromActiveEditor(option); + }; + + // Show the most recently used Main Class as the first one, + // then the Main Class from Active Editor as second, + // finally other Main Class. + const adjustedOptions: IMainClassOption[] = []; + options.forEach((option: IMainClassOption) => { + if (isPrivileged(option)) { + adjustedOptions.push(option); + } + }); + options.forEach((option: IMainClassOption) => { + if (!isPrivileged(option)) { + adjustedOptions.push(option); + } + }); + + const pickItems = adjustedOptions.map((option) => { + const adjustedDetail = []; + if (isMostRecentlyUsed(option)) { + adjustedDetail.push("$(clock) recently used"); + } + + if (isFromActiveEditor(option) && option.filePath) { + adjustedDetail.push(`$(file-text) active editor (${path.basename(option.filePath)})`); + } + + if (option.projectName) { + adjustedDetail.push(`Project: ${option.projectName}`); + } + + const detail: string = adjustedDetail.join(", "); + + return { + label: labelFormatter ? labelFormatter(option) : defaultLabelFormatter(option), + description: option.filePath ? path.basename(option.filePath) : "", + detail, + data: option, + }; + }); + + const selected = await window.showQuickPick(pickItems, { placeHolder }); + if (selected) { + this.updateMRUTimestamp(selected.data); + return selected.data; + } + return undefined; + } + + /** + * Checks whether the item options can be picked automatically without popping up the QuickPick box. + * @param options the item options to pick + * @param autoPick pick it automatically if only one option is available + */ + public isAutoPicked(options: IMainClassOption[], autoPick?: boolean) { + const shouldAutoPick: boolean = (autoPick === undefined ? true : !!autoPick); + if (!options || !options.length) { + return true; + } else if (shouldAutoPick && options.length === 1) { + return true; + } + + return false; + } + + private getMRUTimestamp(mainClassOption: IMainClassOption): number { + return this.cache[this.getKey(mainClassOption)] || 0; + } + + private updateMRUTimestamp(mainClassOption: IMainClassOption): void { + this.cache[this.getKey(mainClassOption)] = Date.now(); + } + + private contains(mainClassOption: IMainClassOption): boolean { + return Boolean(this.cache[this.getKey(mainClassOption)]); + } + + private getKey(mainClassOption: IMainClassOption): string { + return mainClassOption.mainClass + "|" + mainClassOption.projectName; + } +} + +export const mainClassPicker: MainClassPicker = new MainClassPicker(); diff --git a/src/noConfigDebugInit.ts b/src/noConfigDebugInit.ts new file mode 100644 index 00000000..b0da4f01 --- /dev/null +++ b/src/noConfigDebugInit.ts @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as fs from 'fs'; +import * as path from 'path'; +import * as crypto from 'crypto'; +import * as vscode from 'vscode'; + +import { sendInfo, sendError } from "vscode-extension-telemetry-wrapper"; +import { getJavaHome } from "./utility"; + +/** + * Registers the configuration-less debugging setup for the extension. + * + * This function sets up environment variables and a file system watcher to + * facilitate debugging without requiring a pre-configured launch.json file. + * + * @param envVarCollection - The collection of environment variables to be modified. + * @param extPath - The path to the extension directory. + * + * Environment Variables: + * - `VSCODE_JDWP_ADAPTER_ENDPOINTS`: Path to the file containing the debugger adapter endpoint. + * - `JAVA_TOOL_OPTIONS`: JDWP configuration for automatic debugging. + * - `PATH`: Appends the path to the noConfigScripts directory. + */ +export async function registerNoConfigDebug( + envVarCollection: vscode.EnvironmentVariableCollection, + extPath: string, +): Promise { + const collection = envVarCollection; + + // create a temp directory for the noConfigDebugAdapterEndpoints + // file path format: extPath/.noConfigDebugAdapterEndpoints/endpoint-stableWorkspaceHash.txt + let workspaceString = vscode.workspace.workspaceFile?.fsPath; + if (!workspaceString) { + workspaceString = vscode.workspace.workspaceFolders?.map((e) => e.uri.fsPath).join(';'); + } + if (!workspaceString) { + const error: Error = { + name: "NoConfigDebugError", + message: '[Java Debug] No workspace folder found', + }; + sendError(error); + return Promise.resolve(new vscode.Disposable(() => { })); + } + + // create a stable hash for the workspace folder, reduce terminal variable churn + const hash = crypto.createHash('sha256'); + hash.update(workspaceString.toString()); + const stableWorkspaceHash = hash.digest('hex').slice(0, 16); + + const tempDirPath = path.join(extPath, '.noConfigDebugAdapterEndpoints'); + const tempFilePath = path.join(tempDirPath, `endpoint-${stableWorkspaceHash}.txt`); + + // create the temp directory if it doesn't exist + if (!fs.existsSync(tempDirPath)) { + fs.mkdirSync(tempDirPath, { recursive: true }); + } else { + // remove endpoint file in the temp directory if it exists (async to avoid blocking) + if (fs.existsSync(tempFilePath)) { + fs.promises.unlink(tempFilePath).catch((err) => { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] Failed to cleanup old endpoint file: ${err}`, + }; + sendError(error); + }); + } + } + + // clear the env var collection to remove any existing env vars + collection.clear(); + + // Add env var for VSCODE_JDWP_ADAPTER_ENDPOINTS + // Note: We do NOT set JAVA_TOOL_OPTIONS globally to avoid affecting all Java processes + // (javac, maven, gradle, language server, etc.). Instead, JAVA_TOOL_OPTIONS is set + // only in the debugjava wrapper scripts (debugjava.ps1, debugjava.bat, debugjava) + collection.replace('VSCODE_JDWP_ADAPTER_ENDPOINTS', tempFilePath); + + // Try to get Java executable from Java Language Server + // This ensures we use the same Java version as the project is compiled with + try { + const javaHome = await getJavaHome(); + if (javaHome) { + const javaExec = path.join(javaHome, 'bin', 'java'); + collection.replace('VSCODE_JAVA_EXEC', javaExec); + } + } catch (error) { + // If we can't get Java from Language Server, that's okay + // The wrapper script will fall back to JAVA_HOME or PATH + } + + const noConfigScriptsDir = path.join(extPath, 'bundled', 'scripts', 'noConfigScripts'); + const pathSeparator = process.platform === 'win32' ? ';' : ':'; + + // Check if the current PATH already ends with a path separator to avoid double separators + const currentPath = process.env.PATH || ''; + const needsSeparator = currentPath.length > 0 && !currentPath.endsWith(pathSeparator); + const pathValueToAppend = needsSeparator ? `${pathSeparator}${noConfigScriptsDir}` : noConfigScriptsDir; + + collection.append('PATH', pathValueToAppend); + + // create file system watcher for the debuggerAdapterEndpointFolder for when the communication port is written + const fileSystemWatcher = vscode.workspace.createFileSystemWatcher( + new vscode.RelativePattern(tempDirPath, '**/*.txt') + ); + + // Track active debug sessions to prevent duplicates + const activeDebugSessions = new Set(); + + // Handle both file creation and modification to support multiple runs + const handleEndpointFile = async (uri: vscode.Uri) => { + const filePath = uri.fsPath; + + // Add a small delay to ensure file is fully written + // File system events can fire before write is complete + await new Promise(resolve => setTimeout(resolve, 100)); + + fs.readFile(filePath, (err, data) => { + if (err) { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: file_read_error - ${err}`, + }; + sendError(error); + return; + } + try { + // parse the client port + const dataParse = data.toString(); + const jsonData = JSON.parse(dataParse); + + // Validate JSON structure + if (!jsonData || typeof jsonData !== 'object' || !jsonData.client) { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: invalid_format - ${dataParse}`, + }; + sendError(error); + return; + } + + const clientPort = jsonData.client.port; + + // Validate port number + if (!clientPort || typeof clientPort !== 'number' || clientPort < 1 || clientPort > 65535) { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: invalid_port - ${clientPort}`, + }; + sendError(error); + return; + } + + // Check if we already have an active session for this port + if (activeDebugSessions.has(clientPort)) { + // Skip duplicate session silently - this is expected behavior + return; + } + + // Mark this port as active + activeDebugSessions.add(clientPort); + + const options: vscode.DebugSessionOptions = { + noDebug: false, + }; + + // start debug session with the client port + vscode.debug.startDebugging( + undefined, + { + type: 'java', + request: 'attach', + name: 'Attach to Java (No-Config)', + hostName: 'localhost', + port: clientPort, + }, + options, + ).then( + (started) => { + if (started) { + // Send telemetry only on successful session start with port info + sendInfo('', { message: '[Java Debug] No-config debug session started', port: clientPort }); + // Clean up the endpoint file after successful debug session start (async) + if (fs.existsSync(filePath)) { + fs.promises.unlink(filePath).catch((cleanupErr) => { + // Cleanup failure is non-critical, just log for debugging + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: cleanup_error - ${cleanupErr}`, + }; + sendError(error); + }); + } + } else { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: attach_failed - port ${clientPort}`, + }; + sendError(error); + // Remove from active sessions on failure + activeDebugSessions.delete(clientPort); + } + }, + (error) => { + const attachError: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: attach_error - port ${clientPort} - ${error}`, + }; + sendError(attachError); + // Remove from active sessions on error + activeDebugSessions.delete(clientPort); + }, + ); + } catch (parseErr) { + const error: Error = { + name: "NoConfigDebugError", + message: `[Java Debug] No-config debug failed: parse_error - ${parseErr}`, + }; + sendError(error); + } + }); + }; + + // Listen for both file creation and modification events + const fileCreationEvent = fileSystemWatcher.onDidCreate(handleEndpointFile); + const fileChangeEvent = fileSystemWatcher.onDidChange(handleEndpointFile); + + // Clean up active sessions when debug session ends + const debugSessionEndListener = vscode.debug.onDidTerminateDebugSession((session) => { + if (session.name === 'Attach to Java (No-Config)' && session.configuration.port) { + const port = session.configuration.port; + activeDebugSessions.delete(port); + // Session end is normal operation, no telemetry needed + } + }); + + return Promise.resolve( + new vscode.Disposable(() => { + fileSystemWatcher.dispose(); + fileCreationEvent.dispose(); + fileChangeEvent.dispose(); + debugSessionEndListener.dispose(); + activeDebugSessions.clear(); + }), + ); +} diff --git a/src/processPicker.ts b/src/processPicker.ts new file mode 100644 index 00000000..a9f11ff0 --- /dev/null +++ b/src/processPicker.ts @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as path from "path"; +import { window } from "vscode"; +import { getProcesses, getProcessTree } from "./processTree"; + +const JAVA_PATTERN = /(?:java|javaw|j9|j9w)$/i; +const DEBUG_MODE_PATTERN = /(-agentlib|-Xrunjdwp):\S*(address=[^\s,]+)/i; + +interface IJavaProcess { + pid: number; + command: string; + args: string; + hostName: string; + debugPort: number; +} + +function convertToJavaProcess(pid: number, command: string, args: string): IJavaProcess | undefined { + if (process.platform === "win32" && command.indexOf("\\??\\") === 0) { + // remove leading device specifier + command = command.replace("\\??\\", ""); + } + + const simpleName = path.basename(command, ".exe"); + if (JAVA_PATTERN.test(simpleName) && args) { + const match = args.match(DEBUG_MODE_PATTERN); + if (match && match.length) { + const address = match[2].split("=")[1].split(":"); + const hostName = address.length > 1 ? address[0] : "127.0.0.1"; + const debugPort = parseInt(address[address.length - 1], 10); + const exeName = path.basename(command); + const binPath = path.dirname(command); + const commandPath = path.basename(binPath) === "bin" ? + path.join(path.basename(path.dirname(binPath)), "bin", exeName) : exeName; + return { + pid, + command: commandPath, + args, + hostName, + debugPort, + }; + } + } + + return undefined; +} + +export async function pickJavaProcess(): Promise { + const javaProcesses: IJavaProcess[] = []; + try { + await getProcesses((pid: number, _ppid: number, command: string, args: string, _date: number) => { + const javaProcess = convertToJavaProcess(pid, command, args); + if (javaProcess) { + javaProcesses.push(javaProcess); + } + }); + } catch (error) { + throw new Error("Process picker failed: " + error); + } + + if (!javaProcesses.length) { + throw new Error("Process picker: Cannot find any debuggable Java process. Please make sure to use vmArgs like " + + "'-agentlib:jdwp=transport=dt_socket,server=y,address=5005' to turn on debug mode when you start your " + + "program."); + } + + const items = javaProcesses.map((process) => { + return { + label: process.command, + description: process.args, + detail: `process id: ${process.pid}, debug port: ${process.debugPort}`, + process, + }; + }); + + const pick = await window.showQuickPick(items, { + placeHolder: "Pick Java process to attach to", + }); + + if (pick) { + return pick.process; + } + + return undefined; +} + +export async function resolveJavaProcess(pid: number): Promise { + const processTree = await getProcessTree(pid); + if (!processTree || processTree.pid !== pid) { + return undefined; + } + + return convertToJavaProcess(processTree.pid, processTree.command, processTree.args); +} diff --git a/src/processTree.ts b/src/processTree.ts new file mode 100644 index 00000000..7a0840e0 --- /dev/null +++ b/src/processTree.ts @@ -0,0 +1,201 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Copied from https://github.com/microsoft/vscode-node-debug/blob/master/src/node/extension/processTree.ts + *--------------------------------------------------------------------------------------------*/ +/* tslint:disable */ +'use strict'; + +import { spawn, ChildProcessWithoutNullStreams } from 'child_process'; +import { join } from 'path'; + +export class ProcessTreeNode { + children?: ProcessTreeNode[]; + + constructor(public pid: number, public ppid: number, public command: string, public args: string) { + } +} + +export async function getProcessTree(rootPid: number) : Promise { + + const map = new Map(); + + map.set(0, new ProcessTreeNode(0, 0, '???', '')); + + try { + await getProcesses((pid: number, ppid: number, command: string, args: string) => { + if (pid !== ppid) { + map.set(pid, new ProcessTreeNode(pid, ppid, command, args)); + } + }); + } catch (err) { + return undefined; + } + + const values = map.values(); + for (const p of values) { + const parent = map.get(p.ppid); + if (parent && parent !== p) { + if (!parent.children) { + parent.children = []; + } + parent.children.push(p); + } + } + + if (!isNaN(rootPid) && rootPid > 0) { + return map.get(rootPid); + } + return map.get(0); +} + +export function getProcesses(one: (pid: number, ppid: number, command: string, args: string, date?: number) => void) : Promise { + + // returns a function that aggregates chunks of data until one or more complete lines are received and passes them to a callback. + function lines(callback: (a: string) => void) { + let unfinished = ''; // unfinished last line of chunk + return (data: string | Buffer) => { + const lines = data.toString().split(/\r?\n/); + const finishedLines = lines.slice(0, lines.length - 1); + finishedLines[0] = unfinished + finishedLines[0]; // complete previous unfinished line + unfinished = lines[lines.length - 1]; // remember unfinished last line of this chunk for next round + for (const s of finishedLines) { + callback(s); + } + }; + } + + return new Promise((resolve, reject) => { + + let proc: ChildProcessWithoutNullStreams; + + if (process.platform === 'win32') { + + // attributes columns are in alphabetic order! + const CMD_PAT = /^(.*)\s+([0-9]+)\.[0-9]+[+-][0-9]+\s+([0-9]+)\s+([0-9]+)$/; + + const wmic = join(process.env['WINDIR'] || 'C:\\Windows', 'System32', 'wbem', 'WMIC.exe'); + proc = spawn(wmic, [ 'process', 'get', 'CommandLine,CreationDate,ParentProcessId,ProcessId' ]); + proc.stdout.setEncoding('utf8'); + proc.stdout.on('data', lines(line => { + let matches = CMD_PAT.exec(line.trim()); + if (matches && matches.length === 5) { + const pid = Number(matches[4]); + const ppid = Number(matches[3]); + const date = Number(matches[2]); + let args = matches[1].trim(); + if (!isNaN(pid) && !isNaN(ppid) && args) { + let command = args; + if (args[0] === '"') { + const end = args.indexOf('"', 1); + if (end > 0) { + command = args.substr(1, end-1); + args = args.substr(end + 2); + } + } else { + const end = args.indexOf(' '); + if (end > 0) { + command = args.substr(0, end); + args = args.substr(end + 1); + } else { + args = ''; + } + } + one(pid, ppid, command, args, date); + } + } + })); + + } else if (process.platform === 'darwin') { // OS X + + proc = spawn('/bin/ps', [ '-x', '-o', `pid,ppid,comm=${'a'.repeat(256)},command` ]); + proc.stdout.setEncoding('utf8'); + proc.stdout.on('data', lines(line => { + + const pid = Number(line.substr(0, 5)); + const ppid = Number(line.substr(6, 5)); + const command = line.substr(12, 256).trim(); + const args = line.substr(269 + command.length); + + if (!isNaN(pid) && !isNaN(ppid)) { + one(pid, ppid, command, args); + } + })); + + } else { // linux + + proc = spawn('/bin/ps', [ '-ax', '-o', 'pid:6,ppid:6,comm:20,command' ]); // we specify the column width explicitly + proc.stdout.setEncoding('utf8'); + proc.stdout.on('data', lines(line => { + + // the following substr arguments must match the column width specified for the "ps" command above + // regular substr is deprecated + const pid = Number(substr(line, 0, 6)); + const ppid = Number(substr(line, 7, 6)); + const shortName = substr(line, 14, 20).trim() + const fullCommand = substr(line, 35) + + let command = shortName; + let args = fullCommand; + + const pos = fullCommand.indexOf(shortName); + if (pos >= 0) { + // binaries with spaces in path may not work + // possible solution to read directly from /proc + const commandEndPositionMaybe = fullCommand.indexOf(" ", pos + shortName.length); + const commandEndPosition = commandEndPositionMaybe < 0 ? fullCommand.length : commandEndPositionMaybe; + command = fullCommand.substring(0, commandEndPosition) + args = fullCommand.substring(commandEndPosition).trimStart() + } + + + if (!isNaN(pid) && !isNaN(ppid)) { + one(pid, ppid, command, args); + } + })); + } + + proc.on('error', err => { + reject(err); + }); + + proc.stderr.setEncoding('utf8'); + proc.stderr.on('data', data => { + const e = data.toString(); + if (e.indexOf('screen size is bogus') >= 0) { + // ignore this error silently; see https://github.com/microsoft/vscode/issues/75932 + } else { + reject(new Error(data.toString())); + } + }); + + proc.on('close', (code, signal) => { + if (code === 0) { + resolve(); + } else if (code !== null && code > 0) { + reject(new Error(`process terminated with exit code: ${code}`)); + } + if (signal) { + reject(new Error(`process terminated with signal: ${signal}`)); + } + }); + + proc.on('exit', (code, signal) => { + if (typeof code === 'number') { + if (code === 0) { + //resolve(); + } else if (code > 0) { + reject(new Error(`process terminated with exit code: ${code}`)); + } + } + if (signal) { + reject(new Error(`process terminated with signal: ${signal}`)); + } + }); + }); +} + +function substr(str: string, startIndex: number, length?: number) { + return str.slice(startIndex, length != undefined ? startIndex + length : str.length) +} diff --git a/src/progressAPI.ts b/src/progressAPI.ts new file mode 100644 index 00000000..d78581d8 --- /dev/null +++ b/src/progressAPI.ts @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { CancellationToken, ProgressLocation } from "vscode"; + +export interface IProgressReporter { + /** + * Set the job name. + * @param jobName the job name + */ + setJobName(jobName: string): void; + + /** + * Returns the id of the progress reporter. + */ + getId(): string; + + /** + * Returns the progress location. + */ + getProgressLocation(): ProgressLocation | { viewId: string }; + + /** + * Reports a progress message update. + * @param message the message to update + * @param increment use `increment` to report discrete progress. Each call with a `increment` + * value will be summed up and reflected as overall progress until 100% is reached. + * Note that currently only `ProgressLocation.Notification` is capable of showing + * discrete progress. + */ + report(message: string, increment?: number): void; + + /** + * Shows the progress reporter. + */ + show(): void; + + /** + * Hides the progress reporter. + * @param onlyNotifications only hide the progress reporter when it's shown as notification. + */ + hide(onlyNotifications?: boolean): void; + + /** + * Returns whether the progress reporter has been cancelled or completed. + */ + isCancelled(): boolean; + + /** + * Notifies the work is done that is either the task is completed or the user has cancelled it. + */ + done(): void; + + /** + * The CancellationToken to monitor if the progress reporter has been cancelled by the user. + */ + getCancellationToken(): CancellationToken; + + /** + * Disposes the progress reporter if the observed token has been cancelled. + * @param token the cancellation token to observe + */ + observe(token?: CancellationToken): void; +} + +export interface IProgressProvider { + /** + * Creates a progress reporter. + * @param jobName the job name + * @param progressLocation The location at which progress should show, defaults to `ProgressLocation.Notification`. + * @param cancellable Controls if a cancel button should show to allow the user to cancel the progress reporter, + * defaults to true. Note that currently only `ProgressLocation.Notification` is supporting + * to show a cancel button. + */ + createProgressReporter(jobName: string, progressLocation?: ProgressLocation | { viewId: string }, cancellable?: boolean): IProgressReporter; + + /** + * Returns the progress reporter with the progress id. + * @param progressId the progress id + */ + getProgressReporter(progressId: string): IProgressReporter | undefined; +} diff --git a/src/progressImpl.ts b/src/progressImpl.ts new file mode 100644 index 00000000..6ee2a98c --- /dev/null +++ b/src/progressImpl.ts @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { v4 } from "uuid"; +import { CancellationToken, CancellationTokenSource, Disposable, EventEmitter, ProgressLocation, + StatusBarAlignment, StatusBarItem, window, workspace } from "vscode"; +import { IProgressProvider, IProgressReporter } from "./progressAPI"; + +const STATUS_COMMAND: string = "java.show.server.task.status"; +class ProgressReporter implements IProgressReporter { + private _id: string = v4(); + private _jobName: string; + private _progressLocation: ProgressLocation | { viewId: string }; + private _cancellable: boolean = false; + + private _message: string; + private _increment: number | undefined; + private _isShown: boolean; + + private _tokenSource = new CancellationTokenSource(); + private _statusBarItem: StatusBarItem | undefined; + private _cancelProgressEventEmitter: EventEmitter; + private _progressEventEmitter: EventEmitter; + private _disposables: Disposable[] = []; + + constructor(jobName: string, progressLocation: ProgressLocation | { viewId: string }, cancellable: boolean) { + this._jobName = jobName; + this._progressLocation = progressLocation || ProgressLocation.Notification; + this._cancellable = cancellable; + const config = workspace.getConfiguration("java"); + if (config.silentNotification && this._progressLocation === ProgressLocation.Notification) { + this._progressLocation = ProgressLocation.Window; + } + + if (this._progressLocation === ProgressLocation.Window) { + this._statusBarItem = window.createStatusBarItem(this._id, StatusBarAlignment.Left, 1); + this._statusBarItem.name = "Progress Message for " + this._jobName; + this._statusBarItem.text = `$(sync~spin) ${this._jobName}...`; + this._statusBarItem.command = { + title: "Check Java Build Status", + command: STATUS_COMMAND, + arguments: [], + }; + this._statusBarItem.tooltip = "Check Java Build Status"; + this._disposables.push(this._statusBarItem); + } + + this._cancelProgressEventEmitter = new EventEmitter(); + this._progressEventEmitter = new EventEmitter(); + this._disposables.push(this._cancelProgressEventEmitter); + this._disposables.push(this._progressEventEmitter); + this._disposables.push(this._tokenSource); + } + + public setJobName(jobName: string): void { + this._jobName = jobName; + } + + public getId(): string { + return this._id; + } + + public getProgressLocation(): ProgressLocation | { viewId: string } { + return this._progressLocation; + } + + public report(message: string, increment?: number): void { + if (this._statusBarItem) { + const text = message ? `${this._jobName} - ${message}` : `${this._jobName}...`; + this._statusBarItem.text = `$(sync~spin) ${text}`; + } + + this._message = message; + this._increment = increment; + this._progressEventEmitter.fire(); + this.show(); + } + + public show(): void { + if (this._statusBarItem) { + this._statusBarItem.show(); + return; + } + + this.showNativeProgress(); + } + + public hide(onlyNotifications?: boolean): void { + if (onlyNotifications && this._progressLocation === ProgressLocation.Notification) { + this._cancelProgressEventEmitter.fire(); + this._isShown = false; + } + } + + public isCancelled(): boolean { + return this.getCancellationToken().isCancellationRequested; + } + + public done(): void { + this._tokenSource.cancel(); + this._cancelProgressEventEmitter.fire(); + this._statusBarItem?.hide(); + this._disposables.forEach((disposable) => disposable.dispose()); + ( progressProvider).remove(this); + } + + public getCancellationToken(): CancellationToken { + return this._tokenSource.token; + } + + public observe(token?: CancellationToken): void { + token?.onCancellationRequested(() => { + this.done(); + }); + } + + private showNativeProgress() { + if (this._isShown) { + return; + } + + this._isShown = true; + window.withProgress({ + location: this._progressLocation, + title: this._jobName ? `[${this._jobName}](command:${STATUS_COMMAND})` : undefined, + cancellable: this._cancellable, + }, (progress, token) => { + progress.report({ + message: this._message, + increment: this._increment, + }); + this.observe(token); + this._progressEventEmitter.event(() => { + progress.report({ + message: this._message, + increment: this._increment, + }); + }); + return new Promise((resolve) => { + this._cancelProgressEventEmitter.event(() => { + resolve(true); + }); + }); + }); + } +} + +class ProgressProvider implements IProgressProvider { + private store: { [key: string]: IProgressReporter } = {}; + + public createProgressReporter(jobName: string, progressLocation?: ProgressLocation | { viewId: string }, + cancellable?: boolean): IProgressReporter { + const progressReporter = new ProgressReporter(jobName, progressLocation || ProgressLocation.Notification, + cancellable === undefined ? true : !!cancellable); + this.store[progressReporter.getId()] = progressReporter; + return progressReporter; + } + + public getProgressReporter(progressId: string): IProgressReporter | undefined { + return this.store[progressId]; + } + + public remove(progressReporter: IProgressReporter) { + delete this.store[progressReporter.getId()]; + } +} + +export const progressProvider: IProgressProvider = new ProgressProvider(); diff --git a/src/terminalLinkProvider.ts b/src/terminalLinkProvider.ts new file mode 100644 index 00000000..33016f71 --- /dev/null +++ b/src/terminalLinkProvider.ts @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { CancellationToken, commands, Position, ProviderResult, Range, TerminalLink, TerminalLinkContext, + TerminalLinkProvider, Uri, window } from "vscode"; +import { sendInfo } from "vscode-extension-telemetry-wrapper"; +import { resolveSourceUri } from "./languageServerPlugin"; + +export class JavaTerminalLinkProvder implements TerminalLinkProvider { + /** + * Provide terminal links for the given context. Note that this can be called multiple times + * even before previous calls resolve, make sure to not share global objects (eg. `RegExp`) + * that could have problems when asynchronous usage may overlap. + * @param context Information about what links are being provided for. + * @param token A cancellation token. + * @return A list of terminal links for the given line. + */ + public provideTerminalLinks(context: TerminalLinkContext, _token: CancellationToken): ProviderResult { + const isDebuggerTerminal: boolean = context.terminal.name.startsWith("Run:") || context.terminal.name.startsWith("Debug:"); + const regex = new RegExp("(\\sat\\s+)([\\w$\\.]+\\/)?(([\\w$]+\\.)+[<\\w$>]+)\\(([\\w-$]+\\.java:\\d+)\\)"); + const result: RegExpExecArray | null = regex.exec(context.line); + if (result && result.length) { + const stackTrace = `${result[2] || ""}${result[3]}(${result[5]})`; + const sourceLineNumber = Number(result[5].split(":")[1]); + return [{ + startIndex: result.index + result[1].length, + length: stackTrace.length, + methodName: result[3], + stackTrace, + lineNumber: sourceLineNumber, + isDebuggerTerminal, + }]; + } + + return []; + } + + /** + * Handle an activated terminal link. + */ + public async handleTerminalLink(link: IJavaTerminalLink): Promise { + sendInfo("", { + operationName: "handleJavaTerminalLink", + isDebuggerTerminal: String(link.isDebuggerTerminal), + }); + const uri = await resolveSourceUri(link.stackTrace); + if (uri) { + const lineNumber = Math.max(link.lineNumber - 1, 0); + window.showTextDocument(Uri.parse(uri), { + preserveFocus: true, + selection: new Range(new Position(lineNumber, 0), new Position(lineNumber, 0)), + }); + } else { + // If no source is found, then open the searching symbols quickpick box. + const fullyQualifiedName = link.methodName.substring(0, link.methodName.lastIndexOf(".")); + const className = fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf(".") + 1); + commands.executeCommand("workbench.action.quickOpen", "#" + className); + } + } +} + +interface IJavaTerminalLink extends TerminalLink { + methodName: string; + stackTrace: string; + lineNumber: number; + isDebuggerTerminal: boolean; +} diff --git a/src/threadOperations.ts b/src/threadOperations.ts new file mode 100644 index 00000000..23ca45c6 --- /dev/null +++ b/src/threadOperations.ts @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper"; + +export function initializeThreadOperations(context: vscode.ExtensionContext) { + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.continueAll", async (threadId) => { + await operateThread("continueAll", threadId); + })); + + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.continueOthers", async (threadId) => { + await operateThread("continueOthers", threadId); + })); + + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.pauseAll", async (threadId) => { + await operateThread("pauseAll", threadId); + })); + + context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.debug.pauseOthers", async (threadId) => { + await operateThread("pauseOthers", threadId); + })); +} + +async function operateThread(request: string, threadId: any): Promise { + const debugSession: vscode.DebugSession | undefined = vscode.debug.activeDebugSession; + if (!debugSession) { + return; + } + + if (debugSession.configuration.noDebug) { + return; + } + + await debugSession.customRequest(request, { threadId }); +} diff --git a/src/utility.ts b/src/utility.ts new file mode 100644 index 00000000..94c8e77c --- /dev/null +++ b/src/utility.ts @@ -0,0 +1,325 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { sendError, sendInfo, setUserError } from "vscode-extension-telemetry-wrapper"; +import { Type } from "./javaLogger"; +import { IMainClassOption, resolveMainClass } from "./languageServerPlugin"; +import { IProgressReporter } from "./progressAPI"; + +const TROUBLESHOOTING_LINK = "https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting.md"; +const LEARN_MORE = "Learn More"; +const JAVA_EXTENSION_ID = "redhat.java"; + +export class UserError extends Error { + public context: ITroubleshootingMessage; + + constructor(context: ITroubleshootingMessage) { + super(context.message); + this.context = context; + setUserError(this); + } +} + +export class JavaExtensionNotEnabledError extends Error { + constructor(message: string) { + super(message); + setUserError(this); + } +} + +export class OperationCancelledError extends Error { + constructor(message: string) { + super(message); + } +} + +interface ILoggingMessage { + type?: Type; + message: string; + stack?: string; + bypassLog?: boolean; +} + +interface ITroubleshootingMessage extends ILoggingMessage { + anchor?: string; +} + +function logMessage(message: ILoggingMessage): void { + if (!message.type || message.bypassLog) { + return; + } + + if (message.type === Type.EXCEPTION || message.type === Type.USAGEERROR) { + const error: Error = { + name: "error", + message: message.message, + stack: message.stack, + }; + if (message.type === Type.USAGEERROR) { + setUserError(error); + } + sendError(error); + } else { + sendInfo("", { message: message.message }); + } +} + +export async function showInformationMessage(message: ILoggingMessage, ...items: string[]): Promise { + logMessage(message); + return vscode.window.showInformationMessage(message.message, ...items); +} + +export async function showWarningMessage(message: ILoggingMessage, ...items: string[]): Promise { + logMessage(message); + return vscode.window.showWarningMessage(message.message, ...items); +} + +export async function showErrorMessage(message: ILoggingMessage, ...items: string[]): Promise { + logMessage(message); + return vscode.window.showErrorMessage(message.message, ...items); +} + +export async function showInformationMessageWithTroubleshooting(message: ITroubleshootingMessage, ...items: string[]): Promise { + const choice = await showInformationMessage(message, ...items, LEARN_MORE); + return handleTroubleshooting(message.message, choice, message.anchor); +} + +export async function showWarningMessageWithTroubleshooting(message: ITroubleshootingMessage, ...items: string[]): Promise { + const choice = await showWarningMessage(message, ...items, LEARN_MORE); + return handleTroubleshooting(message.message, choice, message.anchor); +} + +export async function showErrorMessageWithTroubleshooting(message: ITroubleshootingMessage, ...items: string[]): Promise { + const choice = await showErrorMessage(message, ...items, LEARN_MORE); + return handleTroubleshooting(message.message, choice, message.anchor); +} + +function handleTroubleshooting(message: string, choice?: string, anchor?: string): string | undefined { + if (choice === LEARN_MORE) { + openTroubleshootingPage(message, anchor); + return undefined; + } + + return choice; +} + +export function openTroubleshootingPage(message: string, anchor?: string) { + vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(anchor ? `${TROUBLESHOOTING_LINK}#${anchor}` : TROUBLESHOOTING_LINK)); + sendInfo("", { + troubleshooting: "yes", + troubleshootingMessage: message, + }); +} + +export async function guideToInstallJavaExtension() { + const MESSAGE = "Language Support for Java is required. Please install and enable it."; + const INSTALL = "Install"; + const choice = await vscode.window.showWarningMessage(MESSAGE, INSTALL); + if (choice === INSTALL) { + await installJavaExtension(); + } +} + +async function installJavaExtension() { + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (p) => { + p.report({ message: "Installing Language Support for Java ..." }); + await vscode.commands.executeCommand("workbench.extensions.installExtension", JAVA_EXTENSION_ID); + }); + const RELOAD = "Reload Window"; + const choice = await vscode.window.showInformationMessage("Please reload window to activate Language Support for Java.", RELOAD); + if (choice === RELOAD) { + await vscode.commands.executeCommand("workbench.action.reloadWindow"); + } +} + +export function convertErrorToMessage(err: Error): ILoggingMessage { + const properties = formatErrorProperties(err); + return { + type: Type.EXCEPTION, + message: properties.message, + stack: properties.stackTrace, + }; +} + +function formatErrorProperties(ex: any): any { + const exception = (ex && ex.data && ex.data.cause) + || { stackTrace: (ex && ex.stack), detailMessage: String((ex && ex.message) || ex || "Unknown exception") }; + + const properties = { + message: "", + stackTrace: "", + }; + + if (exception && typeof exception === "object") { + properties.message = exception.detailMessage; + properties.stackTrace = (Array.isArray(exception.stackTrace) && JSON.stringify(exception.stackTrace)) + || String(exception.stackTrace); + } else { + properties.message = String(exception); + } + + return properties; +} + +export async function getJavaHome(): Promise { + const extensionApi = await getJavaExtensionAPI(); + if (extensionApi && extensionApi.javaRequirement) { + return extensionApi.javaRequirement.java_home; + } + + return ""; +} + +export function getJavaExtensionAPI(progressReporter?: IProgressReporter): Thenable { + const extension = vscode.extensions.getExtension(JAVA_EXTENSION_ID); + if (!extension) { + throw new JavaExtensionNotEnabledError("VS Code Java Extension is not enabled."); + } + + return new Promise(async (resolve) => { + progressReporter?.getCancellationToken().onCancellationRequested(() => { + resolve(undefined); + }); + + resolve(await extension.activate()); + }); +} + +export function getJavaExtension(): vscode.Extension | undefined { + return vscode.extensions.getExtension(JAVA_EXTENSION_ID); +} + +export function isJavaExtEnabled(): boolean { + const javaExt = vscode.extensions.getExtension(JAVA_EXTENSION_ID); + return !!javaExt; +} + +export function isJavaExtActivated(): boolean { + const javaExt = vscode.extensions.getExtension(JAVA_EXTENSION_ID); + return !!javaExt && javaExt.isActive; +} + +export function isGitBash(isIntegratedTerminal: boolean): boolean { + const currentWindowsShellPath: string | undefined = isIntegratedTerminal ? vscode.env.shell : + vscode.workspace.getConfiguration("terminal")?.get("external.windowsExec"); + if (!currentWindowsShellPath) { + return false; + } + + const candidates: string[] = ["Git\\bin\\bash.exe", "Git\\bin\\bash", "Git\\usr\\bin\\bash.exe", "Git\\usr\\bin\\bash"]; + const find: string | undefined = candidates.find((candidate: string) => currentWindowsShellPath.endsWith(candidate)); + return !!find; +} + +export enum ServerMode { + STANDARD = "Standard", + LIGHTWEIGHT = "LightWeight", + HYBRID = "Hybrid", +} + +/** + * Wait for Java Language Support extension being on Standard mode, + * and return true if the final status is on Standard mode. + */ +export async function waitForStandardMode(progressReporter: IProgressReporter): Promise { + const importMessage = progressReporter?.getProgressLocation() === vscode.ProgressLocation.Notification ? + "Importing projects, [check details](command:java.show.server.task.status)" : "Importing projects..."; + if (await isImportingProjects()) { + progressReporter.report(importMessage); + } + + const api = await getJavaExtensionAPI(progressReporter); + if (!api) { + return false; + } + + if (api && api.serverMode === ServerMode.LIGHTWEIGHT) { + const answer = await vscode.window.showInformationMessage("Run/Debug feature requires Java language server to run in Standard mode. " + + "Do you want to switch it to Standard mode now?", "Yes", "Cancel"); + if (answer === "Yes") { + if (api.serverMode === ServerMode.STANDARD) { + return true; + } + + progressReporter?.report(importMessage); + return new Promise((resolve) => { + progressReporter.getCancellationToken().onCancellationRequested(() => { + resolve(false); + }); + api.onDidServerModeChange((mode: string) => { + if (mode === ServerMode.STANDARD) { + resolve(true); + } + }); + + vscode.commands.executeCommand("java.server.mode.switch", ServerMode.STANDARD, true); + }); + } + + return false; + } else if (api && api.serverMode === ServerMode.HYBRID) { + progressReporter.report(importMessage); + return new Promise((resolve) => { + progressReporter.getCancellationToken().onCancellationRequested(() => { + resolve(false); + }); + api.onDidServerModeChange((mode: string) => { + if (mode === ServerMode.STANDARD) { + resolve(true); + } + }); + }); + } + + return true; +} + +export async function searchMainMethods(uri?: vscode.Uri): Promise { + return resolveMainClass(uri); +} + +export async function searchMainMethodsWithProgress(uri?: vscode.Uri): Promise { + try { + return await vscode.window.withProgress( + { location: vscode.ProgressLocation.Window }, + async (p) => { + p.report({ message: "Searching main classes..." }); + return resolveMainClass(uri); + }); + } catch (ex) { + vscode.window.showErrorMessage(String((ex && ex.message) || ex)); + throw ex; + } +} + +async function isImportingProjects(): Promise { + const extension = vscode.extensions.getExtension(JAVA_EXTENSION_ID); + if (!extension) { + return false; + } + + const serverMode = getJavaServerMode(); + if (serverMode === ServerMode.STANDARD || serverMode === ServerMode.HYBRID) { + const allCommands = await vscode.commands.getCommands(); + return (!extension.isActive && allCommands.includes("java.show.server.task.status")) + || (extension.isActive && extension.exports?.serverMode === ServerMode.HYBRID); + } + + return false; +} + +function getJavaServerMode(): ServerMode { + return vscode.workspace.getConfiguration().get("java.server.launchMode") + || ServerMode.HYBRID; +} + +export function launchJobName(configName: string, noDebug: boolean): string { + let jobName = noDebug ? "Run" : "Debug"; + jobName += configName ? ` '${configName} '` : ""; + return jobName; +} + +export function launchJobNameByMainClass(mainClass: string, noDebug: boolean): string { + return launchJobName(mainClass.substr(mainClass.lastIndexOf(".") + 1), noDebug); +} diff --git a/src/variableMenu.ts b/src/variableMenu.ts new file mode 100644 index 00000000..e12889e4 --- /dev/null +++ b/src/variableMenu.ts @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper"; + +export function registerVariableMenuCommands(context: vscode.ExtensionContext): void { + vscode.workspace.onDidChangeConfiguration((event) => { + if (event.affectsConfiguration("java.debug.settings") || event.affectsConfiguration("debug.autoExpandLazyVariables")) { + updateContextKeys(); + } + }); + // Initialize the context keys + updateContextKeys(); + + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.showHex", () => updateVariableFormatter("showHex", true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.notShowHex", () => updateVariableFormatter("showHex", false))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.showQualifiedNames", () => updateVariableFormatter("showQualifiedNames", true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.notShowQualifiedNames", () => updateVariableFormatter("showQualifiedNames", false))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.showStaticVariables", () => updateVariableFormatter("showStaticVariables", true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.notShowStaticVariables", () => updateVariableFormatter("showStaticVariables", false))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.showLogicalStructure", () => updateVariableFormatter("showLogicalStructure", true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.notShowLogicalStructure", () => updateVariableFormatter("showLogicalStructure", false))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.showToString", () => updateVariableFormatter("showToString", true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.notShowToString", () => updateVariableFormatter("showToString", false))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.autoExpandLazyVariables", () => toggleLazyVariableSetting(true))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + "java.debug.variables.manualExpandLazyVariables", () => toggleLazyVariableSetting(false))); +} + +async function updateVariableFormatter(key: string, value: any) { + const debugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + // Update the formatter to settings.json + await debugSettingsRoot.update(key, value, getConfigurationTarget("java.debug", "settings")); + refreshVariableView(); +} + +function refreshVariableView() { + const debugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + if (vscode.debug.activeDebugSession && vscode.debug.activeDebugSession.type === "java") { + const formatter: any = { + showHex: debugSettingsRoot.showHex, + showQualifiedNames: debugSettingsRoot.showQualifiedNames, + showStaticVariables: debugSettingsRoot.showStaticVariables, + showLogicalStructure: debugSettingsRoot.showLogicalStructure, + showToString: debugSettingsRoot.showToString, + }; + vscode.debug.activeDebugSession.customRequest("refreshVariables", formatter); + } +} + +async function toggleLazyVariableSetting(toggle: boolean) { + const javadDebugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + if (!javadDebugSettingsRoot.showToString) { + await javadDebugSettingsRoot.update("showToString", true, getConfigurationTarget("java.debug", "settings")); + } + + const debugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("debug"); + await debugSettingsRoot.update("autoExpandLazyVariables", toggle, getConfigurationTarget("debug", "autoExpandLazyVariables")); + refreshVariableView(); +} + +function getConfigurationTarget(section: string, key: string): vscode.ConfigurationTarget { + const inspect = vscode.workspace.getConfiguration(section).inspect(key); + if (inspect && inspect.workspaceFolderValue !== undefined) { + return vscode.ConfigurationTarget.WorkspaceFolder; + } else if (inspect && inspect.workspaceValue !== undefined) { + return vscode.ConfigurationTarget.Workspace; + } else { + return vscode.ConfigurationTarget.Global; + } +} + +function updateContextKeys() { + const debugSettingsRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings"); + if (debugSettingsRoot) { + vscode.commands.executeCommand("setContext", "javadebug:showHex", debugSettingsRoot.showHex ? "on" : "off"); + vscode.commands.executeCommand("setContext", "javadebug:showLogicalStructure", debugSettingsRoot.showLogicalStructure ? "on" : "off"); + vscode.commands.executeCommand("setContext", "javadebug:showQualifiedNames", debugSettingsRoot.showQualifiedNames ? "on" : "off"); + vscode.commands.executeCommand("setContext", "javadebug:showStaticVariables", debugSettingsRoot.showStaticVariables ? "on" : "off"); + vscode.commands.executeCommand("setContext", "javadebug:showToString", debugSettingsRoot.showToString ? "on" : "off"); + } + + const globalDebugRoot: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("debug"); + if (globalDebugRoot) { + vscode.commands.executeCommand("setContext", "javadebug:expandLazyVariable", globalDebugRoot.autoExpandLazyVariables ? "on" : "off"); + } +} diff --git a/test/extension.test.ts b/test/extension.test.ts index b5fb28da..a2127763 100644 --- a/test/extension.test.ts +++ b/test/extension.test.ts @@ -1,20 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// The module 'assert' provides assertion methods from node import * as assert from "assert"; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it import * as vscode from "vscode"; -import * as myExtension from "../src/extension"; -// Defines a Mocha test suite to group tests of similar kind together suite("Extension Tests", () => { test("Extension should be present", () => { @@ -23,7 +12,7 @@ suite("Extension Tests", () => { test("should activate", function() { this.timeout(1 * 60 * 1000); - return vscode.extensions.getExtension("vscjava.vscode-java-debug").activate().then((api) => { + return vscode.extensions.getExtension("vscjava.vscode-java-debug")!.activate().then((_api) => { assert.ok(true); }); }); diff --git a/test/index.ts b/test/index.ts index b47e40e6..7e8d8261 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,26 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -// -// 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 { runTests } from "@vscode/test-electron"; -// tslint:disable-next-line:no-submodule-imports -import testRunner = require("vscode/lib/testrunner"); +async function main(): Promise { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath: string = path.resolve(__dirname, "../../"); -// 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 -}); + // The path to the extension test script + // Passed to --extensionTestsPath + const extensionTestsPath: string = path.resolve(__dirname, "./suite/index"); -module.exports = testRunner; + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }); + } catch (err) { + process.exit(1); + } +} + +main(); diff --git a/test/suite/index.ts b/test/suite/index.ts new file mode 100644 index 00000000..d87e690a --- /dev/null +++ b/test/suite/index.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as glob from "glob"; +import * as Mocha from "mocha"; +import * as path from "path"; + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: "tdd", + }); + mocha.options.color = true; + + const testsRoot = path.resolve(__dirname, ".."); + + return new Promise((c, e) => { + glob("**/**.test.js", { cwd: testsRoot }, (err, files) => { + if (err) { + return e(err); + } + + // Add files to the test suite + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); + + try { + // Run the mocha test + mocha.run((failures) => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + e(err); + } + }); + }); +} diff --git a/tsconfig.json b/tsconfig.json index 8e2b3306..5e963013 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,15 +3,21 @@ "module": "commonjs", "target": "es6", "outDir": "out", - "alwaysStrict": true, "lib": [ "es6" ], "sourceMap": true, - "rootDir": "." + "rootDir": ".", + "noUnusedLocals": true, + "noImplicitThis": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noUnusedParameters": true, + "strictNullChecks": true, + "alwaysStrict": true }, "exclude": [ "node_modules", ".vscode-test" ] -} \ No newline at end of file +} diff --git a/tslint.json b/tslint.json index 7cdcbaa1..d9005209 100644 --- a/tslint.json +++ b/tslint.json @@ -7,8 +7,10 @@ ], "no-unused-expression": true, "no-duplicate-variable": true, - "max-classes-per-file": [ - false + "max-classes-per-file": false, + "no-implicit-dependencies": [ + false, + "dev" ], "no-empty": false, "object-literal-sort-keys": false, @@ -23,15 +25,18 @@ "check-separator", "check-type" ], - "semicolon": [ - "always" - ], + "semicolon": true, "triple-equals": true, "max-line-length": [ true, 150 - ], + ], "no-angle-bracket-type-assertion": false, - "no-console": ["log","error"] + "no-console": [ + true, + "log", + "error" + ], + "no-submodule-imports": false } -} \ No newline at end of file +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..54342f8d --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +const path = require('path'); + +module.exports = function (env, argv) { + env = env || {}; + return [{ + name: 'extension', + target: 'node', + mode: 'none', + entry: { + extension: './src/extension.ts' + }, + module: { + rules: [{ + test: /\.ts$/, + exclude: /node_modules/, + use: 'ts-loader' + }] + }, + resolve: { + modules: ['node_modules', path.resolve(__dirname, 'src')], + mainFiles: ['index'], + extensions: ['.js', '.ts', '.json'] + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: "commonjs2", + publicPath: '/', + devtoolModuleFilenameTemplate: "../[resource-path]" + }, + externals: { + 'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module + vscode: 'commonjs vscode' + }, + devtool: 'source-map', + infrastructureLogging: { + level: 'log' + } + }]; +}; \ No newline at end of file