diff --git a/.azure-pipelines/cfs-settings.xml b/.azure-pipelines/cfs-settings.xml new file mode 100644 index 00000000..e5dc4e42 --- /dev/null +++ b/.azure-pipelines/cfs-settings.xml @@ -0,0 +1,40 @@ + + + + + + vscjava + Central Feed Service + ${env.CFS_MAVEN_URL} + central + + + + + vscjava + AzureDevOps + ${env.SYSTEM_ACCESSTOKEN} + + + diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index da46c1be..cc0b039c 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -2,6 +2,8 @@ name: $(Date:yyyyMMdd).$(Rev:r) variables: - name: Codeql.Enabled value: true + - template: /.azure-pipelines/npm-cfs-variables.yml@self + - template: /.azure-pipelines/maven-cfs-variables.yml@self resources: repositories: - repository: self @@ -44,25 +46,27 @@ extends: - checkout: self fetchTags: false - task: JavaToolInstaller@0 - displayName: Use Java 17 + displayName: Use Java 21 inputs: - versionSpec: "17" + versionSpec: "21" jdkArchitectureOption: x64 jdkSourceOption: PreInstalled - task: NodeTool@0 - displayName: Use Node 18.x + displayName: Use Node 20.x inputs: - versionSpec: 18.x - - task: Npm@1 + versionSpec: 20.x + - template: /.azure-pipelines/npm-cfs.yml@self + - script: npm install --verbose displayName: npm install - inputs: - verbose: true - - task: Npm@1 + - script: npm run build-server displayName: npm run build-server - inputs: - command: custom - verbose: false - customCommand: run build-server + # System.AccessToken is a secret, and Azure Pipelines does not export secret + # variables to the environment -- not even through a variable that merely + # references one. It is mapped here, on the step that actually runs Maven, + # rather than in maven-cfs-variables.yml alongside the rest of the wiring. + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + MVNW_PASSWORD: $(System.AccessToken) - task: Bash@3 displayName: vsce package inputs: diff --git a/.azure-pipelines/maven-cfs-variables.yml b/.azure-pipelines/maven-cfs-variables.yml new file mode 100644 index 00000000..11ab65de --- /dev/null +++ b/.azure-pipelines/maven-cfs-variables.yml @@ -0,0 +1,47 @@ +# Variables that route Maven through the Central Feed Service (CFS), as required by +# SFI Network Isolation. Consumed by every pipeline in this directory that builds the +# Java side of the extension: +# +# variables: +# - template: /.azure-pipelines/maven-cfs-variables.yml@self +# +# There is deliberately no companion steps template. Everything the redirect needs is +# already understood by Maven and its wrapper as environment variables, so no task has +# to rewrite a settings file and nothing in the checked-out tree is modified. Pipeline +# variables are exported to every step in the job, which is what makes this work for +# the Maven runs these builds start indirectly -- from an npm script or a gulp task -- +# and never name on a command line of their own. +# +# The one thing that cannot live here is the credential. System.AccessToken is a +# secret, and secret variables are not exported to the environment, not even through +# a variable that merely references one. It is therefore mapped with `env:` on the +# steps that run Maven; grep for MVNW_PASSWORD to find them. That also keeps the token +# out of the environment of every unrelated task in the job. +# +# Two independent egress paths have to be closed, and only the first is obvious. +variables: + # The feed's maven/v1 endpoint, read by cfs-settings.xml and by the wrapper below. + # Committing it matches npm-cfs-variables.yml: a feed address is not a secret, and + # the token that makes it usable never leaves the agent. + - name: CFS_MAVEN_URL + value: https://pkgs.dev.azure.com/mseng/VSJava/_packaging/vscjava/maven/v1 + + # Path one: artifact resolution. The `mvn` launcher prepends MAVEN_ARGS to every + # invocation, so build scripts keep calling `mvnw` with no extra flags of their own. + # Supported by Maven 3.9 and newer, which is what the wrapper here pins. + - name: MAVEN_ARGS + value: -s $(Build.SourcesDirectory)/.azure-pipelines/cfs-settings.xml + + # Path two: the Maven distribution itself. The wrapper downloads it from + # distributionUrl before Maven exists, so settings.xml cannot influence that request. + # MVNW_REPOURL substitutes everything ahead of /org/apache/maven/ in that URL, which + # is why .mvn/wrapper/maven-wrapper.properties still names the public host and needs + # no edit: contributors keep a wrapper that works, agents resolve it from the feed. + # + # The wrapper ignores both of these unless MVNW_PASSWORD is also set, which happens + # on the Maven steps; with no credential it would fall back to an unauthenticated + # fetch and fail on 401 rather than reach a public host. + - name: MVNW_REPOURL + value: $(CFS_MAVEN_URL) + - name: MVNW_USERNAME + value: AzureDevOps diff --git a/.azure-pipelines/nightly.yml b/.azure-pipelines/nightly.yml index 94fe2964..a1ee16a2 100644 --- a/.azure-pipelines/nightly.yml +++ b/.azure-pipelines/nightly.yml @@ -2,6 +2,8 @@ name: $(Date:yyyyMMdd).$(Rev:r) variables: - name: Codeql.Enabled value: true + - template: /.azure-pipelines/npm-cfs-variables.yml@self + - template: /.azure-pipelines/maven-cfs-variables.yml@self schedules: - cron: 0 0 * * * branches: @@ -12,31 +14,30 @@ resources: - repository: self type: git ref: refs/heads/main - - repository: 1esPipelines + - repository: MicroBuildTemplate type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release + name: 1ESPipelineTemplates/MicroBuildTemplate trigger: none extends: - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate parameters: pool: - name: 1ES_JavaTooling_Pool - image: 1ES_JavaTooling_Windows_2022 - os: windows - sdl: - sourceAnalysisPool: - name: 1ES_JavaTooling_Pool - image: 1ES_JavaTooling_Windows_2022 - os: windows - customBuildTags: - - MigrationTooling-mseng-VSJava-13463-Tool + name: VSEng-MicroBuildVSStable + settings: + networkIsolationPolicy: Permissive stages: - stage: Build jobs: - job: Job_1 displayName: Agent job 1 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: extension @@ -47,69 +48,66 @@ extends: clean: true fetchTags: true - task: NodeTool@0 - displayName: Use Node 18.x + displayName: Use Node 20.x inputs: - versionSpec: 18.x + versionSpec: 20.x + # The image does not have jdk preinstalled, we need to download it first. + - task: PowerShell@2 + displayName: Download JDK 21 + inputs: + targetType: 'inline' + script: |- + New-Item -ItemType Directory -Path "$env:AGENT_TEMPDIRECTORY\downloadjdk" + Invoke-WebRequest -Uri "https://aka.ms/download-jdk/microsoft-jdk-21-windows-x64.zip" -OutFile "$env:AGENT_TEMPDIRECTORY\downloadjdk\microsoft-jdk-21-windows-x64.zip" - task: JavaToolInstaller@0 - displayName: Use Java 17 + displayName: Use Java 21 inputs: - versionSpec: "17" + versionSpec: "21" jdkArchitectureOption: x64 - jdkSourceOption: PreInstalled - - task: Npm@1 + jdkSourceOption: LocalDirectory + jdkFile: $(Agent.TempDirectory)/downloadjdk/microsoft-jdk-21-windows-x64.zip + jdkDestinationDirectory: $(Agent.ToolsDirectory)/ms-jdk21 + - script: java --version + displayName: 'Check Java installation' + - template: /.azure-pipelines/npm-cfs.yml@self + - script: npm install displayName: npm install - inputs: - verbose: false - - task: Bash@3 + - task: CmdLine@2 displayName: npx gulp build_server + # System.AccessToken is a secret, and Azure Pipelines does not export secret + # variables to the environment -- not even through a variable that merely + # references one. It is mapped here, on the step that actually runs Maven, + # rather than in maven-cfs-variables.yml alongside the rest of the wiring. + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + MVNW_PASSWORD: $(System.AccessToken) inputs: targetType: inline script: |- # Build the jars to the server folder. npm run build-server - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 - displayName: ESRP CodeSigning + - task: PowerShell@2 + displayName: Sign Jars inputs: - ConnectedServiceName: 'ESRP-Release-Test' - AppRegistrationClientId: '1992ee18-e9d2-42d6-ab20-94dd947a44b6' - AppRegistrationTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47' - AuthAKVName: 'vscjavaci' - AuthCertName: 'vscjava-esrprelease-auth' - AuthSignCertName: 'VSCJava-CodeSign' - FolderPath: server - Pattern: com.microsoft.jdtls.ext.*.jar - signConfigType: inlineSignParams - inlineOperation: |- - [ - { - "KeyCode" : "CP-447347-Java", - "OperationCode" : "JavaSign", - "Parameters" : { - "SigAlg" : "SHA256withRSA", - "Timestamp" : "-tsa http://sha256timestamp.ws.digicert.com/sha256/timestamp" - }, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-447347-Java", - "OperationCode" : "JavaVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] + targetType: 'inline' + script: |- + $files = Get-ChildItem -Path . -Recurse -Filter "com.microsoft.jdtls.ext.*.jar" + foreach ($file in $files) { + $fileName = $file.Name + & dotnet "$env:MBSIGN_APPFOLDER\DDSignFiles.dll" /file:"$fileName" /certs:100010171 + } + workingDirectory: 'server' - task: CmdLine@2 displayName: Replace AI Key inputs: script: npx json@9.0.6 -I -f package.json -e "this.aiKey=\"%AI_KEY%\"" - - task: Bash@3 - displayName: Bash Script + - task: PowerShell@2 + displayName: Update package.json inputs: targetType: inline script: |- node ./scripts/prepare-nightly-build.js - mv ./package.insiders.json ./package.json + Move-Item -Path "./package.insiders.json" -Destination "./package.json" -Force - script: npx @vscode/vsce@latest package --pre-release -o extension.vsix displayName: 'vsce package --pre-release' ### Copy files for APIScan @@ -133,34 +131,12 @@ extends: 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: cp extension.manifest extension.signature.p7s + - script: copy extension.manifest extension.signature.p7s displayName: 'Prepare manifest for signing' - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 + - task: CmdLine@2 + displayName: Sign extension inputs: - ConnectedServiceName: 'ESRP-Release-Test' - AppRegistrationClientId: '1992ee18-e9d2-42d6-ab20-94dd947a44b6' - AppRegistrationTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47' - AuthAKVName: 'vscjavaci' - AuthCertName: 'vscjava-esrprelease-auth' - AuthSignCertName: 'VSCJava-CodeSign' - FolderPath: '.' - Pattern: 'extension.signature.p7s' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-401405", - "operationSetCode": "VSCodePublisherSign", - "parameters" : [], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 90 - MaxConcurrency: 25 - MaxRetryAttempts: 5 - PendingAnalysisWaitTimeoutMinutes: 5 - displayName: 'Sign extension' + script: dotnet %MBSIGN_APPFOLDER%/ddsignfiles.dll /file:extension.signature.p7s /certs:4014052 - task: CopyFiles@2 displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)" inputs: diff --git a/.azure-pipelines/npm-cfs-variables.yml b/.azure-pipelines/npm-cfs-variables.yml new file mode 100644 index 00000000..261e5d08 --- /dev/null +++ b/.azure-pipelines/npm-cfs-variables.yml @@ -0,0 +1,28 @@ +# Variables required to route npm package restore through the Central Feed Service +# (CFS). Consumed by every pipeline in this directory alongside the npm-cfs.yml steps +# template, which is where these values are actually applied. +# +# Both are declared here rather than in each pipeline so the feed URL exists in +# exactly one place. +# +# npm_config_registry is not redundant with the registry written into the generated +# .npmrc. npm resolves configuration in the order cli > environment > project .npmrc +# > user .npmrc, so a registry supplied only through the user config is outranked by +# anything the agent image already configures -- Microsoft hosted images ship a user +# level .npmrc pointing at an internal proxy, and a pool that exports +# npm_config_registry would win outright. Restore would then quietly resolve from +# somewhere other than CFS while the build still reported success. Declaring the +# variable here puts the redirect at environment precedence, where only an explicit +# command line flag can override it. +# +# npm matches npm_config_* environment variables case insensitively, so the +# uppercased form that Azure Pipelines exports applies to every step on every OS. +# That matters because package restore here is not driven by a single task: the Npm +# tasks, `npx json`, `npx @vscode/vsce` and the vsce invocation inside AzureCLI@2 +# all inherit the agent environment rather than reading a task input. + +variables: + - name: npm_config_registry + value: https://pkgs.dev.azure.com/mseng/VSJava/_packaging/vscjava/npm/registry/ + - name: npm_config_userconfig + value: $(Agent.TempDirectory)/.npmrc diff --git a/.azure-pipelines/npm-cfs.yml b/.azure-pipelines/npm-cfs.yml new file mode 100644 index 00000000..c7445e78 --- /dev/null +++ b/.azure-pipelines/npm-cfs.yml @@ -0,0 +1,58 @@ +# Routes npm package restore through the Central Feed Service (CFS), as required by +# SFI Network Isolation. Consumed by every build pipeline in this directory. +# +# Pipelines must also include the companion variables template: +# variables: +# - template: /.azure-pipelines/npm-cfs-variables.yml@self +# which declares the feed URL and the generated .npmrc path. The redirect itself is +# carried by the npm_config_registry environment variable that template exports; see +# its header for why the generated .npmrc alone is not enough. +# +# The .npmrc is generated at build time into the agent temp directory rather than +# being committed to the repository, so that: +# * open source contributors and the GitHub Actions workflows keep restoring from +# the public npm registry -- npm rewrites the host of every `resolved` URL in +# package-lock.json to the configured registry, so a single lockfile serves both; +# * the credential that NpmAuthenticate injects never lands inside the workspace; +# * the configuration does not depend on the repository being checked out, so +# release jobs consuming a prebuilt artifact work the same way as build jobs. +# +# The registry is still written into that file because NpmAuthenticate discovers the +# registries to authenticate by reading it. npm then takes the URL from the +# environment and the matching credential from this file. +# +# The file is written with `npm config set` rather than a shell redirect because +# these pipelines span both Linux and Windows pools. `script:` maps to CmdLine@2, +# which runs on both, and the npm invocation itself is shell agnostic. PowerShell@2 +# is avoided because it resolves `pwsh` before `powershell` and hard fails when +# neither is on PATH, which is not guaranteed on a custom Linux image. +# +# This template must run after the Node install task, and before any step that +# restores packages -- including `npx`, which resolves downloads through the +# configured registry. +# +# Consumers must reference this file as `/.azure-pipelines/npm-cfs.yml@self`. A +# relative path is resolved against the file doing the including, which for these +# pipelines is the 1ES extends template in another repository, so the unqualified +# form is looked up in 1ESPipelineTemplates and fails YAML compilation. + +steps: + - script: npm config set registry $(npm_config_registry) --location=user --userconfig="$(npm_config_userconfig)" + displayName: Configure CFS npm registry + + # Appends `//pkgs.dev.azure.com/.../registry/:_authToken=` for every + # registry it finds in the file above. `always-auth` is deliberately not written: + # it is not read by this task and is rejected outright by the npm 10 shipped with + # Node 20. + - task: NpmAuthenticate@0 + displayName: Authenticate to CFS feed + inputs: + workingFile: $(npm_config_userconfig) + + # Restore silently falling back to the public registry is the failure mode this + # whole template exists to prevent, and it leaves no trace in the build log, so it + # is asserted rather than assumed. Written in node, which the agent already + # provides, to avoid shell differences between the Linux and Windows pools. + - script: >- + node -e "const cp=require('child_process');const r=cp.execSync('npm config get registry').toString().trim();console.log('npm registry -> '+r);if(!r.startsWith('https://pkgs.dev.azure.com/')){console.error('##vso[task.logissue type=error]npm is not configured against the CFS feed');process.exit(1);}" + displayName: Verify CFS npm registry diff --git a/.azure-pipelines/rc.yml b/.azure-pipelines/rc.yml index ee059eb5..59286c81 100644 --- a/.azure-pipelines/rc.yml +++ b/.azure-pipelines/rc.yml @@ -2,36 +2,37 @@ name: $(Date:yyyyMMdd).$(Rev:r) variables: - name: Codeql.Enabled value: true + - template: /.azure-pipelines/npm-cfs-variables.yml@self + - template: /.azure-pipelines/maven-cfs-variables.yml@self resources: repositories: - repository: self type: git ref: refs/heads/main - - repository: 1esPipelines + - repository: MicroBuildTemplate type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release + name: 1ESPipelineTemplates/MicroBuildTemplate trigger: none extends: - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate parameters: pool: - name: 1ES_JavaTooling_Pool - image: 1ES_JavaTooling_Windows_2022 - os: windows - sdl: - sourceAnalysisPool: - name: 1ES_JavaTooling_Pool - image: 1ES_JavaTooling_Windows_2022 - os: windows - customBuildTags: - - MigrationTooling-mseng-VSJava-9019-Tool + name: VSEng-MicroBuildVSStable + settings: + networkIsolationPolicy: Permissive stages: - stage: Build jobs: - job: Job_1 displayName: 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: extension @@ -42,63 +43,60 @@ extends: clean: true fetchTags: true - task: NodeTool@0 - displayName: Use Node 18.x + displayName: Use Node 20.x inputs: - versionSpec: 18.x + versionSpec: 20.x + # The image does not have jdk preinstalled, we need to download it first. + - task: PowerShell@2 + displayName: Download JDK 21 + inputs: + targetType: 'inline' + script: |- + New-Item -ItemType Directory -Path "$env:AGENT_TEMPDIRECTORY\downloadjdk" + Invoke-WebRequest -Uri "https://aka.ms/download-jdk/microsoft-jdk-21-windows-x64.zip" -OutFile "$env:AGENT_TEMPDIRECTORY\downloadjdk\microsoft-jdk-21-windows-x64.zip" - task: JavaToolInstaller@0 - displayName: Use Java 17 + displayName: Use Java 21 inputs: - versionSpec: "17" + versionSpec: "21" jdkArchitectureOption: x64 - jdkSourceOption: PreInstalled - - task: Npm@1 + jdkSourceOption: LocalDirectory + jdkFile: $(Agent.TempDirectory)/downloadjdk/microsoft-jdk-21-windows-x64.zip + jdkDestinationDirectory: $(Agent.ToolsDirectory)/ms-jdk21 + - script: java --version + displayName: 'Check Java installation' + - template: /.azure-pipelines/npm-cfs.yml@self + - script: npm install displayName: npm install - inputs: - verbose: false - - task: Bash@3 + - task: CmdLine@2 displayName: npx gulp build_server + # System.AccessToken is a secret, and Azure Pipelines does not export secret + # variables to the environment -- not even through a variable that merely + # references one. It is mapped here, on the step that actually runs Maven, + # rather than in maven-cfs-variables.yml alongside the rest of the wiring. + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + MVNW_PASSWORD: $(System.AccessToken) inputs: targetType: inline script: |- # Build the jars to the server folder. npm run build-server - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 - displayName: ESRP CodeSigning + - task: PowerShell@2 + displayName: Sign Jars inputs: - ConnectedServiceName: 'ESRP-Release-Test' - AppRegistrationClientId: '1992ee18-e9d2-42d6-ab20-94dd947a44b6' - AppRegistrationTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47' - AuthAKVName: 'vscjavaci' - AuthCertName: 'vscjava-esrprelease-auth' - AuthSignCertName: 'VSCJava-CodeSign' - FolderPath: server - Pattern: com.microsoft.jdtls.ext.*.jar - signConfigType: inlineSignParams - inlineOperation: |- - [ - { - "KeyCode" : "CP-447347-Java", - "OperationCode" : "JavaSign", - "Parameters" : { - "SigAlg" : "SHA256withRSA", - "Timestamp" : "-tsa http://sha256timestamp.ws.digicert.com/sha256/timestamp" - }, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-447347-Java", - "OperationCode" : "JavaVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] + targetType: 'inline' + script: |- + $files = Get-ChildItem -Path . -Recurse -Filter "com.microsoft.jdtls.ext.*.jar" + foreach ($file in $files) { + $fileName = $file.Name + & dotnet "$env:MBSIGN_APPFOLDER\DDSignFiles.dll" /file:"$fileName" /certs:100010171 + } + workingDirectory: 'server' - task: CmdLine@2 displayName: Replace AI Key inputs: script: npx json@9.0.6 -I -f package.json -e "this.aiKey=\"%AI_KEY%\"" - - task: Bash@3 + - task: CmdLine@2 displayName: vsce package inputs: targetType: inline @@ -124,34 +122,12 @@ extends: 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: cp extension.manifest extension.signature.p7s + - script: copy extension.manifest extension.signature.p7s displayName: 'Prepare manifest for signing' - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 + - task: CmdLine@2 + displayName: Sign extension inputs: - ConnectedServiceName: 'ESRP-Release-Test' - AppRegistrationClientId: '1992ee18-e9d2-42d6-ab20-94dd947a44b6' - AppRegistrationTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47' - AuthAKVName: 'vscjavaci' - AuthCertName: 'vscjava-esrprelease-auth' - AuthSignCertName: 'VSCJava-CodeSign' - FolderPath: '.' - Pattern: 'extension.signature.p7s' - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-401405", - "operationSetCode": "VSCodePublisherSign", - "parameters" : [], - "toolName": "sign", - "toolVersion": "1.0" - } - ] - SessionTimeout: 90 - MaxConcurrency: 25 - MaxRetryAttempts: 5 - PendingAnalysisWaitTimeoutMinutes: 5 - displayName: 'Sign extension' + script: dotnet %MBSIGN_APPFOLDER%/ddsignfiles.dll /file:extension.signature.p7s /certs:4014052 - task: CopyFiles@2 displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)" inputs: diff --git a/.azure-pipelines/release-nightly.yml b/.azure-pipelines/release-nightly.yml new file mode 100644 index 00000000..a9aa67d9 --- /dev/null +++ b/.azure-pipelines/release-nightly.yml @@ -0,0 +1,57 @@ +# This pipeline is used to release the Project Manager for Java VSCode 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 + - template: /.azure-pipelines/npm-cfs-variables.yml@self +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 Project Manager for Java VSCode 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: extension + downloadType: specific + targetPath: '$(Build.SourcesDirectory)' + steps: + - task: NodeTool@0 + displayName: Use Node 20.x + inputs: + versionSpec: 20.x + - template: /.azure-pipelines/npm-cfs.yml@self + - 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'' --allow-proposed-apis chatPromptFiles --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..a9aa67d9 --- /dev/null +++ b/.azure-pipelines/release.yml @@ -0,0 +1,57 @@ +# This pipeline is used to release the Project Manager for Java VSCode 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 + - template: /.azure-pipelines/npm-cfs-variables.yml@self +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 Project Manager for Java VSCode 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: extension + downloadType: specific + targetPath: '$(Build.SourcesDirectory)' + steps: + - task: NodeTool@0 + displayName: Use Node 20.x + inputs: + versionSpec: 20.x + - template: /.azure-pipelines/npm-cfs.yml@self + - 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'' --allow-proposed-apis chatPromptFiles --azure-credential' \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..a6dfb950 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @testforstephen @wenytang-ms @chagong diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..451981cf --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,8 @@ +# Copilot instructions for vscode-java-dependency + +## UI and E2E tests + +- When asked to add, update, run, or debug UI/E2E coverage, prefer the AutoTest YAML workflow under `test/e2e-plans/`. +- Use the `uitest` skill for UI test work. It should create or update `test/e2e-plans/*.yaml`, validate the plan, build the OSGi bundle and package the extension when needed, run AutoTest, and inspect `test-results/`. +- Do not create legacy VS Code extension tests (`test/maven-suite`, `test/gui`) for UI coverage unless the user explicitly asks for that format. +- Prefer deterministic AutoTest verifiers (`verifyTreeItem`, `verifyFile`, `verifyEditorTab`, `verifyClipboard`) over screenshot-only checks. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..a4a0cf03 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,28 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + # CI restores packages from the Central Feed Service, which withholds + # upstream versions until they are roughly a week old (measured at ~6.8 + # days; both the packument entry and the tarball return 404 before then). + # Dependabot's built-in cooldown is only 3 days, so bumps otherwise land in + # a window where the feed 404s and the build fails. 10 days leaves margin + # in case the feed's ingestion lag drifts. + cooldown: + default-days: 10 + - package-ecosystem: "github-actions" + directory: "/" + groups: + github-actions: + patterns: ["*"] + schedule: + interval: "weekly" + cooldown: + default-days: 7 diff --git a/.github/instructions/uitest-plan.instructions.md b/.github/instructions/uitest-plan.instructions.md new file mode 100644 index 00000000..34cc6708 --- /dev/null +++ b/.github/instructions/uitest-plan.instructions.md @@ -0,0 +1,49 @@ +--- +applyTo: "test/e2e-plans/**/*.yaml" +description: "Authoring rules for vscode-java-dependency (Project Manager for Java) AutoTest UI/E2E YAML test plans" +--- + +# AutoTest UI/E2E test plan instructions + +Test plans under `test/e2e-plans/` are executable YAML files consumed by `@vscjava/vscode-autotest`. They should describe stable user scenarios for the Java Projects explorer, not raw implementation details. + +## Setup rules + +- Use `setup.extension: "vscjava.vscode-java-pack"` plus `setup.vscodeVersion: "stable"` for most scenarios. Installing the Extension Pack for Java pulls in every Java extension the Java Projects view relies on, so there is no need to install `redhat.java` separately. +- Install the extension under test from a local VSIX at runtime with `--vsix vscode-java-dependency.vsix` — do not rely on a marketplace copy of `vscjava.vscode-java-dependency`. +- Use existing in-repo fixtures as the workspace: `../maven` (a `maven-archetype-quickstart` project: `my-app` / `com.mycompany.app` / `App.java`) or `../invisible` (an unmanaged-folder project for referenced-library scenarios). Paths are relative to the test plan file. Do not add large binary fixtures. +- Referenced-library / classpath commands (`java.project.addLibraries`, `java.project.removeLibrary`, `java.project.addLibraryFolders`, `java.project.refreshLibraries`) only apply to invisible projects — use `../invisible`, not `../maven`, for those. +- Disable noisy startup surfaces with settings when relevant, for example `workbench.startupEditor: "none"` and `java.configuration.checkProjectSettingsExclusions: false`. + +## Action rules + +- Prefer stable command IDs via `executeVSCodeCommand` (for example `javaProjectExplorer.focus`, `java.view.package.revealInProjectExplorer`, `workbench.actions.treeView.javaProjectExplorer.collapseAll`) before UI locators. Command IDs are locale-independent. +- Drive the tree with `expandTreeItem ` and title-bar buttons with `clickViewTitleAction "Java Projects" ""`. The action resolver only matches the exact `expandTreeItem ` form; free-form phrasing silently falls back to the command palette and no-ops. +- Free up sidebar space before asserting tree rows: `executeVSCodeCommand workbench.action.closeAuxiliaryBar`, `collapseSidebarSection OUTLINE`, `collapseSidebarSection TIMELINE`, and `collapseWorkspaceRoot`. +- Use `insertLineInFile` for Java edits that the language server must analyze. Use `typeInEditor` only for text that does not require language-server analysis. +- Use `waitForLanguageServer` before interacting with the tree; prefer verifier polling over long static waits. Short static waits are acceptable only for UI rendering settle time. +- Native file/folder pickers are suppressed in the smoke-test driver; drive VS Code's internal quick-pick with `fillQuickInput` instead of relying on `mockOpenDialog`. +- Quote action arguments that contain spaces: + +```yaml +action: 'clickViewTitleAction "Java Projects" "Unlink with Editor"' +``` + +## Verification rules + +- Add deterministic verification to every meaningful step. The natural-language `verify` field is context for humans and failure analysis; it is not pass/fail authority by itself, and it is auto-passed when a plan runs with `--no-llm`. +- Use `verifyTreeItem` (with `name:`, optional `exact: true`, and `visible: false` for absence) as the authoritative check for Java Projects tree state. +- Use `verifyFile` after operations that create, modify, or delete files on disk (new type, export jar, permanent delete). VS Code can open duplicate editor tabs with stale buffers, so prefer file-content checks over editor checks after such operations. +- Use `verifyEditorTab` to assert which file an action opened, and `verifyClipboard` for copy-path commands. +- On state-check steps whose only assertion is a deterministic verifier, omit the `verify:` field to avoid false LLM failures. +- Use screenshots only as diagnostics produced by AutoTest; do not make screenshots the only evidence of pass/fail. + +## Local validation commands + +```powershell +npx -y @vscjava/vscode-autotest validate test\e2e-plans\.yaml +npm install # first time only; on later iterations run just the commands below +npm run build-server +npx @vscode/vsce package -o vscode-java-dependency.vsix +npx -y @vscjava/vscode-autotest run test\e2e-plans\.yaml --vsix vscode-java-dependency.vsix --no-llm +``` diff --git a/.github/llms.md b/.github/llms.md new file mode 100644 index 00000000..55d69b23 --- /dev/null +++ b/.github/llms.md @@ -0,0 +1,38 @@ +# 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 \ No newline at end of file diff --git a/.github/skills/uitest/SKILL.md b/.github/skills/uitest/SKILL.md new file mode 100644 index 00000000..801bc8ba --- /dev/null +++ b/.github/skills/uitest/SKILL.md @@ -0,0 +1,79 @@ +--- +name: uitest +description: Write, update, run, or debug vscode-java-dependency (Project Manager for Java) UI/E2E tests using AutoTest YAML plans. Use when the user asks for a UI test, E2E test, VS Code UI validation, Java Projects tree/view test, referenced-library test, or autotest plan. +--- + +# UI/E2E tests with AutoTest + +Use this skill to add or update UI/E2E coverage for `vscode-java-dependency` (Project Manager for Java). + +The repository uses `@vscjava/vscode-autotest`: YAML plans in `test/e2e-plans/*.yaml` launch VS Code, install the Extension Pack for Java (`vscjava.vscode-java-pack`) plus a local VSIX of this extension, execute user-facing actions against the Java Projects view, capture screenshots, and write `test-results//results.json`. + +## Prerequisites (local) + +- Node.js >= 18 and JDK 21+ installed and on `PATH` (JDK 21 is required to build the `jdtls.ext` OSGi bundle). +- Close any running VS Code instance before running a plan locally; a running instance can block AutoTest from launching its own VS Code. +- Workspace fixtures are in-repo — no external clones are needed. Plans reference `../maven` (`test/maven`, a `maven-archetype-quickstart` project) or `../invisible` (`test/invisible`, an unmanaged-folder project). + +## Workflow + +1. Identify the scenario and search `test/e2e-plans/*.yaml` for an existing plan that already covers the area (project explorer, view modes, classpath, export jar, new types, file operations, delete, copy paths, refresh, build lifecycle, autorefresh). +2. Update the existing plan when possible. Create a new `test/e2e-plans/java-dep-.yaml` only when no existing plan fits. +3. Use stable AutoTest actions and deterministic verifiers. Do not add raw Playwright tests or screenshot-only checks. +4. Validate the plan: + +```powershell +npx -y @vscjava/vscode-autotest validate test\e2e-plans\.yaml +``` + +5. If validating the current branch, build the OSGi bundle and package the extension: + +```powershell +npm install # first time only; on later iterations run just the two commands below +npm run build-server +npx @vscode/vsce package -o vscode-java-dependency.vsix +``` + +6. Run the plan against the packaged VSIX: + +```powershell +npx -y @vscjava/vscode-autotest run test\e2e-plans\.yaml --vsix vscode-java-dependency.vsix --output test-results\ +``` + + Add `--no-llm` to skip natural-language `verify:` fields and rely only on deterministic verifiers for a fast local loop. Run the whole suite with `npm run test-e2e` (`autotest run-all test/e2e-plans --no-llm`). + +7. Inspect `test-results//results.json` and `test-results//screenshots/`. +8. Iterate based on the failure cause: + - **Incorrect plan**: fix the YAML and rerun step 6. No rebuild is needed. + - **Product code fix**: after editing extension source (`src/**`) or the OSGi bundle (`jdtls.ext/**`), re-run step 5 (rebuild + repackage the VSIX) before rerunning step 6. Never rerun against a stale VSIX. + - **Product bug (report only)**: report the observed behavior and cite the failing step, screenshot, and result reason. + +## Authoring rules + +- For most plans, use: + +```yaml +setup: + extension: "vscjava.vscode-java-pack" + vscodeVersion: "stable" + workspace: "../maven" + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" +``` + +- Use `--vsix vscode-java-dependency.vsix` to test current-branch changes; do not rely on a marketplace copy of `vscjava.vscode-java-dependency`. +- Use `../invisible` (not `../maven`) for referenced-library / classpath commands, which only apply to unmanaged-folder projects. +- Prefer `executeVSCodeCommand ` for command-driven UI (e.g. `javaProjectExplorer.focus`, `java.view.package.revealInProjectExplorer`, `workbench.actions.treeView.javaProjectExplorer.collapseAll`). +- Drive the tree with `expandTreeItem ` and title-bar buttons with `clickViewTitleAction "Java Projects" ""`. +- Prefer `verifyTreeItem` for tree state, `verifyFile` for generated/modified/deleted files, `verifyEditorTab` for opened tabs, and `verifyClipboard` for copy-path commands. +- Use `waitForLanguageServer` before tree interactions, and `insertLineInFile` for Java source edits that JDT LS must observe. +- Free sidebar space (`closeAuxiliaryBar`, `collapseSidebarSection OUTLINE`/`TIMELINE`, `collapseWorkspaceRoot`) before asserting tree rows. +- Keep step IDs unique, descriptive, and kebab-case. Omit `verify:` on steps whose only assertion is a deterministic verifier. +- Avoid hard-coded coordinates and brittle DOM structure assumptions. + +## CI + +The repository workflow `.github/workflows/e2eUI.yml` runs on push and pull requests to `main`. It lints, discovers `test/e2e-plans/*.yaml` into a matrix, builds a branch VSIX per OS, runs every plan on Windows and Linux as independent matrix cells, and uploads `test-results/` artifacts plus an aggregate summary. + +Each plan surfaces as its own PR check, so a new `test/e2e-plans/*.yaml` is picked up automatically without editing the workflow. diff --git a/.github/workflows/e2eUI.yml b/.github/workflows/e2eUI.yml new file mode 100644 index 00000000..2c3a7f2f --- /dev/null +++ b/.github/workflows/e2eUI.yml @@ -0,0 +1,323 @@ +name: E2E UI Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +# Split-pipeline E2E UI workflow. +# +# lint → tslint + checkstyle (ubuntu, OS-agnostic) +# discover-plans → emits a matrix of test-plan basenames +# +# build-linux ─┐ +# e2e-linux (×plan) ┤ +# ├──→ analyze → unified summary covering both OSes +# build-windows ─┤ +# e2e-windows (×plan)┘ +# +# Per-OS pipelines run completely independently: Linux e2e jobs do NOT +# wait for the Windows VSIX build (and vice versa), so a slow Windows +# build cannot delay the start of Linux e2e plans. Each matrix cell +# surfaces as its own PR check, so failures are visible without an +# extra gate job. +# +# Inspired by vscode-java-pack/.github/workflows/e2e-autotest.yml. + +jobs: + # ── Lint + Checkstyle (OS-agnostic) ───────────────────── + lint: + name: Lint & Checkstyle + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Lint + run: npm run tslint + + - name: Checkstyle + working-directory: ./jdtls.ext + run: ./mvnw checkstyle:check + + # ── Discover test plans ───────────────────────────────── + discover-plans: + name: Discover E2E Plans + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.scan.outputs.matrix }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Scan test plans + id: scan + shell: bash + run: | + plans=$(ls test/e2e-plans/*.yaml | xargs -n1 basename | sed 's/\.yaml$//' | jq -R . | jq -sc .) + echo "matrix=$plans" >> "$GITHUB_OUTPUT" + echo "Found plans: $plans" + + # ── Build VSIX (Linux) ────────────────────────────────── + build-linux: + name: Build VSIX (Linux) + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Install VSCE + run: npm install -g @vscode/vsce + + - name: Build OSGi bundle + run: npm run build-server + + - name: Build VSIX file + run: vsce package -o vscode-java-dependency.vsix + + - name: Upload VSIX artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vsix-linux + path: vscode-java-dependency.vsix + retention-days: 1 + + # ── Build VSIX (Windows) ──────────────────────────────── + build-windows: + name: Build VSIX (Windows) + runs-on: windows-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 20 + + - name: Install Node.js modules + run: npm install + + - name: Install VSCE + run: npm install -g @vscode/vsce + + - name: Build OSGi bundle + run: npm run build-server + + - name: Build VSIX file + run: vsce package -o vscode-java-dependency.vsix + + - name: Upload VSIX artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vsix-windows + path: vscode-java-dependency.vsix + retention-days: 1 + + # ── E2E plans (Linux) — depends only on Linux build ───── + e2e-linux: + name: E2E Linux (${{ matrix.plan }}) + needs: [ build-linux, discover-plans ] + runs-on: ubuntu-latest + timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + plan: ${{ fromJson(needs.discover-plans.outputs.matrix) }} + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 22 + + - name: Setup autotest + run: npm install -g @vscjava/vscode-autotest + + - name: Download VSIX artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: vsix-linux + path: . + + - name: E2E Test — ${{ matrix.plan }} + shell: bash + env: + AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} + AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_DEPLOYMENT: ${{ secrets.AZURE_OPENAI_DEPLOYMENT }} + run: | + # Use 1920x1080 so the Java Projects view gets enough vertical space. + xvfb-run -a -s "-screen 0 1920x1080x24" \ + autotest run "test/e2e-plans/${{ matrix.plan }}.yaml" \ + --vsix "$(pwd)/vscode-java-dependency.vsix" \ + --output "test-results/${{ matrix.plan }}" + + - name: Upload test results + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: e2e-results-linux-${{ matrix.plan }} + path: test-results/ + retention-days: 7 + + # ── E2E plans (Windows) — depends only on Windows build ─ + e2e-windows: + name: E2E Windows (${{ matrix.plan }}) + needs: [ build-windows, discover-plans ] + runs-on: windows-latest + timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + plan: ${{ fromJson(needs.discover-plans.outputs.matrix) }} + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 22 + + - name: Setup autotest + run: npm install -g @vscjava/vscode-autotest + + - name: Download VSIX artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: vsix-windows + path: . + + - name: E2E Test — ${{ matrix.plan }} + shell: pwsh + env: + AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} + AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_DEPLOYMENT: ${{ secrets.AZURE_OPENAI_DEPLOYMENT }} + run: | + autotest run "test/e2e-plans/${{ matrix.plan }}.yaml" --vsix "$((Get-Location).Path)\vscode-java-dependency.vsix" --output "test-results\${{ matrix.plan }}" + + - name: Upload test results + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: e2e-results-windows-${{ matrix.plan }} + path: test-results/ + retention-days: 7 + + # ── Unified analysis across both OSes ─────────────────── + analyze: + name: E2E Summary + needs: [ e2e-linux, e2e-windows ] + if: ${{ always() }} + runs-on: ubuntu-latest + steps: + - name: Setup Node.js environment + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 22 + + - name: Setup autotest + run: npm install -g @vscjava/vscode-autotest + + - name: Download all plan results + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: e2e-results-* + path: all-results + merge-multiple: false + + - name: Organize results (prefix each plan by OS) + shell: bash + run: | + mkdir -p test-results + for dir in all-results/e2e-results-linux-*/; do + [ -d "$dir" ] || continue + find "$dir" -name "results.json" -exec dirname {} \; | while read d; do + name=$(basename "$d") + mkdir -p "test-results/linux-$name" + cp -r "$d"/. "test-results/linux-$name"/ + done + done + for dir in all-results/e2e-results-windows-*/; do + [ -d "$dir" ] || continue + find "$dir" -name "results.json" -exec dirname {} \; | while read d; do + name=$(basename "$d") + mkdir -p "test-results/windows-$name" + cp -r "$d"/. "test-results/windows-$name"/ + done + done + echo "Organized plan result directories:" + ls test-results/ || true + + - name: Analyze results + env: + AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} + AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_DEPLOYMENT: ${{ secrets.AZURE_OPENAI_DEPLOYMENT }} + run: autotest analyze test-results --output test-results + + - name: Write Job Summary + if: always() + shell: bash + run: | + if [ -f test-results/summary.md ]; then + cat test-results/summary.md >> "$GITHUB_STEP_SUMMARY" + fi + + - name: Upload aggregate summary + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: e2e-aggregate-summary + path: test-results/summary.md + retention-days: 30 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 6cec9f67..f2ec7b3d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Setup Build Environment run: | @@ -21,15 +21,16 @@ jobs: sudo /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & sleep 3 - - name: Set up JDK 17 - uses: actions/setup-java@v1 + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: - java-version: '17' + distribution: 'temurin' + java-version: '21' - name: Setup Node.js environment - uses: actions/setup-node@v2 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 16 + node-version: 20 - name: Install Node.js modules run: npm install diff --git a/.github/workflows/linuxUI.yml b/.github/workflows/linuxUI.yml deleted file mode 100644 index 0fb228c7..00000000 --- a/.github/workflows/linuxUI.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - linuxUI: - name: Linux-UI - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v2 - - - 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 17 - uses: actions/setup-java@v1 - with: - java-version: '17' - - - name: Setup Node.js environment - uses: actions/setup-node@v2 - with: - node-version: 16 - - - name: Install Node.js modules - run: npm install - - - name: Install VSCE - run: npm install -g vsce - - - name: Build OSGi bundle - run: npm run build-server - - - name: Build VSIX file - run: vsce package - - - name: UI Test - continue-on-error: true - id: test - run: DISPLAY=:99 npm run test-ui - - - name: Retry UI Test 1 - continue-on-error: true - if: steps.test.outcome=='failure' - id: retry1 - run: | - git reset --hard - git clean -fd - DISPLAY=:99 npm run test-ui - - - name: Retry UI Test 2 - continue-on-error: true - if: steps.retry1.outcome=='failure' - id: retry2 - run: | - git reset --hard - git clean -fd - DISPLAY=:99 npm run test-ui - - - name: Set test status - if: ${{ steps.test.outcome=='failure' && steps.retry1.outcome=='failure' && steps.retry2.outcome=='failure' }} - run: | - echo "Tests failed" - exit 1 - - - name: Print language server Log - if: ${{ failure() }} - run: find ./test-resources/settings/User/workspaceStorage/*/redhat.java/jdt_ws/.metadata/.log -print -exec cat '{}' \;; diff --git a/.github/workflows/macOS.yml b/.github/workflows/macOS.yml index 85a934a3..b2a87373 100644 --- a/.github/workflows/macOS.yml +++ b/.github/workflows/macOS.yml @@ -12,17 +12,18 @@ jobs: runs-on: macos-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Set up JDK 17 - uses: actions/setup-java@v1 + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: - java-version: '17' + distribution: 'temurin' + java-version: '21' - name: Setup Node.js environment - uses: actions/setup-node@v2 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 16 + node-version: 20 - name: Install Node.js modules run: npm install diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index a29ebc24..9edc36f6 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -16,10 +16,10 @@ jobs: permissions: issues: write steps: - - uses: lee-dohm/no-response@9bb0a4b5e6a45046f00353d5de7d90fb8bd773bb + - uses: lee-dohm/no-response@9bb0a4b5e6a45046f00353d5de7d90fb8bd773bb # v0.5.0 with: token: ${{ github.token }} daysUntilClose: 14 - responseRequiredLabel: "need more info" + responseRequiredLabel: "needs more info" 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. \ No newline at end of file + 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..82d239dd --- /dev/null +++ b/.github/workflows/triage-agent.yml @@ -0,0 +1,125 @@ +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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Get issue data + id: get_issue + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + 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-dependency", + "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..9d2fd063 --- /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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + 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: 'asc', + 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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + 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/.github/workflows/windows.yml b/.github/workflows/windows.yml index fee79b90..59cca68f 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -12,17 +12,18 @@ jobs: runs-on: windows-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Set up JDK 17 - uses: actions/setup-java@v1 + - name: Set up JDK 21 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: - java-version: '17' + distribution: 'temurin' + java-version: '21' - name: Setup Node.js environment - uses: actions/setup-node@v2 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 16 + node-version: 20 - name: Install Node.js modules run: npm install diff --git a/.github/workflows/windowsUI.yml b/.github/workflows/windowsUI.yml deleted file mode 100644 index be506d36..00000000 --- a/.github/workflows/windowsUI.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - windowsUI: - name: Windows-UI - runs-on: windows-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v2 - - - name: Set up JDK 17 - uses: actions/setup-java@v1 - with: - java-version: '17' - - - name: Setup Node.js environment - uses: actions/setup-node@v2 - with: - node-version: 16 - - - name: Install Node.js modules - run: npm install - - - name: Install VSCE - run: npm install -g vsce - - - name: Lint - run: npm run tslint - - - name: Checkstyle - working-directory: .\jdtls.ext - run: .\mvnw.cmd checkstyle:check - - - name: Build OSGi bundle - run: npm run build-server - - - name: Build VSIX file - run: vsce package - - - name: UI Test - continue-on-error: true - id: test - run: npm run test-ui - - - name: Retry UI Test 1 - continue-on-error: true - if: steps.test.outcome=='failure' - id: retry1 - run: | - git reset --hard - git clean -fd - npm run test-ui - - - name: Retry UI Test 2 - continue-on-error: true - if: steps.retry1.outcome=='failure' - id: retry2 - run: | - git reset --hard - git clean -fd - npm run test-ui - - - name: Set test status - if: ${{ steps.test.outcome=='failure' && steps.retry1.outcome=='failure' && steps.retry2.outcome=='failure' }} - run: | - echo "Tests failed" - exit 1 - - - name: Print language server Log if job failed - if: ${{ failure() }} - run: Get-ChildItem -Path ./test-resources/settings/User/workspaceStorage/*/redhat.java/jdt_ws/.metadata/.log | cat diff --git a/.vscode/launch.json b/.vscode/launch.json index 57261f9f..7e154613 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,7 @@ { "type": "java", "name": "Attach to Plugin", + "projectName": "com.microsoft.jdtls.ext.core", "request": "attach", "hostName": "localhost", "port": 1044 diff --git a/.vscodeignore b/.vscodeignore index 8a6df51d..f3a42313 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -23,3 +23,9 @@ test-resources # Ignore output of code sign server/*.md +**/*.log + +# Local env / autotest artifacts +.env +.env.* +test-results/** diff --git a/CHANGELOG.md b/CHANGELOG.md index 02f3bb79..e0f5287a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,89 @@ All notable changes to the "vscode-java-dependency" extension will be documented 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). +## 0.27.6 + +- enhancement - Prefer Java upgrade over CVE in dependency recommendations in https://github.com/microsoft/vscode-java-dependency/pull/1033 +- enhancement - Improve Java upgrade telemetry tracking and extension installation flow in https://github.com/microsoft/vscode-java-dependency/pull/1030 +- perf - Improve Java LSP tool result handoff in https://github.com/microsoft/vscode-java-dependency/pull/1031 +- fix - Refresh now surfaces externally-generated files in new packages in https://github.com/microsoft/vscode-java-dependency/pull/1026 + +## 0.27.5 + +- fix - Check GHCP modernization version before call gotoAgentMode command in https://github.com/microsoft/vscode-java-dependency/pull/1022 +- perf - Tune Java LSP tool selection guidance in https://github.com/microsoft/vscode-java-dependency/pull/1020 + +## 0.27.4 + +- fix - Implement LSP tools for stable builds in https://github.com/microsoft/vscode-java-dependency/pull/1014 + +## 0.27.3 + +- feat - Enable Copilot LLM tools / chat skills / chat instructions in stable builds +- perf - Narrow to Java project to show the explorer in https://github.com/microsoft/vscode-java-dependency/pull/1010 +- perf - Use incremental build by default in https://github.com/microsoft/vscode-java-dependency/pull/998 +- feat - Add `revealInProjectExplorer` command in https://github.com/microsoft/vscode-java-dependency/pull/996 +- fix - Support Unicode identifiers in Java class name validation in https://github.com/microsoft/vscode-java-dependency/pull/993 +- fix - Adjust parameter to require the right name for file uri in https://github.com/microsoft/vscode-java-dependency/pull/1000 + +## 0.27.2 + +- perf - Progressive project tree view during import in https://github.com/microsoft/vscode-java-dependency/pull/982 + +## 0.27.1 + +- Enhancement - Update upgrade prompt after merging extension in https://github.com/microsoft/vscode-java-dependency/pull/971 + +## 0.27.0 + +- feat - Add CVE checking to notify users to fix the critical/high-severity CVE issues in https://github.com/microsoft/vscode-java-dependency/pull/948 + +## 0.26.5 + +- Enhancement - Register Context Provider after Java LS ready in https://github.com/microsoft/vscode-java-dependency/pull/939 +- Fix - Fix uri parse and file parse in https://github.com/microsoft/vscode-java-dependency/pull/940 + +## 0.26.4 + +- Fix - Update wording for Java 21 in https://github.com/microsoft/vscode-java-dependency/pull/930 +- Enhancement - throttling telemetry event in context provider https://github.com/microsoft/vscode-java-dependency/pull/936 +- Enhancement - optimizing javadoc from binary and filter common 3rd lib https://github.com/microsoft/vscode-java-dependency/pull/931 +- Fix - unblocking activation of extension while registering copilot context provider https://github.com/microsoft/vscode-java-dependency/pull/937 + +## 0.26.3 + +- Enhancement - Register Context Provider to Copilot in https://github.com/microsoft/vscode-java-dependency/pull/924 +- Enhancement - Adjust format to getProjectInfo method in https://github.com/microsoft/vscode-java-dependency/pull/927 +- Enhancement - Add cache to getProjectInfo in https://github.com/microsoft/vscode-java-dependency/pull/925 + +## 0.26.2 + +- Enhancement - Add getProjectInfo method to collect project info in https://github.com/microsoft/vscode-java-dependency/pull/919 + +## 0.26.1 + +- fix - Calculate package version range for upgrade by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/910 + +## 0.26.0 + +- feat - Add getImportClassContent method to collect import class info by @wenytang-ms in https://github.com/microsoft/vscode-java-dependency/pull/907 + +## 0.25.2 + +- ux - Improve wording on project modernization by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/912 +- ux - Check extension existence on-the-fly when needed by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/911 + +## 0.25.0 +- feat - Remind users to upgrade old (<21) Java and EOL Spring Boot/Framework versions by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/901 +- feat - Improve ProjectCommand.getMainClasses by @snjeza in https://github.com/microsoft/vscode-java-dependency/pull/883 + +## 0.24.1 +* Graal Cloud Native Launcher extension renamed. by @dbalek in https://github.com/microsoft/vscode-java-dependency/pull/849 +* ux - display maven and gradle dependencies with pattern 'groupId:artifactId:version ' by @mamilic in https://github.com/microsoft/vscode-java-dependency/pull/859 + +## New Contributors +* @mamilic made their first contribution in https://github.com/microsoft/vscode-java-dependency/pull/859 + ## 0.24.0 * feat - Support adding new package from file explorer by @jdneo in https://github.com/microsoft/vscode-java-dependency/pull/845 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..9917e21e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,37 @@ +# How to Contribute + +We greatly appreciate contributions to the vscode-java-dependency project. Your efforts help us maintain and improve this extension. To ensure a smooth contribution process, please follow these guidelines. + +## Prerequisites +- [JDK](https://www.oracle.com/java/technologies/downloads/?er=221886) +- [Node.JS](https://nodejs.org/en/) +- [VSCode](https://code.visualstudio.com/) + +## Build and Run + +To set up the vscode-java-dependency project, follow these steps: + +1. **Build the Server JAR**: + - The server JAR (Java application) is located in the [jdtls.ext](./jdtls.ext) directory. + - Run the following command to build the server: + ```shell + npm run build-server + ``` + +2. **Install Dependencies**: + - Execute the following command to install the necessary dependencies: + ```shell + npm install + ``` + +3. **Run/Debug the Extension**: + - Open the "Run and Debug" view in Visual Studio Code. + - Run the "Run Extension" task. + +4. **Attach to Plugin[Debug Java]**: + - Prerequisite: Ensure that the extension is activated, meaning the Java process is already launched. This is required for the task to run properly. + - Open the "Run and Debug" view in Visual Studio Code. + - Run the "Attach to Plugin" task. + - Note: This task is required only if you want to debug Java code [jdtls.ext](./jdtls.ext). It requires the [vscode-pde](https://marketplace.visualstudio.com/items?itemName=yaozheng.vscode-pde) extension to be installed. + +Thank you for your contributions and support! \ No newline at end of file diff --git a/README.md b/README.md index 805b8e76..6fc1881c 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,20 @@ You can tell that the glob pattern is supported. And here's more - you can incl } ``` +### Stay Secure and Up to Date + +Project Manager for Java keeps an eye on your project's Java runtime and dependencies, so you don't have to track them yourself. When it spots something worth your attention, it offers a one-click recommendation to fix it: + +- **Upgrade recommendations** – Get notified when your Java runtime or libraries are out of date, deprecated, or have reached end of life, along with a suggested target version. +- **Security recommendations** – Get alerted when known vulnerabilities (CVEs) are detected in your dependencies, so you can address them before they become a problem. + +When you accept a recommendation, the upgrade or fix is carried out for you by the [GitHub Copilot app modernization](https://marketplace.visualstudio.com/items?itemName=vscjava.migrate-java-to-azure) extension. If the extension isn't installed yet, it will be set up automatically as part of the flow. + +You can turn these reminders on or off at any time with the `java.dependency.enableDependencyCheckup` setting. + ## Requirements -- VS Code (version 1.83.1+) +- VS Code (version 1.95.0+) - [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) @@ -70,6 +81,7 @@ You can tell that the glob pattern is supported. And here's more - you can incl | `java.dependency.autoRefresh` | Specify whether to automatically sync the change from editor to the Java Projects explorer. | `true` | | `java.dependency.refreshDelay` | The delay time (ms) the auto refresh is invoked when changes are detected. | `2000ms` | | `java.dependency.packagePresentation` | Specify how to display the package. Supported values are: `flat`, `hierarchical`.| `flat` | +| `java.dependency.enableDependencyCheckup` | Show reminders when your Java runtimes or dependencies need an upgrade. | `true` | | `java.project.exportJar.targetPath` | The output path of export jar. When this setting is **empty** , a file explorer will pop up to let the user select the output location.| `${workspaceFolder}/${workspaceFolderBasename}.jar` | | `java.project.explorer.showNonJavaResources` | When enabled, the explorer shows non-Java resources. | `true` | diff --git a/jdtls.ext/.mvn/wrapper/maven-wrapper.jar b/jdtls.ext/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 41c70a7e..00000000 Binary files a/jdtls.ext/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/jdtls.ext/.mvn/wrapper/maven-wrapper.properties b/jdtls.ext/.mvn/wrapper/maven-wrapper.properties index 9e0264d0..2b8cd3d6 100644 --- a/jdtls.ext/.mvn/wrapper/maven-wrapper.properties +++ b/jdtls.ext/.mvn/wrapper/maven-wrapper.properties @@ -1 +1 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip \ No newline at end of file +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/META-INF/MANIFEST.MF b/jdtls.ext/com.microsoft.jdtls.ext.core/META-INF/MANIFEST.MF index 5bba4389..0503367f 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/META-INF/MANIFEST.MF +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: JDTLS EXT Core Bundle-SymbolicName: com.microsoft.jdtls.ext.core;singleton:=true -Bundle-Version: 0.24.0 +Bundle-Version: 0.24.1 Bundle-Activator: com.microsoft.jdtls.ext.core.JdtlsExtActivator Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-ActivationPolicy: lazy diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/plugin.xml b/jdtls.ext/com.microsoft.jdtls.ext.core/plugin.xml index 0352e983..4966a319 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/plugin.xml +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/plugin.xml @@ -10,6 +10,9 @@ + + + com.microsoft.jdtls.ext jdtls-ext-parent - 0.24.0 + 0.24.1 com.microsoft.jdtls.ext.core eclipse-plugin diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/AiContextCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/AiContextCommand.java new file mode 100644 index 00000000..3b2a166f --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/AiContextCommand.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2018 Microsoft Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Microsoft Corporation - initial API and implementation + *******************************************************************************/ + +package com.microsoft.jdtls.ext.core; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IImportDeclaration; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.ls.core.internal.JDTUtils; + +import com.microsoft.jdtls.ext.core.model.FileImportsResult; +import com.microsoft.jdtls.ext.core.model.FileImportsResult.ImportEntry; +import com.microsoft.jdtls.ext.core.model.FileImportsResult.StaticImportEntry; + +/** + * Lightweight command handler for AI context tools. + * All methods in this class are designed to be non-blocking and fast (< 10ms). + * They only read AST-level information and do NOT trigger classpath resolution, + * type resolution, or any expensive JDT operations. + */ +public class AiContextCommand { + + // Well-known JDK package prefixes + private static final Set JDK_PREFIXES = new HashSet<>(); + static { + JDK_PREFIXES.add("java."); + JDK_PREFIXES.add("javax."); + JDK_PREFIXES.add("jdk."); + JDK_PREFIXES.add("sun."); + JDK_PREFIXES.add("com.sun."); + JDK_PREFIXES.add("org.xml."); + JDK_PREFIXES.add("org.w3c."); + JDK_PREFIXES.add("jakarta."); // Jakarta EE (post Java EE) + } + + /** + * Get the classified import list of a Java file. + * This is a lightweight AST-only operation — it reads import declarations + * without doing any type resolution (findType) or classpath resolution. + * + * Typical response time: < 5ms + * + * @param arguments List containing the file URI as the first element + * @param monitor Progress monitor for cancellation support + * @return FileImportsResult with classified imports + */ + public static FileImportsResult getFileImports(List arguments, IProgressMonitor monitor) { + FileImportsResult result = new FileImportsResult(); + result.imports = new ArrayList<>(); + result.staticImports = new ArrayList<>(); + + if (arguments == null || arguments.isEmpty()) { + result.error = "No arguments provided"; + return result; + } + + try { + String fileUri = (String) arguments.get(0); + if (fileUri == null || fileUri.trim().isEmpty()) { + result.error = "Invalid file URI"; + return result; + } + + // Resolve compilation unit from URI — this is fast, just a model lookup + java.net.URI uri = JDTUtils.toURI(fileUri); + ICompilationUnit compilationUnit = JDTUtils.resolveCompilationUnit(uri); + + if (compilationUnit == null || !compilationUnit.exists()) { + result.error = "File not found or not a Java file: " + fileUri; + return result; + } + + // Get project-relative file path (strip the leading project segment + // from the Eclipse workspace-relative path, e.g. "/my-project/src/Foo.java" → "src/Foo.java") + IJavaProject javaProject = compilationUnit.getJavaProject(); + result.file = compilationUnit.getPath().removeFirstSegments(1).toString(); + + // Collect project source package names for classification + Set projectPackages = collectProjectPackages(javaProject); + + // Read import declarations — pure AST operation, no type resolution + IImportDeclaration[] imports = compilationUnit.getImports(); + if (imports == null || imports.length == 0) { + return result; // No imports, return empty (not an error) + } + + for (IImportDeclaration imp : imports) { + if (monitor.isCanceled()) { + break; + } + + String name = imp.getElementName(); + boolean isStatic = Flags.isStatic(imp.getFlags()); + boolean isOnDemand = name.endsWith(".*"); + + if (isStatic) { + StaticImportEntry entry = new StaticImportEntry(); + entry.name = name; + entry.memberKind = "unknown"; // Would need findType to know — skip + entry.source = classifyByPackageName(name, projectPackages); + result.staticImports.add(entry); + } else { + ImportEntry entry = new ImportEntry(); + entry.name = name; + entry.kind = "unknown"; // Would need findType to know — skip + entry.source = classifyByPackageName(name, projectPackages); + entry.artifact = null; // Would need classpath attributes — skip for now + entry.isOnDemand = isOnDemand; + result.imports.add(entry); + } + } + + return result; + + } catch (Exception e) { + JdtlsExtActivator.logException("Error in getFileImports", e); + result.error = "Exception: " + e.getMessage(); + return result; + } + } + + /** + * Classify an import by its package name prefix. + * This is a heuristic — no type resolution involved. + * + * @param qualifiedName the fully qualified name of the import + * @param projectPackages set of package names found in the project's source roots + * @return "jdk", "project", or "external" + */ + private static String classifyByPackageName(String qualifiedName, Set projectPackages) { + // Check JDK + for (String prefix : JDK_PREFIXES) { + if (qualifiedName.startsWith(prefix)) { + return "jdk"; + } + } + + // Check project packages + String packageName = getPackageName(qualifiedName); + if (packageName != null && projectPackages.contains(packageName)) { + return "project"; + } + + // Check if any project package is a prefix of this import + for (String projPkg : projectPackages) { + if (qualifiedName.startsWith(projPkg + ".")) { + return "project"; + } + } + + return "external"; + } + + /** + * Get the package name from a fully qualified name. + * e.g., "com.example.model.Order" → "com.example.model" + * "com.example.model.*" → "com.example.model" + */ + private static String getPackageName(String qualifiedName) { + if (qualifiedName == null) { + return null; + } + // Handle wildcard imports + if (qualifiedName.endsWith(".*")) { + return qualifiedName.substring(0, qualifiedName.length() - 2); + } + int lastDot = qualifiedName.lastIndexOf('.'); + if (lastDot > 0) { + return qualifiedName.substring(0, lastDot); + } + return null; + } + + /** + * Collect all package names that exist in the project's source roots. + * This uses getPackageFragmentRoots(K_SOURCE) which is fast — it reads + * the project model, not the filesystem. + */ + private static Set collectProjectPackages(IJavaProject javaProject) { + Set packages = new HashSet<>(); + if (javaProject == null) { + return packages; + } + + try { + IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); + for (IPackageFragmentRoot root : roots) { + if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { + org.eclipse.jdt.core.IJavaElement[] children = root.getChildren(); + for (org.eclipse.jdt.core.IJavaElement child : children) { + if (child instanceof org.eclipse.jdt.core.IPackageFragment) { + String pkgName = child.getElementName(); + if (pkgName != null && !pkgName.isEmpty()) { + packages.add(pkgName); + } + } + } + } + } + } catch (Exception e) { + // Non-critical — fall back to treating everything as external + JdtlsExtActivator.logException("Error collecting project packages", e); + } + + return packages; + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/CommandHandler.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/CommandHandler.java index 5d395719..49db346f 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/CommandHandler.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/CommandHandler.java @@ -37,6 +37,12 @@ public Object executeCommand(String commandId, List arguments, IProgress return ProjectCommand.exportJar(arguments, monitor); case "java.project.checkImportStatus": return ProjectCommand.checkImportStatus(); + case "java.project.getImportClassContent": + return ProjectCommand.getImportClassContent(arguments, monitor); + case "java.project.getDependencies": + return ProjectCommand.getProjectDependencies(arguments, monitor); + case "java.project.getFileImports": + return AiContextCommand.getFileImports(arguments, monitor); default: break; } diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java index 1bb2e99b..9baf72fb 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java @@ -14,7 +14,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -78,7 +80,7 @@ public class PackageCommand { private static final Map>> commands; static { - commands = new HashMap<>(); + commands = new EnumMap<>(NodeKind.class); commands.put(NodeKind.PROJECT, PackageCommand::getProjectChildren); commands.put(NodeKind.CONTAINER, PackageCommand::getContainerChildren); commands.put(NodeKind.PACKAGEROOT, PackageCommand::getPackageRootChildren); @@ -370,7 +372,7 @@ private static List getPackageRootChildren(PackageParams query, IPr throw new CoreException( new Status(IStatus.ERROR, JdtlsExtActivator.PLUGIN_ID, String.format("No package root found for %s", query.getPath()))); } - List result = getPackageFragmentRootContent(packageRoot, query.isHierarchicalView(), pm); + List result = getPackageFragmentRootContent(packageRoot, query.isHierarchicalView(), query.getSyncPaths(), pm); ResourceSet resourceSet = new ResourceSet(result, query.isHierarchicalView()); ResourceVisitor visitor = new JavaResourceVisitor(packageRoot.getJavaProject()); resourceSet.accept(visitor); @@ -507,8 +509,62 @@ private static List getFolderChildren(PackageParams query, IProgres * @param pm the progress monitor */ public static List getPackageFragmentRootContent(IPackageFragmentRoot root, boolean isHierarchicalView, IProgressMonitor pm) throws CoreException { + return getPackageFragmentRootContent(root, isHierarchicalView, null, pm); + } + + public static List getPackageFragmentRootContent(IPackageFragmentRoot root, boolean isHierarchicalView, List syncPaths, IProgressMonitor pm) throws CoreException { ArrayList result = new ArrayList<>(); - refreshLocal(root.getResource(), pm); + IResource rootResource = root.getResource(); + if (rootResource instanceof IContainer && rootResource.exists() + && root.getKind() == IPackageFragmentRoot.K_SOURCE) { + // Packages created out-of-band (e.g. by code generators or + // refactor-moves that write straight to disk) are otherwise never + // surfaced. A shallow DEPTH_ONE refresh only syncs the source root's + // immediate children and never discovers brand-new nested package + // folders. Even a DEPTH_INFINITE resource refresh is not enough on + // its own: the Java Model keeps a cached list of package fragments + // for the root, so closing it forces getChildren() below to rebuild + // that list from the freshly refreshed resource tree. + // + // On auto-refresh the client passes the changed resource URIs in + // syncPaths so we only deep-refresh those subtrees instead of the + // whole source tree. If any path cannot be resolved to an existing + // resource inside this root we conservatively fall back to a full + // DEPTH_INFINITE refresh so no package is ever missed. + // See https://github.com/microsoft/vscode-java-dependency/issues/914 + boolean refreshedTargets = false; + if (syncPaths != null && !syncPaths.isEmpty()) { + Set targets = new LinkedHashSet<>(); + boolean allResolved = true; + for (String syncPath : syncPaths) { + IResource target = findNearestExistingResource(syncPath, (IContainer) rootResource); + if (target == null) { + allResolved = false; + break; + } + // Multiple changed paths can resolve to the same existing + // ancestor (e.g. several new files in one new package); the + // set keeps each distinct subtree so it is refreshed once. + targets.add(target); + } + if (allResolved && !targets.isEmpty()) { + for (IResource target : targets) { + refreshLocal(target, IResource.DEPTH_INFINITE, pm); + } + refreshedTargets = true; + } + } + if (!refreshedTargets) { + refreshLocal(rootResource, IResource.DEPTH_INFINITE, pm); + } + try { + root.close(); + } catch (JavaModelException e) { + JdtlsExtActivator.log(e); + } + } else { + refreshLocal(rootResource, IResource.DEPTH_ONE, pm); + } if (isHierarchicalView) { Map map = new HashMap<>(); for (IJavaElement child : root.getChildren()) { @@ -598,13 +654,56 @@ public static IJavaProject getJavaProject(String projectUri) { } private static void refreshLocal(IResource resource, IProgressMonitor monitor) { + refreshLocal(resource, IResource.DEPTH_ONE, monitor); + } + + private static void refreshLocal(IResource resource, int depth, IProgressMonitor monitor) { if (resource == null || !resource.exists()) { return; } try { - resource.refreshLocal(IResource.DEPTH_ONE, monitor); + resource.refreshLocal(depth, monitor); } catch (CoreException e) { JdtlsExtActivator.log(e); } } + + /** + * Resolve a changed resource URI to the nearest ancestor that already exists + * in the workspace resource tree and lives inside the given source root. + * Used to scope an auto-refresh to only the affected subtree. Returns null + * when the URI cannot be mapped to a resource within the root, in which case + * the caller falls back to a full refresh so no package is missed. + */ + private static IResource findNearestExistingResource(String uriStr, IContainer root) { + if (StringUtils.isBlank(uriStr) || root == null) { + return null; + } + try { + URI uri = JDTUtils.toURI(uriStr); + if (uri == null) { + return null; + } + IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); + IResource resource = null; + IFile[] files = wsRoot.findFilesForLocationURI(uri); + if (files.length > 0) { + resource = files[0]; + } else { + IContainer[] containers = wsRoot.findContainersForLocationURI(uri); + if (containers.length > 0) { + resource = containers[0]; + } + } + while (resource != null && !resource.exists()) { + resource = resource.getParent(); + } + if (resource != null && root.getFullPath().isPrefixOf(resource.getFullPath())) { + return resource; + } + } catch (Exception e) { + JdtlsExtActivator.logException("Failed to resolve sync path " + uriStr, e); + } + return null; + } } diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageParams.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageParams.java index 4b6468ed..576563c5 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageParams.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageParams.java @@ -11,6 +11,8 @@ package com.microsoft.jdtls.ext.core; +import java.util.List; + import com.microsoft.jdtls.ext.core.model.NodeKind; /** @@ -31,6 +33,14 @@ public class PackageParams { private boolean isHierarchicalView; + /** + * Optional list of resource URIs (sent by the client on auto-refresh) that + * have just changed on disk. When present, the server only refreshes the + * affected subtrees instead of deeply refreshing the whole source root. + * See https://github.com/microsoft/vscode-java-dependency/issues/914 + */ + private List syncPaths; + public PackageParams() { } @@ -97,4 +107,12 @@ public void setRootPath(String rootPath) { this.rootPath = rootPath; } + public List getSyncPaths() { + return syncPaths; + } + + public void setSyncPaths(List syncPaths) { + this.syncPaths = syncPaths; + } + } diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java index 1c89a202..75c8b4b5 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -41,14 +42,11 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; -import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IModuleDescription; -import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.search.IJavaSearchConstants; @@ -59,6 +57,7 @@ import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.core.search.SearchRequestor; import org.eclipse.jdt.launching.JavaRuntime; +import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; import org.eclipse.jdt.ls.core.internal.ProjectUtils; import org.eclipse.jdt.ls.core.internal.ResourceUtils; @@ -70,6 +69,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.microsoft.jdtls.ext.core.parser.ContextResolver; +import com.microsoft.jdtls.ext.core.parser.ContextResolver.ImportClassInfo; +import com.microsoft.jdtls.ext.core.parser.ProjectResolver; import com.microsoft.jdtls.ext.core.model.PackageNode; public final class ProjectCommand { @@ -86,6 +88,142 @@ public MainClassInfo(String name, String path) { } } + private static class DependencyInfo { + public String key; + public String value; + + public DependencyInfo(String key, String value) { + this.key = key; + this.value = value; + } + } + + /** + * Empty reasons for ImportClassContent operation + */ + public enum ImportClassContentErrorReason { + NULL_ARGUMENTS("NullArgs"), + INVALID_URI("InvalidURI"), + URI_PARSE_FAILED("ParseFail"), + FILE_NOT_FOUND("NotFound"), + FILE_NOT_EXISTS("NotExists"), + NOT_JAVA_PROJECT("NotJava"), + PROJECT_NOT_EXISTS("ProjNotExists"), + NOT_COMPILATION_UNIT("NotCU"), + NO_IMPORTS("NoImports"), + OPERATION_CANCELLED("Cancelled"), + TIME_LIMIT_EXCEEDED("Timeout"), + NO_RESULTS("NoResults"), + PROCESSING_EXCEPTION("Error"); + + private final String message; + + ImportClassContentErrorReason(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + + /** + * Empty reasons for ProjectDependencies operation + */ + public enum ProjectDependenciesErrorReason { + NULL_ARGUMENTS("NullArgs"), + INVALID_URI("InvalidURI"), + URI_PARSE_FAILED("ParseFail"), + MALFORMED_URI("MalformedURI"), + OPERATION_CANCELLED("Cancelled"), + RESOLVER_NULL_RESULT("ResolverNull"), + NO_DEPENDENCIES("NoDeps"), + PROCESSING_EXCEPTION("Error"); + + private final String message; + + ProjectDependenciesErrorReason(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + + /** + * Error context information for operations + */ + public static class ErrorContext { + public final String errorValue; // The value that caused the error (e.g., invalid URI, null parsedPath, etc.) + + public ErrorContext(String errorValue) { + this.errorValue = errorValue; + } + } + + /** + * Result wrapper for getImportClassContent method + */ + public static class ImportClassContentResult { + public List classInfoList; + public String emptyReason; // Reason why the result is empty + public boolean isEmpty; + public ErrorContext errorContext; // Error context (only set when isEmpty = true) + + public ImportClassContentResult(List classInfoList) { + this.classInfoList = classInfoList; + this.emptyReason = null; + this.isEmpty = false; + this.errorContext = null; + } + + public ImportClassContentResult(ImportClassContentErrorReason errorReason) { + this.classInfoList = Collections.emptyList(); + this.emptyReason = errorReason.getMessage(); // Use enum message + this.isEmpty = true; + this.errorContext = null; + } + + public ImportClassContentResult(ImportClassContentErrorReason errorReason, String errorValue) { + this.classInfoList = Collections.emptyList(); + this.emptyReason = errorReason.getMessage(); + this.isEmpty = true; + this.errorContext = new ErrorContext(errorValue); + } + } + + /** + * Result wrapper for getProjectDependencies method + */ + public static class ProjectDependenciesResult { + public List dependencyInfoList; + public String emptyReason; // Reason why the result is empty + public boolean isEmpty; + public ErrorContext errorContext; // Error context (only set when isEmpty = true) + + public ProjectDependenciesResult(List dependencyInfoList) { + this.dependencyInfoList = dependencyInfoList; + this.emptyReason = null; + this.isEmpty = false; + this.errorContext = null; + } + + public ProjectDependenciesResult(ProjectDependenciesErrorReason errorReason) { + this.dependencyInfoList = new ArrayList<>(); + this.emptyReason = errorReason.getMessage(); // Use enum message + this.isEmpty = true; + this.errorContext = null; + } + + public ProjectDependenciesResult(ProjectDependenciesErrorReason errorReason, String errorValue) { + this.dependencyInfoList = new ArrayList<>(); + this.emptyReason = errorReason.getMessage(); + this.isEmpty = true; + this.errorContext = new ErrorContext(errorValue); + } + } + private static class Classpath { public String source; public String destination; @@ -108,7 +246,7 @@ public static List listProjects(List arguments, IProgressMo projects = ProjectUtils.getAllProjects(); } else { projects = Arrays.stream(ProjectUtils.getJavaProjects()) - .map(IJavaProject::getProject).toArray(IProject[]::new); + .map(IJavaProject::getProject).toArray(IProject[]::new); } ArrayList children = new ArrayList<>(); @@ -200,11 +338,14 @@ private static boolean exportJarExecution(String mainClass, Classpath[] classpat } if (classpath.isArtifact) { MultiStatus resultStatus = writeArchive(new ZipFile(classpath.source), - /* areDirectoryEntriesIncluded = */true, /* isCompressed = */true, target, directories, monitor); + /* areDirectoryEntriesIncluded = */true, /* isCompressed = */true, target, directories, + monitor); int severity = resultStatus.getSeverity(); if (severity == IStatus.OK) { java.nio.file.Path path = java.nio.file.Paths.get(classpath.source); - reportExportJarMessage(terminalId, IStatus.OK, "Successfully extracted the file to the exported jar: " + path.getFileName().toString()); + reportExportJarMessage(terminalId, IStatus.OK, + "Successfully extracted the file to the exported jar: " + + path.getFileName().toString()); continue; } if (resultStatus.isMultiStatus()) { @@ -216,9 +357,13 @@ private static boolean exportJarExecution(String mainClass, Classpath[] classpat } } else { try { - writeFile(new File(classpath.source), new Path(classpath.destination), /* areDirectoryEntriesIncluded = */true, - /* isCompressed = */true, target, directories); - reportExportJarMessage(terminalId, IStatus.OK, "Successfully added the file to the exported jar: " + classpath.destination); + writeFile(new File(classpath.source), new Path(classpath.destination), /* + * areDirectoryEntriesIncluded + * = + */true, + /* isCompressed = */true, target, directories); + reportExportJarMessage(terminalId, IStatus.OK, + "Successfully added the file to the exported jar: " + classpath.destination); } catch (CoreException e) { reportExportJarMessage(terminalId, IStatus.ERROR, e.getMessage()); } @@ -231,24 +376,34 @@ private static boolean exportJarExecution(String mainClass, Classpath[] classpat return true; } - public static List getMainClasses(List arguments, IProgressMonitor monitor) throws Exception { - List projectList = listProjects(arguments, monitor); - final List res = new ArrayList<>(); - List searchRoots = new ArrayList<>(); + public static List getMainClasses(List arguments, IProgressMonitor monitor) + throws Exception { + List args = new ArrayList<>(arguments); + if (args.size() <= 1) { + args.add(Boolean.TRUE); + } else { + args.set(1, Boolean.TRUE); + } + List projectList = listProjects(args, monitor); if (projectList.size() == 0) { - return res; + return Collections.emptyList(); } + final List res = new ArrayList<>(); + List javaProjects = new ArrayList<>(); for (PackageNode project : projectList) { IJavaProject javaProject = PackageCommand.getJavaProject(project.getUri()); - for (IPackageFragmentRoot packageFragmentRoot : javaProject.getAllPackageFragmentRoots()) { - if (!packageFragmentRoot.isArchive()) { - searchRoots.add(packageFragmentRoot); - } + if (javaProject != null && javaProject.exists()) { + javaProjects.add(javaProject); } } - IJavaSearchScope scope = SearchEngine.createJavaSearchScope(searchRoots.toArray(new IJavaElement[0])); - SearchPattern pattern = SearchPattern.createPattern("main(String[]) void", IJavaSearchConstants.METHOD, - IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); + int includeMask = IJavaSearchScope.SOURCES; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(javaProjects.toArray(new IJavaProject[0]), + includeMask); + SearchPattern pattern1 = SearchPattern.createPattern("main(String[]) void", IJavaSearchConstants.METHOD, + IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CASE_SENSITIVE | SearchPattern.R_EXACT_MATCH); + SearchPattern pattern2 = SearchPattern.createPattern("main() void", IJavaSearchConstants.METHOD, + IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CASE_SENSITIVE | SearchPattern.R_EXACT_MATCH); + SearchPattern pattern = SearchPattern.createOrPattern(pattern1, pattern2); SearchRequestor requestor = new SearchRequestor() { @Override public void acceptSearchMatch(SearchMatch match) { @@ -274,8 +429,8 @@ public void acceptSearchMatch(SearchMatch match) { }; SearchEngine searchEngine = new SearchEngine(); try { - searchEngine.search(pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, - requestor, new NullProgressMonitor()); + searchEngine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, + requestor, monitor); } catch (CoreException e) { // ignore } @@ -321,11 +476,162 @@ public static boolean checkImportStatus() { return hasError; } + /** + * Get import class content for Copilot integration. + * This method extracts information about imported classes from a Java file. + * Uses a time-controlled strategy: prioritizes internal classes, adds external + * classes only if time permits. + * + * @param arguments List containing the file URI as the first element + * @param monitor Progress monitor for cancellation support + * @return List of ImportClassInfo containing class information and JavaDoc + */ + public static ImportClassContentResult getImportClassContent(List arguments, + IProgressMonitor monitor) { + // Record start time for timeout control + long startTime = System.currentTimeMillis(); + final long TIMEOUT_MS = 80; // 80ms timeout + + if (arguments == null || arguments.isEmpty()) { + return new ImportClassContentResult(ImportClassContentErrorReason.NULL_ARGUMENTS); + } + + try { + String fileUri = (String) arguments.get(0); + if (fileUri == null || fileUri.trim().isEmpty()) { + return new ImportClassContentResult(ImportClassContentErrorReason.INVALID_URI, fileUri); + } + + // Directly resolve compilation unit from URI using JDTUtils + java.net.URI uri = JDTUtils.toURI(fileUri); + org.eclipse.jdt.core.ICompilationUnit compilationUnit = JDTUtils.resolveCompilationUnit(uri); + + if (compilationUnit == null || !compilationUnit.exists()) { + return new ImportClassContentResult(ImportClassContentErrorReason.FILE_NOT_FOUND, fileUri); + } + + // Get the Java project from the compilation unit + IJavaProject javaProject = compilationUnit.getJavaProject(); + if (javaProject == null || !javaProject.exists()) { + String projectName = javaProject != null && javaProject.getProject() != null + ? javaProject.getProject().getName() + : "unknown"; + return new ImportClassContentResult(ImportClassContentErrorReason.PROJECT_NOT_EXISTS, projectName); + } + + // Parse imports and resolve local project files + List classInfoList = new ArrayList<>(); + + // Get all imports from the compilation unit + org.eclipse.jdt.core.IImportDeclaration[] imports = compilationUnit.getImports(); + Set processedTypes = new HashSet<>(); + + // Check if file has no imports + if (imports == null || imports.length == 0) { + return new ImportClassContentResult(ImportClassContentErrorReason.NO_IMPORTS); + } + + // Phase 1: Priority - Resolve project source classes (internal) + for (org.eclipse.jdt.core.IImportDeclaration importDecl : imports) { + // Check cancellation before each operation + if (monitor.isCanceled()) { + return new ImportClassContentResult(ImportClassContentErrorReason.OPERATION_CANCELLED); + } + + String importName = importDecl.getElementName(); + boolean isStatic = (importDecl.getFlags() & org.eclipse.jdt.core.Flags.AccStatic) != 0; + + if (isStatic) { + // Handle static imports - delegate to ContextResolver + ContextResolver.resolveStaticImport(javaProject, importName, classInfoList, processedTypes, + monitor); + } else if (importName.endsWith(".*")) { + // Handle package imports - delegate to ContextResolver + String packageName = importName.substring(0, importName.length() - 2); + ContextResolver.resolvePackageTypes(javaProject, packageName, classInfoList, processedTypes, + monitor); + } else { + // Handle single type imports - delegate to ContextResolver + ContextResolver.resolveSingleType(javaProject, importName, classInfoList, processedTypes, monitor); + } + } + + // Phase 2: Resolve external dependencies if not cancelled and within time limit + if (!monitor.isCanceled()) { + // Check if we have exceeded the timeout before starting external resolution + long currentTime = System.currentTimeMillis(); + long elapsedTime = currentTime - startTime; + + if (elapsedTime >= TIMEOUT_MS) { + // Return early due to timeout, but still return what we have collected so far + if (classInfoList.isEmpty()) { + return new ImportClassContentResult(ImportClassContentErrorReason.TIME_LIMIT_EXCEEDED, + String.valueOf(elapsedTime) + "ms"); + } + return new ImportClassContentResult(classInfoList); + } + + List externalClasses = new ArrayList<>(); + + for (org.eclipse.jdt.core.IImportDeclaration importDecl : imports) { + // Check cancellation before each external resolution + if (monitor.isCanceled()) { + break; + } + + // Check timeout before each external resolution + currentTime = System.currentTimeMillis(); + elapsedTime = currentTime - startTime; + if (elapsedTime >= TIMEOUT_MS) { + // Timeout reached, stop processing external dependencies but keep existing + // results + break; + } + + String importName = importDecl.getElementName(); + boolean isStatic = (importDecl.getFlags() & org.eclipse.jdt.core.Flags.AccStatic) != 0; + + // Skip package imports (*.* ) - too broad for external dependencies + if (importName.endsWith(".*")) { + continue; + } + + // Resolve external (binary) types with simplified content + if (!isStatic) { + ContextResolver.resolveBinaryType(javaProject, importName, externalClasses, + processedTypes, Integer.MAX_VALUE, monitor); + } + } + + // Append external classes after project sources + classInfoList.addAll(externalClasses); + } + // Success case - return the resolved class information + if (classInfoList.isEmpty()) { + return new ImportClassContentResult(ImportClassContentErrorReason.NO_RESULTS); + } + return new ImportClassContentResult(classInfoList); + + } catch (Exception e) { + JdtlsExtActivator.logException("Error in getImportClassContent", e); + // Try to get context from arguments if available + String errorUri = null; + try { + if (arguments != null && !arguments.isEmpty()) { + errorUri = (String) arguments.get(0); + } + } catch (Exception ignored) { + // Ignore any further exceptions when trying to get context + } + return new ImportClassContentResult(ImportClassContentErrorReason.PROCESSING_EXCEPTION, errorUri); + } + } + private static void reportExportJarMessage(String terminalId, int severity, String message) { if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(terminalId)) { String readableSeverity = getSeverityString(severity); JavaLanguageServerPlugin.getInstance().getClientConnection().executeClientCommand(COMMAND_EXPORT_JAR_REPORT, - terminalId, "[" + readableSeverity + "] " + message); + terminalId, "[" + readableSeverity + "] " + message); } } @@ -346,6 +652,76 @@ private static String getSeverityString(int severity) { } } + /** + * Get project dependencies information including JDK version. + * + * @param arguments List containing the file URI as the first element + * @param monitor Progress monitor for cancellation support + * @return List of DependencyInfo containing key-value pairs of project + * information + */ + public static ProjectDependenciesResult getProjectDependencies(List arguments, + IProgressMonitor monitor) { + if (arguments == null || arguments.isEmpty()) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.NULL_ARGUMENTS); + } + + try { + String fileUri = (String) arguments.get(0); + if (fileUri == null || fileUri.trim().isEmpty()) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.INVALID_URI, fileUri); + } + + // Validate URI format using JDTUtils + try { + java.net.URI uri = JDTUtils.toURI(fileUri); + if (uri == null) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.URI_PARSE_FAILED, fileUri); + } + } catch (Exception e) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.MALFORMED_URI, fileUri); + } + + // Check if monitor is cancelled before processing + if (monitor.isCanceled()) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.OPERATION_CANCELLED); + } + List resolverResult = ProjectResolver.resolveProjectDependencies(fileUri, + monitor); + // Check if resolver returned null (should not happen, but defensive + // programming) + if (resolverResult == null) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.RESOLVER_NULL_RESULT); + } + // Convert ProjectResolver.DependencyInfo to ProjectCommand.DependencyInfo + List result = new ArrayList<>(); + for (ProjectResolver.DependencyInfo info : resolverResult) { + if (info != null) { + result.add(new DependencyInfo(info.key, info.value)); + } + } + + // Check if no dependencies were resolved + if (result.isEmpty()) { + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.NO_DEPENDENCIES); + } + + return new ProjectDependenciesResult(result); + } catch (Exception e) { + JdtlsExtActivator.logException("Error in getProjectDependenciesWithReason", e); + // Try to get context from arguments if available + String errorUri = null; + try { + if (arguments != null && !arguments.isEmpty()) { + errorUri = (String) arguments.get(0); + } + } catch (Exception ignored) { + // Ignore any further exceptions when trying to get context + } + return new ProjectDependenciesResult(ProjectDependenciesErrorReason.PROCESSING_EXCEPTION, errorUri); + } + } + private static final class LinkedFolderVisitor implements IResourceVisitor { private boolean belongsToWorkspace; diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ClassDetailResult.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ClassDetailResult.java new file mode 100644 index 00000000..1c050cdc --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ClassDetailResult.java @@ -0,0 +1,49 @@ +package com.microsoft.jdtls.ext.core.model; + +import java.util.List; + +/** + * L1: Detailed class information. + * AI calls this for specific classes it needs to understand, not for all imports. + */ +public class ClassDetailResult { + + public String qualifiedName; // "com.example.model.Order" + public String kind; // "class" | "interface" | "enum" | "annotation" + public String uri; // file URI (for project source) or jar URI + public String source; // "project" | "external" | "jdk" + public String artifact; // GAV for external: "com.google.code.gson:gson:2.10.1" + + public String signature; // "public class Order implements Serializable" + public String superClass; // "java.lang.Object" (null if Object) + public List interfaces; // ["java.io.Serializable"] + public List annotations; // ["@Entity", "@Table(name = \"orders\")"] + + public String javadocSummary; // First sentence only, null if none + + public List constructors; // ["Order()", "Order(String orderId, Customer customer)"] + public List methods; // ["String getOrderId()", "void setStatus(OrderStatus)"] + public List fields; // ["private String orderId", "private List items"] + + public int totalMethodCount; // actual total (methods list may be truncated) + public int totalFieldCount; // actual total + + public String error; // null if success + + /** + * Builder-style static factories for common cases + */ + public static ClassDetailResult notFound(String qualifiedName) { + ClassDetailResult r = new ClassDetailResult(); + r.qualifiedName = qualifiedName; + r.error = "Type not found: " + qualifiedName; + return r; + } + + public static ClassDetailResult error(String qualifiedName, String message) { + ClassDetailResult r = new ClassDetailResult(); + r.qualifiedName = qualifiedName; + r.error = message; + return r; + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/DependencyDetailsResult.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/DependencyDetailsResult.java new file mode 100644 index 00000000..dc373de8 --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/DependencyDetailsResult.java @@ -0,0 +1,37 @@ +package com.microsoft.jdtls.ext.core.model; + +import java.util.List; + +/** + * L1: Detailed dependency information with query filtering. + * AI calls this when it needs to investigate specific dependencies. + */ +public class DependencyDetailsResult { + + public List dependencies; + public String error; // null if success + + public static class DependencyEntry { + public String groupId; // "com.google.code.gson" + public String artifactId; // "gson" + public String version; // "2.10.1" + public String scope; // "compile" | "test" | "runtime" | "provided" | "system" + public boolean isDirect; // true = declared in pom.xml/build.gradle + public String broughtBy; // for transitive: "com.google.guava:guava:32.1.3-jre" + public String jarFileName; // "gson-2.10.1.jar" + + public DependencyEntry() {} + + public DependencyEntry(String groupId, String artifactId, String version, + String scope, boolean isDirect, String broughtBy, + String jarFileName) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.scope = scope; + this.isDirect = isDirect; + this.broughtBy = broughtBy; + this.jarFileName = jarFileName; + } + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/FileImportsResult.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/FileImportsResult.java new file mode 100644 index 00000000..5ef31fdc --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/FileImportsResult.java @@ -0,0 +1,46 @@ +package com.microsoft.jdtls.ext.core.model; + +import java.util.List; + +/** + * L0: Import list for a Java file. + * Returns classified imports without expanding class details. + */ +public class FileImportsResult { + + public String file; // project-relative file path (e.g. "src/main/java/com/example/Foo.java") + public List imports; + public List staticImports; + public String error; // null if success + + public static class ImportEntry { + public String name; // fully qualified name: "com.example.model.Order" + public String kind; // "class" | "interface" | "enum" | "annotation" | "unknown" + public String source; // "project" | "external" | "jdk" + public String artifact; // only for "external": "spring-context", null for others + public boolean isOnDemand; // true for wildcard imports (e.g. "import com.example.model.*") + + public ImportEntry() {} + + public ImportEntry(String name, String kind, String source, String artifact) { + this.name = name; + this.kind = kind; + this.source = source; + this.artifact = artifact; + } + } + + public static class StaticImportEntry { + public String name; // "org.junit.Assert.assertEquals" + public String memberKind; // "method" | "field" | "unknown" + public String source; // "project" | "external" | "jdk" + + public StaticImportEntry() {} + + public StaticImportEntry(String name, String memberKind, String source) { + this.name = name; + this.memberKind = memberKind; + this.source = source; + } + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java index 7f146d8d..92fa4cf7 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.Objects; +import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -273,11 +274,32 @@ public static PackageRootNode createNodeForPackageFragmentRoot(IPackageFragmentR for (IClasspathAttribute attribute : resolvedClasspathEntry.getExtraAttributes()) { node.setMetaDataValue(attribute.getName(), attribute.getValue()); } + + String computedDisplayName = computeDisplayName(node); + if (StringUtils.isNotBlank(computedDisplayName)) { + node.setDisplayName(computedDisplayName); + } } return node; } + private static String computeDisplayName(PackageRootNode node) { + if (node.getMetaData() == null || node.getMetaData().isEmpty()) { + return node.getName(); + } + + String version = (String) node.getMetaData().get("maven.version"); + String groupId = (String) node.getMetaData().get("maven.groupId"); + String artifactId = (String) node.getMetaData().get("maven.artifactId"); + + if (StringUtils.isBlank(version) || StringUtils.isBlank(groupId) || StringUtils.isBlank(artifactId)) { + return node.getName(); + } + + return groupId + ":" + artifactId + ":" + version; + } + /** * Get the correspond node of classpath, it may be container or a package root. * diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ProjectContextResult.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ProjectContextResult.java new file mode 100644 index 00000000..113c0c9f --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/ProjectContextResult.java @@ -0,0 +1,42 @@ +package com.microsoft.jdtls.ext.core.model; + +/** + * Structured result models for Java Context Tools. + * These models are designed for AI consumption — small, structured, layered. + * + * Design principles: + * 1. Each result should serialize to < 200 tokens of JSON + * 2. Use structured fields instead of freeform text + * 3. Only include information the AI actually needs at this granularity level + */ + +import java.util.List; + +/** + * L0: Project-level context overview. + * First thing AI should request when entering a Java project. + */ +public class ProjectContextResult { + + public ProjectMeta project; + public DependencySummary dependencies; + public List projectReferences; + public String error; // null if success + + public static class ProjectMeta { + public String name; + public String buildTool; // "Maven" | "Gradle" | "Unknown" + public String javaVersion; // compiler compliance level + public String sourceLevel; + public String targetLevel; + public List sourceRoots; // relative paths: ["src/main/java", "src/test/java"] + public String moduleName; // Java module name, null if not modular + } + + public static class DependencySummary { + public int total; + public int directCount; + public int transitiveCount; + public List direct; // GAV strings: ["group:artifact:version", ...] + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ContextResolver.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ContextResolver.java new file mode 100644 index 00000000..77c04010 --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ContextResolver.java @@ -0,0 +1,1514 @@ +/******************************************************************************* + * Copyright (c) 2018 Microsoft Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Microsoft Corporation - initial API and implementation + *******************************************************************************/ + +package com.microsoft.jdtls.ext.core.parser; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.ls.core.internal.JDTUtils; + +import com.microsoft.jdtls.ext.core.JdtlsExtActivator; + +/** + * Parser for extracting Java class content information for Copilot integration. + * Handles import resolution, JavaDoc extraction, and class description generation. + */ +public class ContextResolver { + + // Pre-compiled regex patterns for performance + private static final Pattern MARKDOWN_CODE_PATTERN = Pattern.compile("(?s)```(?:java)?\\n?(.*?)```"); + private static final Pattern HTML_PRE_PATTERN = Pattern.compile("(?is)]*>(.*?)"); + private static final Pattern HTML_CODE_PATTERN = Pattern.compile("(?is)]*>(.*?)"); + + // Constants for limiting displayed members + private static final int MAX_METHODS_TO_DISPLAY = 10; + private static final int MAX_FIELDS_TO_DISPLAY = 10; + private static final int MAX_STATIC_METHODS_TO_DISPLAY = 10; + private static final int MAX_STATIC_FIELDS_TO_DISPLAY = 10; + + // Common JDK packages to skip (Copilot already has good understanding of these) + // These are well-known packages whose classes don't need to be extracted from JARs + private static final Set SKIP_COMMON_JDK_PACKAGES = new HashSet<>(); + static { + // Core Java packages - Copilot has excellent understanding of these + SKIP_COMMON_JDK_PACKAGES.add("java.lang"); // Object, String, Integer, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.util"); // Collections, List, Map, Set, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.io"); // File, InputStream, Reader, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.nio"); // ByteBuffer, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.nio.file"); // Path, Paths, Files + SKIP_COMMON_JDK_PACKAGES.add("java.time"); // LocalDate, LocalDateTime, Instant, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.util.concurrent"); // ExecutorService, Future, CompletableFuture, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.util.stream"); // Stream, Collectors + SKIP_COMMON_JDK_PACKAGES.add("java.util.function"); // Function, Consumer, Supplier, Predicate + SKIP_COMMON_JDK_PACKAGES.add("java.net"); // URL, URI, HttpURLConnection + SKIP_COMMON_JDK_PACKAGES.add("java.util.regex"); // Pattern, Matcher + SKIP_COMMON_JDK_PACKAGES.add("java.math"); // BigDecimal, BigInteger + SKIP_COMMON_JDK_PACKAGES.add("java.text"); // DateFormat, SimpleDateFormat, etc. + SKIP_COMMON_JDK_PACKAGES.add("java.sql"); // Connection, ResultSet, etc. + SKIP_COMMON_JDK_PACKAGES.add("javax.sql"); // DataSource, etc. + + // Java EE / Jakarta EE - Well-known enterprise packages + SKIP_COMMON_JDK_PACKAGES.add("javax.servlet"); // Servlet API + SKIP_COMMON_JDK_PACKAGES.add("javax.annotation"); // @PostConstruct, @PreDestroy, etc. + SKIP_COMMON_JDK_PACKAGES.add("javax.persistence"); // JPA annotations + SKIP_COMMON_JDK_PACKAGES.add("javax.inject"); // @Inject + SKIP_COMMON_JDK_PACKAGES.add("javax.validation"); // Bean Validation + SKIP_COMMON_JDK_PACKAGES.add("jakarta.servlet"); // Jakarta Servlet + SKIP_COMMON_JDK_PACKAGES.add("jakarta.persistence"); // Jakarta JPA + + // Spring Framework - Extremely common and well-documented + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.stereotype"); // @Component, @Service, @Repository, @Controller + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.beans"); // @Autowired, BeanFactory + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.context"); // ApplicationContext, @Configuration + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.web.bind"); // @RequestMapping, @PathVariable, etc. + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.boot"); // SpringApplication, @SpringBootApplication + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.data.jpa"); // JpaRepository + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.data.repository"); // CrudRepository + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.transaction"); // @Transactional + SKIP_COMMON_JDK_PACKAGES.add("org.springframework.security"); // Spring Security annotations + + // Testing frameworks - Very common and well-documented + SKIP_COMMON_JDK_PACKAGES.add("org.junit"); // JUnit 4/5 - @Test, assertions + SKIP_COMMON_JDK_PACKAGES.add("org.junit.jupiter"); // JUnit 5 specific + SKIP_COMMON_JDK_PACKAGES.add("org.testng"); // TestNG + SKIP_COMMON_JDK_PACKAGES.add("org.mockito"); // Mockito - mock(), when(), verify() + SKIP_COMMON_JDK_PACKAGES.add("org.assertj"); // AssertJ fluent assertions + SKIP_COMMON_JDK_PACKAGES.add("org.hamcrest"); // Hamcrest matchers + + // Lombok - Code generation library (Copilot understands these annotations very well) + SKIP_COMMON_JDK_PACKAGES.add("lombok"); // @Data, @Getter, @Setter, @Builder, etc. + + // Logging frameworks - Very standard APIs + SKIP_COMMON_JDK_PACKAGES.add("org.slf4j"); // SLF4J - Logger, LoggerFactory + SKIP_COMMON_JDK_PACKAGES.add("org.apache.logging.log4j"); // Log4j 2 + SKIP_COMMON_JDK_PACKAGES.add("org.apache.log4j"); // Log4j 1.x + SKIP_COMMON_JDK_PACKAGES.add("java.util.logging"); // JUL - java.util.logging + + // Jackson - JSON processing (very common) + SKIP_COMMON_JDK_PACKAGES.add("com.fasterxml.jackson.annotation"); // @JsonProperty, @JsonIgnore + SKIP_COMMON_JDK_PACKAGES.add("com.fasterxml.jackson.core"); // JsonParser, JsonGenerator + SKIP_COMMON_JDK_PACKAGES.add("com.fasterxml.jackson.databind"); // ObjectMapper + + // Google Guava - Well-known utility library + SKIP_COMMON_JDK_PACKAGES.add("com.google.common.collect"); // ImmutableList, ImmutableMap, etc. + SKIP_COMMON_JDK_PACKAGES.add("com.google.common.base"); // Preconditions, Strings, etc. + + // Apache Commons - Well-known utility libraries + SKIP_COMMON_JDK_PACKAGES.add("org.apache.commons.lang3"); // StringUtils, etc. + SKIP_COMMON_JDK_PACKAGES.add("org.apache.commons.collections4"); // CollectionUtils + SKIP_COMMON_JDK_PACKAGES.add("org.apache.commons.io"); // IOUtils, FileUtils + } + + /** + * ImportClassInfo - Conforms to Copilot CodeSnippet format + * Used to provide Java class context information and JavaDoc to Copilot + */ + public static class ImportClassInfo { + public String uri; // File URI (required) + public String value; // Human-readable class description with JavaDoc appended (required) + + public ImportClassInfo(String uri, String value) { + this.uri = uri; + this.value = value; + } + } + + /** + * Resolve a single type import and extract its information + */ + public static void resolveSingleType(IJavaProject javaProject, String typeName, List classInfoList, + Set processedTypes, IProgressMonitor monitor) { + try { + // Check if already processed to avoid duplicates + if (processedTypes.contains(typeName)) { + return; + } + + // Extract package and simple name from the fully qualified type name + int lastDotIndex = typeName.lastIndexOf('.'); + if (lastDotIndex == -1) { + // Default package or invalid type name - mark as processed to avoid retry + processedTypes.add(typeName); + return; + } + + String packageName = typeName.substring(0, lastDotIndex); + String simpleName = typeName.substring(lastDotIndex + 1); + + // Strategy: Use JDT's global type resolution first (comprehensive), + // then fallback to manual package fragment traversal if needed + + // Primary path: Use JDT's findType which searches all sources and dependencies + try { + org.eclipse.jdt.core.IType type = javaProject.findType(typeName); + if (type != null && type.exists()) { + // Found type - check if it's a source type we want to process + if (!type.isBinary()) { + // Source type found - mark as processed and extract information + processedTypes.add(typeName); + extractTypeInfo(type, classInfoList, monitor); + return; + } + // Binary types (from JARs/JRE) found but not processed in Phase 1 + // Do NOT mark as processed - let Phase 2 handle them if triggered + return; + } + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error in primary type search: " + typeName, e); + // Continue to fallback method + } + + // Fallback path: Manual search in local source package fragments + // This is used when findType() doesn't return results or fails + IPackageFragmentRoot[] packageRoots = javaProject.getPackageFragmentRoots(); + for (IPackageFragmentRoot packageRoot : packageRoots) { + if (packageRoot.getKind() == IPackageFragmentRoot.K_SOURCE) { + org.eclipse.jdt.core.IPackageFragment packageFragment = packageRoot.getPackageFragment(packageName); + if (packageFragment != null && packageFragment.exists()) { + // Look for compilation unit with matching name + org.eclipse.jdt.core.ICompilationUnit cu = packageFragment.getCompilationUnit(simpleName + ".java"); + if (cu != null && cu.exists()) { + // Use JDTUtils to check if the compilation unit is accessible + String cuUri = JDTUtils.toUri(cu); + if (cuUri != null) { + // Get primary type from compilation unit + org.eclipse.jdt.core.IType primaryType = cu.findPrimaryType(); + if (primaryType != null && primaryType.exists() && + typeName.equals(primaryType.getFullyQualifiedName())) { + // Found local project source type via fallback method + processedTypes.add(typeName); + extractTypeInfo(primaryType, classInfoList, monitor); + return; + } + } + + // Also check for inner types in the compilation unit + org.eclipse.jdt.core.IType[] allTypes = cu.getAllTypes(); + for (org.eclipse.jdt.core.IType type : allTypes) { + if (typeName.equals(type.getFullyQualifiedName())) { + processedTypes.add(typeName); + extractTypeInfo(type, classInfoList, monitor); + return; + } + } + } + } + } + } + + // Type not found - mark as processed to avoid repeated failed lookups + processedTypes.add(typeName); + + } catch (JavaModelException e) { + // Log and mark as processed even on error to avoid repeated failures + JdtlsExtActivator.logException("Error resolving type: " + typeName, e); + processedTypes.add(typeName); + } + } + + /** + * Check if a type belongs to a common JDK package that should be skipped. + * Uses package-level matching for efficient filtering. + * + * @param typeName Fully qualified type name (e.g., "java.lang.String") + * @return true if the type is from a common JDK package + */ + private static boolean isCommonJdkType(String typeName) { + if (typeName == null || typeName.isEmpty()) { + return false; + } + + int lastDotIndex = typeName.lastIndexOf('.'); + if (lastDotIndex == -1) { + return false; + } + + String packageName = typeName.substring(0, lastDotIndex); + + // Check exact match or sub-package match + return SKIP_COMMON_JDK_PACKAGES.contains(packageName) || + SKIP_COMMON_JDK_PACKAGES.stream().anyMatch(pkg -> packageName.startsWith(pkg + ".")); + } + + /** + * Resolve a static import statement + */ + public static void resolveStaticImport(IJavaProject javaProject, String staticImportName, List classInfoList, + Set processedTypes, IProgressMonitor monitor) { + try { + if (staticImportName.endsWith(".*")) { + // Static import of all static members from a class: import static MyClass.*; + String className = staticImportName.substring(0, staticImportName.length() - 2); + resolveStaticMembersFromClass(javaProject, className, classInfoList, processedTypes, monitor); + } else { + // Static import of specific member: import static MyClass.myMethod; + int lastDotIndex = staticImportName.lastIndexOf('.'); + if (lastDotIndex > 0) { + String className = staticImportName.substring(0, lastDotIndex); + String memberName = staticImportName.substring(lastDotIndex + 1); + resolveStaticMemberFromClass(javaProject, className, memberName, classInfoList, processedTypes, monitor); + } + } + } catch (Exception e) { + JdtlsExtActivator.logException("Error resolving static import: " + staticImportName, e); + } + } + + /** + * Resolve all static members from a class + */ + public static void resolveStaticMembersFromClass(IJavaProject javaProject, String className, + List classInfoList, Set processedTypes, IProgressMonitor monitor) { + try { + // First resolve the class itself to get context information + resolveSingleType(javaProject, className, classInfoList, processedTypes, monitor); + + // Find the type and extract its static members + org.eclipse.jdt.core.IType type = javaProject.findType(className); + if (type != null && type.exists() && !type.isBinary()) { + StringBuilder description = new StringBuilder(); + description.append("Static Import: ").append(className).append(".*\n"); + description.append("All static members from ").append(className).append("\n\n"); + + // Get static methods + IMethod[] methods = type.getMethods(); + List staticMethodSigs = new ArrayList<>(); + for (IMethod method : methods) { + int flags = method.getFlags(); + if (org.eclipse.jdt.core.Flags.isStatic(flags) && org.eclipse.jdt.core.Flags.isPublic(flags)) { + if (staticMethodSigs.size() < MAX_STATIC_METHODS_TO_DISPLAY) { + staticMethodSigs.add(generateMethodSignature(method)); + } + } + } + + // Get static fields + org.eclipse.jdt.core.IField[] fields = type.getFields(); + List staticFieldSigs = new ArrayList<>(); + for (org.eclipse.jdt.core.IField field : fields) { + int flags = field.getFlags(); + if (org.eclipse.jdt.core.Flags.isStatic(flags) && org.eclipse.jdt.core.Flags.isPublic(flags)) { + if (staticFieldSigs.size() < MAX_STATIC_FIELDS_TO_DISPLAY) { + staticFieldSigs.add(generateFieldSignature(field)); + } + } + } + + if (!staticMethodSigs.isEmpty()) { + description.append("Static Methods:\n"); + for (String sig : staticMethodSigs) { + description.append(" - ").append(sig).append("\n"); + } + description.append("\n"); + } + + if (!staticFieldSigs.isEmpty()) { + description.append("Static Fields:\n"); + for (String sig : staticFieldSigs) { + description.append(" - ").append(sig).append("\n"); + } + } + + String uri = getTypeUri(type); + if (uri != null) { + classInfoList.add(new ImportClassInfo(uri, description.toString())); + } + } + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error resolving static members from: " + className, e); + } + } + + /** + * Resolve a specific static member from a class + */ + public static void resolveStaticMemberFromClass(IJavaProject javaProject, String className, String memberName, + List classInfoList, Set processedTypes, IProgressMonitor monitor) { + try { + // First resolve the class itself + resolveSingleType(javaProject, className, classInfoList, processedTypes, monitor); + + // Find the specific static member + org.eclipse.jdt.core.IType type = javaProject.findType(className); + if (type != null && type.exists() && !type.isBinary()) { + StringBuilder description = new StringBuilder(); + description.append("Static Import: ").append(className).append(".").append(memberName).append("\n\n"); + + boolean found = false; + + // Check if it's a method + IMethod[] methods = type.getMethods(); + for (IMethod method : methods) { + if (method.getElementName().equals(memberName)) { + int flags = method.getFlags(); + if (org.eclipse.jdt.core.Flags.isStatic(flags)) { + description.append("Static Method:\n"); + description.append(" - ").append(generateMethodSignature(method)).append("\n"); + found = true; + break; + } + } + } + + // Check if it's a field + if (!found) { + org.eclipse.jdt.core.IField[] fields = type.getFields(); + for (org.eclipse.jdt.core.IField field : fields) { + if (field.getElementName().equals(memberName)) { + int flags = field.getFlags(); + if (org.eclipse.jdt.core.Flags.isStatic(flags)) { + description.append("Static Field:\n"); + description.append(" - ").append(generateFieldSignature(field)).append("\n"); + found = true; + break; + } + } + } + } + + if (found) { + String uri = getTypeUri(type); + if (uri != null) { + classInfoList.add(new ImportClassInfo(uri, description.toString())); + } + } + } + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error resolving static member: " + className + "." + memberName, e); + } + } + + /** + * Resolve a binary type (from external JAR/JRE) with simplified content. + * This method is used for external dependencies when project sources are sparse. + * + * @param javaProject The Java project context + * @param typeName Fully qualified type name (e.g., "java.util.ArrayList") + * @param classInfoList List to append resolved class information + * @param processedTypes Set tracking already processed types to avoid duplicates + * @param maxMethods Maximum number of methods to include (to limit token usage) + * @param monitor Progress monitor for cancellation + */ + public static void resolveBinaryType(IJavaProject javaProject, String typeName, + List classInfoList, Set processedTypes, + int maxMethods, IProgressMonitor monitor) { + try { + if (processedTypes.contains(typeName)) { + return; + } + + // Performance optimization: Skip common JDK packages that Copilot already understands well + // This significantly reduces processing time for external dependencies + if (isCommonJdkType(typeName)) { + processedTypes.add(typeName); + return; + } + + // Use JDT's findType which searches all sources and dependencies + org.eclipse.jdt.core.IType type = javaProject.findType(typeName); + if (type == null || !type.exists()) { + return; + } + + // Only process binary types (from JARs/JRE) + if (!type.isBinary()) { + return; // Skip source types - they should be handled by resolveSingleType + } + + processedTypes.add(typeName); + + // Extract simplified information for binary types + extractBinaryTypeInfo(type, classInfoList, maxMethods, monitor); + + } catch (JavaModelException e) { + // Log but continue processing other types + JdtlsExtActivator.logException("Error resolving binary type: " + typeName, e); + } + } + + /** + * Resolve all types in a package (for wildcard imports) + */ + public static void resolvePackageTypes(IJavaProject javaProject, String packageName, List classInfoList, + Set processedTypes, IProgressMonitor monitor) { + try { + // Find all package fragments with this name + IPackageFragmentRoot[] packageRoots = javaProject.getPackageFragmentRoots(); + for (IPackageFragmentRoot packageRoot : packageRoots) { + if (packageRoot.getKind() == IPackageFragmentRoot.K_SOURCE) { + org.eclipse.jdt.core.IPackageFragment packageFragment = packageRoot.getPackageFragment(packageName); + if (packageFragment != null && packageFragment.exists()) { + // Get all compilation units in this package + org.eclipse.jdt.core.ICompilationUnit[] compilationUnits = packageFragment + .getCompilationUnits(); + for (org.eclipse.jdt.core.ICompilationUnit cu : compilationUnits) { + // Get all types in the compilation unit + org.eclipse.jdt.core.IType[] types = cu.getAllTypes(); + for (org.eclipse.jdt.core.IType type : types) { + String fullTypeName = type.getFullyQualifiedName(); + if (!processedTypes.contains(fullTypeName)) { + processedTypes.add(fullTypeName); + extractTypeInfo(type, classInfoList, monitor); + } + } + } + } + } + } + } catch (JavaModelException e) { + // Log but continue processing + JdtlsExtActivator.logException("Error resolving package: " + packageName, e); + } + } + + /** + * Extract type information and generate ImportClassInfo conforming to Copilot CodeSnippet format + * Also extracts JavaDoc if available and appends it to the class description + * Improved version: generates human-readable class descriptions with integrated JavaDoc + */ + public static void extractTypeInfo(org.eclipse.jdt.core.IType type, List classInfoList, + IProgressMonitor monitor) { + try { + // Get file URI + String uri = getTypeUri(type); + if (uri == null) { + return; + } + + // Extract relevant JavaDoc content first (code snippets with fallback strategy) + // This uses a hybrid approach: AST extraction -> HTML extraction -> Markdown extraction -> fallback + String relevantJavadoc = extractRelevantJavaDocContent(type, monitor); + + // Generate human-readable class description with JavaDoc inserted after signature + String description = generateClassDescription(type, relevantJavadoc); + + // Create ImportClassInfo (conforms to Copilot CodeSnippet format) + ImportClassInfo info = new ImportClassInfo(uri, description); + classInfoList.add(info); + + // Recursively process nested types + org.eclipse.jdt.core.IType[] nestedTypes = type.getTypes(); + for (org.eclipse.jdt.core.IType nestedType : nestedTypes) { + extractTypeInfo(nestedType, classInfoList, monitor); + } + + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error extracting type info for: " + type.getElementName(), e); + } + } + + /** + * Extract simplified information for binary types (external dependencies). + * This method extracts only essential information to reduce token usage: + * - Class signature (modifiers, name, generics, extends/implements) + * - Limited number of public methods (no implementation details) + * - Public fields (if any) + * - Basic class-level JavaDoc if available + * + * @param type Binary type from JAR/JRE + * @param classInfoList List to append resolved class information + * @param maxMethods Maximum number of methods to include + * @param monitor Progress monitor for cancellation + */ + public static void extractBinaryTypeInfo(org.eclipse.jdt.core.IType type, + List classInfoList, int maxMethods, IProgressMonitor monitor) { + try { + // Use a placeholder URI for binary types (they don't have local file paths) + String uri = "jar://" + type.getFullyQualifiedName().replace('.', '/') + ".class"; + + // Generate simplified class description for binary types + StringBuilder sb = new StringBuilder(); + + // 1. Extract class-level JavaDoc (brief summary only) + String javadoc = extractBriefJavaDoc(type); + if (javadoc != null && !javadoc.isEmpty()) { + sb.append("/**\n * ").append(javadoc).append("\n */\n"); + } + + // 2. Class signature (modifiers, name, generics, inheritance) + sb.append(generateClassSignature(type)); + sb.append(" {\n\n"); + + // 3. Public fields (limit to first 5) + org.eclipse.jdt.core.IField[] fields = type.getFields(); + int fieldCount = 0; + for (org.eclipse.jdt.core.IField field : fields) { + if (fieldCount >= 5) break; + if (org.eclipse.jdt.core.Flags.isPublic(field.getFlags())) { + sb.append(" ").append(generateBinaryFieldSignature(field)).append("\n"); + fieldCount++; + } + } + if (fieldCount > 0) { + sb.append("\n"); + } + + // 4. Public methods (limited by maxMethods parameter) + org.eclipse.jdt.core.IMethod[] methods = type.getMethods(); + int methodCount = 0; + for (org.eclipse.jdt.core.IMethod method : methods) { + if (methodCount >= maxMethods) break; + if (org.eclipse.jdt.core.Flags.isPublic(method.getFlags())) { + sb.append(" ").append(generateBinaryMethodSignature(method)).append("\n"); + methodCount++; + } + } + + sb.append("}\n"); + + // Add note indicating this is simplified external dependency info + sb.append("// Note: External dependency - showing simplified signature only\n"); + + // Create ImportClassInfo + ImportClassInfo info = new ImportClassInfo(uri, sb.toString()); + classInfoList.add(info); + + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error extracting binary type info for: " + type.getElementName(), e); + } + } + + /** + * Generate class signature with modifiers, name, generics, and inheritance + */ + private static String generateClassSignature(org.eclipse.jdt.core.IType type) throws JavaModelException { + StringBuilder sb = new StringBuilder(); + + // Modifiers + int flags = type.getFlags(); + if (org.eclipse.jdt.core.Flags.isPublic(flags)) sb.append("public "); + if (org.eclipse.jdt.core.Flags.isAbstract(flags) && !type.isInterface()) sb.append("abstract "); + if (org.eclipse.jdt.core.Flags.isFinal(flags)) sb.append("final "); + + // Type kind + if (type.isInterface()) { + sb.append("interface "); + } else if (type.isEnum()) { + sb.append("enum "); + } else if (type.isAnnotation()) { + sb.append("@interface "); + } else { + sb.append("class "); + } + + // Simple name + sb.append(type.getElementName()); + + // Type parameters + org.eclipse.jdt.core.ITypeParameter[] typeParams = type.getTypeParameters(); + if (typeParams != null && typeParams.length > 0) { + sb.append("<"); + for (int i = 0; i < typeParams.length; i++) { + if (i > 0) sb.append(", "); + sb.append(typeParams[i].getElementName()); + } + sb.append(">"); + } + + // Superclass + String superclass = type.getSuperclassName(); + if (superclass != null && !superclass.equals("Object") && !type.isInterface()) { + sb.append(" extends ").append(simplifyTypeName(superclass)); + } + + // Interfaces + String[] interfaces = type.getSuperInterfaceNames(); + if (interfaces != null && interfaces.length > 0) { + if (type.isInterface()) { + sb.append(" extends "); + } else { + sb.append(" implements "); + } + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) sb.append(", "); + sb.append(simplifyTypeName(interfaces[i])); + } + } + + return sb.toString(); + } + + /** + * Extract brief JavaDoc summary for binary types (first sentence only) + * Performance optimization: Skip JavaDoc extraction for binary types to avoid expensive I/O + */ + private static String extractBriefJavaDoc(org.eclipse.jdt.core.IType type) { + // Performance optimization: Skip JavaDoc extraction for binary types + // getAttachedJavadoc() is expensive - may involve JAR reading, network downloads, HTML parsing + if (type.isBinary()) { + return null; + } + + try { + String javadoc = type.getAttachedJavadoc(null); + if (javadoc == null || javadoc.isEmpty()) { + return null; + } + return getFirstSentenceOrLimit(javadoc, 120); + } catch (Exception e) { + return null; + } + } + + /** + * Generate simplified field signature for binary types + */ + private static String generateBinaryFieldSignature(org.eclipse.jdt.core.IField field) { + return generateFieldSignatureInternal(field, true); + } + + /** + * Generate simplified method signature for binary types (no implementation) + */ + private static String generateBinaryMethodSignature(org.eclipse.jdt.core.IMethod method) { + return generateMethodSignatureInternal(method, true, false); + } + + /** + * Get file URI/path for the type (instead of fully qualified class name) + */ + public static String getTypeUri(org.eclipse.jdt.core.IType type) { + try { + // Get the compilation unit that contains this type + org.eclipse.jdt.core.ICompilationUnit compilationUnit = type.getCompilationUnit(); + if (compilationUnit != null) { + // Use JDTUtils to get URI (consistent with other parts of the codebase) + String uri = JDTUtils.toUri(compilationUnit); + if (uri != null) { + return uri; + } + } + + // For class files (binary types), try to get URI from class file + org.eclipse.jdt.core.IClassFile classFile = type.getClassFile(); + if (classFile != null) { + String uri = JDTUtils.toUri(classFile); + if (uri != null) { + return uri; + } + } + + // Fallback: if we can't get file URI, return the fully qualified class name + // This should rarely happen for source types + return type.getFullyQualifiedName(); + } catch (Exception e) { + JdtlsExtActivator.logException("Error getting file URI for type: " + type.getElementName(), e); + // Fallback to class name in case of error + try { + return type.getFullyQualifiedName(); + } catch (Exception e2) { + return null; + } + } + } + + /** + * Generate complete class description (natural language format, similar to JavaDoc) + * @param type the Java type to describe + * @param javadoc optional JavaDoc content to insert after signature (can be null or empty) + */ + public static String generateClassDescription(org.eclipse.jdt.core.IType type, String javadoc) { + StringBuilder description = new StringBuilder(); + + try { + String qualifiedName = type.getFullyQualifiedName(); + String simpleName = type.getElementName(); + + // === 1. Title and signature === + description.append("Class: ").append(qualifiedName).append("\n"); + + // Generate class signature + StringBuilder signature = new StringBuilder(); + int flags = type.getFlags(); + + if (org.eclipse.jdt.core.Flags.isPublic(flags)) signature.append("public "); + if (org.eclipse.jdt.core.Flags.isAbstract(flags)) signature.append("abstract "); + if (org.eclipse.jdt.core.Flags.isFinal(flags)) signature.append("final "); + + if (type.isInterface()) { + signature.append("interface "); + } else if (type.isEnum()) { + signature.append("enum "); + } else if (type.isAnnotation()) { + signature.append("@interface "); + } else { + signature.append("class "); + } + + signature.append(simpleName); + + // Type parameters + String[] typeParams = type.getTypeParameterSignatures(); + if (typeParams != null && typeParams.length > 0) { + signature.append("<"); + for (int i = 0; i < typeParams.length; i++) { + if (i > 0) signature.append(", "); + signature.append(convertTypeSignature(typeParams[i])); + } + signature.append(">"); + } + + // Inheritance relationship + String superclass = type.getSuperclassName(); + if (superclass != null && !superclass.equals("Object") && !type.isInterface()) { + signature.append(" extends ").append(superclass); + } + + // Implemented interfaces + String[] interfaces = type.getSuperInterfaceNames(); + if (interfaces != null && interfaces.length > 0) { + if (type.isInterface()) { + signature.append(" extends "); + } else { + signature.append(" implements "); + } + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) signature.append(", "); + signature.append(interfaces[i]); + } + } + + description.append("Signature: ").append(signature).append("\n\n"); + + // === 2. JavaDoc (inserted after signature) === + if (isNotEmpty(javadoc)) { + description.append("JavaDoc:\n").append(javadoc).append("\n\n"); + } + + // === 3. Constructors === + IMethod[] methods = type.getMethods(); + List constructorSigs = new ArrayList<>(); + + for (IMethod method : methods) { + if (method.isConstructor()) { + constructorSigs.add(generateMethodSignature(method)); + } + } + + if (!constructorSigs.isEmpty()) { + description.append("Constructors:\n"); + for (String sig : constructorSigs) { + description.append(" - ").append(sig).append("\n"); + } + description.append("\n"); + } + + // === 4. Public methods (limited to first 10) === + List methodSigs = new ArrayList<>(); + int methodCount = 0; + + for (IMethod method : methods) { + if (!method.isConstructor() && org.eclipse.jdt.core.Flags.isPublic(method.getFlags())) { + if (methodCount < MAX_METHODS_TO_DISPLAY) { + methodSigs.add(generateMethodSignature(method)); + methodCount++; + } else { + break; + } + } + } + + if (!methodSigs.isEmpty()) { + description.append("Methods:\n"); + for (String sig : methodSigs) { + description.append(" - ").append(sig).append("\n"); + } + if (methodCount == MAX_METHODS_TO_DISPLAY && methods.length > methodCount) { + description.append(" - ... (more methods available)\n"); + } + description.append("\n"); + } + + // === 5. Public fields (limited to first 10) === + org.eclipse.jdt.core.IField[] fields = type.getFields(); + List fieldSigs = new ArrayList<>(); + int fieldCount = 0; + + for (org.eclipse.jdt.core.IField field : fields) { + if (org.eclipse.jdt.core.Flags.isPublic(field.getFlags()) && fieldCount < MAX_FIELDS_TO_DISPLAY) { + fieldSigs.add(generateFieldSignature(field)); + fieldCount++; + } + } + + if (!fieldSigs.isEmpty()) { + description.append("Fields:\n"); + for (String sig : fieldSigs) { + description.append(" - ").append(sig).append("\n"); + } + } + + } catch (JavaModelException e) { + return "Error generating description for type: " + e.getMessage(); + } + + return description.toString(); + } + + // ================ JavaDoc Extraction Methods ================ + + /** + * Extracts relevant JavaDoc content including description text and code snippets. + * This method extracts: + * 1. Class description (first paragraph of text) + * 2. Code snippets from ,
, and ``` blocks
+     * 3. @deprecated tag if present
+     *
+     * @param type the type to extract Javadoc from.
+     * @param monitor the progress monitor.
+     * @return A string containing description and code snippets in LLM-readable format.
+     */
+    private static String extractRelevantJavaDocContent(org.eclipse.jdt.core.IType type, IProgressMonitor monitor) {
+        try {
+            // Performance optimization: Skip JavaDoc extraction for binary types
+            // getAttachedJavadoc() is EXTREMELY expensive for binary types:
+            // - Requires reading from JAR files (I/O overhead)
+            // - May trigger Maven artifact download from remote repositories (network)
+            // - Involves HTML parsing and DOM manipulation (CPU intensive)
+            // Binary types from JARs are typically well-known libraries that Copilot already understands
+            if (type.isBinary()) {
+                return ""; // Skip expensive JavaDoc extraction for external dependencies
+            }
+            
+            String rawJavadoc;
+
+            // Extract JavaDoc from source code (fast - no I/O, no network, no HTML parsing)
+            org.eclipse.jdt.core.ISourceRange javadocRange = type.getJavadocRange();
+            if (javadocRange == null) {
+                return "";
+            }
+            rawJavadoc = type.getCompilationUnit().getSource().substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength());
+
+            if (!isNotEmpty(rawJavadoc)) {
+                return "";
+            }
+
+            StringBuilder result = new StringBuilder();
+            Set seenCodeSnippets = new HashSet<>();
+            
+            // Clean Javadoc comment for processing
+            String cleanedJavadoc = cleanJavadocComment(rawJavadoc);
+            cleanedJavadoc = removeHtmlTags(cleanedJavadoc);
+            cleanedJavadoc = convertHtmlEntities(cleanedJavadoc);
+
+            // === High Priority: Extract class description text (first paragraph) ===
+            String description = extractClassDescription(cleanedJavadoc);
+            if (isNotEmpty(description)) {
+                result.append("Description:\n").append(description).append("\n\n");
+            }
+
+            // === Extract code snippets ===
+            // 1. Extract markdown code blocks (```...```)
+            Matcher markdownMatcher = MARKDOWN_CODE_PATTERN.matcher(rawJavadoc);
+            while (markdownMatcher.find()) {
+                String code = markdownMatcher.group(1).trim();
+                if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
+                    result.append("```java\n").append(code).append("\n```\n\n");
+                }
+            }
+
+            // 2. Extract HTML 
 and  blocks
+            // Priority 1: 
 blocks (often contain well-formatted code)
+            Matcher preMatcher = HTML_PRE_PATTERN.matcher(cleanedJavadoc);
+            while (preMatcher.find()) {
+                String code = preMatcher.group(1).replaceAll("(?i)]*>", "").replaceAll("(?i)", "").trim();
+                if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
+                    result.append("```java\n").append(code).append("\n```\n\n");
+                }
+            }
+
+            // Priority 2:  blocks (for inline snippets)
+            Matcher codeMatcher = HTML_CODE_PATTERN.matcher(cleanedJavadoc);
+            while (codeMatcher.find()) {
+                String code = codeMatcher.group(1).trim();
+                // Use HashSet for O(1) duplicate checking
+                if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
+                    result.append("```java\n").append(code).append("\n```\n\n");
+                }
+            }
+
+            return result.toString().trim();
+
+        } catch (Exception e) {
+            JdtlsExtActivator.logException("Error extracting relevant JavaDoc content for: " + type.getElementName(), e);
+            return "";
+        }
+    }
+    
+    /**
+     * Extract the main description paragraph from class JavaDoc (before @tags and code blocks).
+     * Returns the first paragraph of descriptive text, limited to reasonable length.
+     */
+    private static String extractClassDescription(String cleanedJavadoc) {
+        if (cleanedJavadoc == null || cleanedJavadoc.isEmpty()) {
+            return "";
+        }
+        
+        // Remove code blocks first to get pure text
+        String textOnly = cleanedJavadoc;
+        textOnly = MARKDOWN_CODE_PATTERN.matcher(textOnly).replaceAll("");
+        textOnly = HTML_PRE_PATTERN.matcher(textOnly).replaceAll("");
+        textOnly = HTML_CODE_PATTERN.matcher(textOnly).replaceAll("");
+        
+        // Extract description before @tags
+        String description = extractJavadocDescription(textOnly);
+        
+        // Limit to ~2000 characters
+        if (description.length() > 2000) {
+            int breakPoint = findBestBreakpoint(description, 1500, 2100);
+            if (breakPoint != -1) {
+                description = description.substring(0, breakPoint + 1).trim();
+            } else {
+                int lastSpace = description.lastIndexOf(' ', 2000);
+                description = description.substring(0, lastSpace > 1500 ? lastSpace : 2000).trim() + "...";
+            }
+        }
+        
+        return description.trim();
+    }
+
+    /**
+     * Clean up raw JavaDoc comment by removing comment markers and asterisks
+     */
+    private static String cleanJavadocComment(String rawJavadoc) {
+        if (rawJavadoc == null || rawJavadoc.isEmpty()) {
+            return "";
+        }
+        
+        // Remove opening /** and closing */
+        String cleaned = rawJavadoc;
+        cleaned = cleaned.replaceFirst("^/\\*\\*", "");
+        cleaned = cleaned.replaceFirst("\\*/$", "");
+        
+        // Split into lines and clean each line
+        String[] lines = cleaned.split("\\r?\\n");
+        StringBuilder result = new StringBuilder();
+        
+        for (String line : lines) {
+            // Remove leading whitespace and asterisk
+            String trimmed = line.trim();
+            if (trimmed.startsWith("*")) {
+                trimmed = trimmed.substring(1).trim();
+            }
+            
+            // Skip empty lines at the beginning
+            if (result.length() == 0 && trimmed.isEmpty()) {
+                continue;
+            }
+            
+            // Add line to result
+            if (result.length() > 0 && !trimmed.isEmpty()) {
+                result.append("\n");
+            }
+            result.append(trimmed);
+        }
+        
+        return result.toString();
+    }
+
+
+    /**
+     * Convert HTML entities to their plain text equivalents
+     */
+    private static String convertHtmlEntities(String text) {
+        if (text == null || text.isEmpty()) {
+            return text;
+        }
+        return text.replace(" ", " ")
+                   .replace("<", "<")
+                   .replace(">", ">")
+                   .replace("&", "&")
+                   .replace(""", "\"")
+                   .replace("'", "'")
+                   .replace("'", "'")
+                   .replace("—", "-")
+                   .replace("–", "-");
+    }
+
+    /**
+     * Remove all HTML tags from text, keeping only plain text content.
+     * Preserves line breaks for block-level tags like 

,
,

. + */ + private static String removeHtmlTags(String text) { + if (text == null || text.isEmpty()) { + return text; + } + + // Replace block-level tags with line breaks + text = text.replaceAll("(?i)||]*>", "\n"); + + // Remove all remaining HTML tags + text = text.replaceAll("<[^>]+>", ""); + + // Clean up whitespace: collapse spaces, trim lines, limit line breaks + text = text.replaceAll("[ \\t]+", " ") + .replaceAll(" *\\n *", "\n") + .replaceAll("\\n{3,}", "\n\n"); + + return text.trim(); + } + + /** + * Extract method JavaDoc content directly for LLM consumption. + * Returns cleaned JavaDoc without artificial truncation - let LLM understand the full context. + */ + private static String extractMethodJavaDocSummary(IMethod method) { + try { + org.eclipse.jdt.core.ISourceRange javadocRange = method.getJavadocRange(); + if (javadocRange == null) { + return ""; + } + + String rawJavadoc = method.getCompilationUnit().getSource() + .substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength()); + + if (!isNotEmpty(rawJavadoc)) { + return ""; + } + + // Just clean and return - let LLM understand the full context + String cleaned = cleanJavadocComment(rawJavadoc); + cleaned = removeHtmlTags(cleaned); + return convertHtmlEntities(cleaned); + + } catch (Exception e) { + return ""; + } + } + + /** + * Extract the main description part from JavaDoc (before @tags) + */ + private static String extractJavadocDescription(String cleanedJavadoc) { + if (cleanedJavadoc == null || cleanedJavadoc.isEmpty()) { + return ""; + } + + // Split into lines and extract description before @tags + String[] lines = cleanedJavadoc.split("\\n"); + StringBuilder description = new StringBuilder(); + + for (String line : lines) { + String trimmedLine = line.trim(); + // Check if line starts with @tag + if (trimmedLine.startsWith("@")) { + break; // Stop at first tag + } + + // Skip empty lines at the beginning + if (description.length() == 0 && trimmedLine.isEmpty()) { + continue; + } + + if (description.length() > 0) { + description.append(" "); + } + description.append(trimmedLine); + } + + return description.toString().trim(); + } + + /** + * Get the first sentence or limit the text to maxLength characters + */ + private static String getFirstSentenceOrLimit(String text, int maxLength) { + if (text == null || text.isEmpty()) { + return ""; + } + + // Find first sentence boundary (., !, ?) + int firstSentenceEnd = findFirstSentenceBoundary(text); + + // Return first sentence if within reasonable length + if (firstSentenceEnd != -1 && firstSentenceEnd < maxLength) { + return text.substring(0, firstSentenceEnd + 1).trim(); + } + + // Otherwise truncate at maxLength with word boundary + if (text.length() > maxLength) { + int lastSpace = text.lastIndexOf(' ', maxLength); + int cutPoint = (lastSpace > maxLength / 2) ? lastSpace : maxLength; + return text.substring(0, cutPoint).trim() + "..."; + } + + return text.trim(); + } + + /** + * Find the first sentence boundary in text + */ + private static int findFirstSentenceBoundary(String text) { + int[] boundaries = {text.indexOf(". "), text.indexOf(".\n"), text.indexOf("! "), text.indexOf("? ")}; + int result = -1; + for (int boundary : boundaries) { + if (boundary != -1 && (result == -1 || boundary < result)) { + result = boundary; + } + } + return result; + } + + /** + * Find the best breakpoint for truncating text within a range + */ + private static int findBestBreakpoint(String text, int minPos, int maxPos) { + int[] boundaries = { + text.indexOf(". ", minPos), + text.indexOf(".\n", minPos), + text.indexOf("! ", minPos), + text.indexOf("? ", minPos) + }; + + int result = -1; + for (int boundary : boundaries) { + if (boundary != -1 && boundary < maxPos && (result == -1 || boundary < result)) { + result = boundary; + } + } + return result; + } + + /** + * Extract field JavaDoc content directly for LLM consumption. + * Returns cleaned JavaDoc without artificial truncation - let LLM understand the full context. + */ + private static String extractFieldJavaDocSummary(org.eclipse.jdt.core.IField field) { + try { + org.eclipse.jdt.core.ISourceRange javadocRange = field.getJavadocRange(); + if (javadocRange == null) { + return ""; + } + + String rawJavadoc = field.getCompilationUnit().getSource() + .substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength()); + + if (!isNotEmpty(rawJavadoc)) { + return ""; + } + + // Just clean and return - let LLM understand the full context + String cleaned = cleanJavadocComment(rawJavadoc); + cleaned = removeHtmlTags(cleaned); + return convertHtmlEntities(cleaned); + + } catch (Exception e) { + return ""; + } + } + + /** + * Generate human-readable method signature with JavaDoc description + */ + public static String generateMethodSignature(IMethod method) { + return generateMethodSignatureInternal(method, false, true); + } + + /** + * Generate human-readable field signature with JavaDoc description + */ + public static String generateFieldSignature(org.eclipse.jdt.core.IField field) { + return generateFieldSignatureInternal(field, false); + } + + /** + * Convert JDT type signature to human-readable format + */ + public static String convertTypeSignature(String jdtSignature) { + if (jdtSignature == null || jdtSignature.isEmpty()) { + return "void"; + } + + // Handle array types + int arrayDimensions = 0; + while (jdtSignature.startsWith("[")) { + arrayDimensions++; + jdtSignature = jdtSignature.substring(1); + } + + String baseType; + + // Handle type parameters and reference types (starts with Q) + if (jdtSignature.startsWith("Q") && jdtSignature.endsWith(";")) { + baseType = jdtSignature.substring(1, jdtSignature.length() - 1); + baseType = baseType.replace('/', '.'); + + // Handle generic type parameters (e.g., "QResult;") + baseType = processGenericTypes(baseType); + baseType = simplifyTypeName(baseType); + } + // Handle fully qualified types (starts with L) + else if (jdtSignature.startsWith("L") && jdtSignature.endsWith(";")) { + baseType = jdtSignature.substring(1, jdtSignature.length() - 1); + baseType = baseType.replace('/', '.'); + + // Handle generic type parameters + baseType = processGenericTypes(baseType); + baseType = simplifyTypeName(baseType); + } + // Handle primitive types + else { + switch (jdtSignature.charAt(0)) { + case 'I': baseType = "int"; break; + case 'Z': baseType = "boolean"; break; + case 'V': baseType = "void"; break; + case 'J': baseType = "long"; break; + case 'F': baseType = "float"; break; + case 'D': baseType = "double"; break; + case 'B': baseType = "byte"; break; + case 'C': baseType = "char"; break; + case 'S': baseType = "short"; break; + default: baseType = jdtSignature; + } + } + + // Add array markers + for (int i = 0; i < arrayDimensions; i++) { + baseType += "[]"; + } + + return baseType; + } + + /** + * Process generic type parameters in a type name + * Example: "Result" -> "Result" + */ + private static String processGenericTypes(String typeName) { + if (typeName == null || !typeName.contains("<")) { + return typeName; + } + + StringBuilder result = new StringBuilder(); + int i = 0; + + while (i < typeName.length()) { + char c = typeName.charAt(i); + + if (c == '<' || c == ',' || c == ' ') { + // Keep angle brackets, commas, and spaces + result.append(c); + i++; + + // Skip whitespace after comma or opening bracket + while (i < typeName.length() && typeName.charAt(i) == ' ') { + result.append(' '); + i++; + } + + // Check if next is a type parameter (Q or L prefix) + if (i < typeName.length()) { + char next = typeName.charAt(i); + + if (next == 'Q' || next == 'L') { + // Find the end of this type parameter (marked by ;) + int endIndex = typeName.indexOf(';', i); + if (endIndex != -1) { + // Extract the type parameter and convert it + String typeParam = typeName.substring(i + 1, endIndex); + + // Recursively process nested generics + typeParam = processGenericTypes(typeParam); + typeParam = simplifyTypeName(typeParam); + + result.append(typeParam); + i = endIndex + 1; // Skip past the semicolon + } else { + result.append(next); + i++; + } + } else { + // Not a type parameter, just append + result.append(next); + i++; + } + } + } else { + result.append(c); + i++; + } + } + + return result.toString(); + } + + /** + * Simplify fully qualified type name to just the simple name + */ + private static String simplifyTypeName(String qualifiedName) { + if (qualifiedName == null) { + return qualifiedName; + } + int lastDot = qualifiedName.lastIndexOf('.'); + return lastDot == -1 ? qualifiedName : qualifiedName.substring(lastDot + 1); + } + + + + /** + * Unified method signature generator (handles both source and binary types) + * @param simplified true for binary types (no parameter names, no JavaDoc) + * @param includeJavadoc true to include JavaDoc comments + */ + private static String generateMethodSignatureInternal(IMethod method, boolean simplified, boolean includeJavadoc) { + try { + StringBuilder sb = new StringBuilder(); + int flags = method.getFlags(); + + // Modifiers + if (org.eclipse.jdt.core.Flags.isPublic(flags)) sb.append("public "); + if (!simplified) { + if (org.eclipse.jdt.core.Flags.isProtected(flags)) sb.append("protected "); + if (org.eclipse.jdt.core.Flags.isPrivate(flags)) sb.append("private "); + } + if (org.eclipse.jdt.core.Flags.isStatic(flags)) sb.append("static "); + if (org.eclipse.jdt.core.Flags.isFinal(flags)) sb.append("final "); + if (org.eclipse.jdt.core.Flags.isAbstract(flags)) sb.append("abstract "); + + // Type parameters (only for non-simplified) + if (!simplified) { + @SuppressWarnings("deprecation") + String[] typeParameters = method.getTypeParameterSignatures(); + if (typeParameters != null && typeParameters.length > 0) { + sb.append("<"); + for (int i = 0; i < typeParameters.length; i++) { + if (i > 0) sb.append(", "); + sb.append(convertTypeSignature(typeParameters[i])); + } + sb.append("> "); + } + } + + // Return type (skip for constructors) + if (!method.isConstructor()) { + String returnType = simplified ? + simplifyTypeName(org.eclipse.jdt.core.Signature.toString(method.getReturnType())) : + convertTypeSignature(method.getReturnType()); + sb.append(returnType).append(" "); + } + + // Method name and parameters + sb.append(method.getElementName()).append("("); + String[] paramTypes = method.getParameterTypes(); + String[] paramNames = simplified ? null : method.getParameterNames(); + + for (int i = 0; i < paramTypes.length; i++) { + if (i > 0) sb.append(", "); + String paramType = simplified ? + simplifyTypeName(org.eclipse.jdt.core.Signature.toString(paramTypes[i])) : + convertTypeSignature(paramTypes[i]); + sb.append(paramType); + if (paramNames != null && i < paramNames.length) { + sb.append(" ").append(paramNames[i]); + } + } + sb.append(")"); + + // Exception declarations (only for non-simplified) + if (!simplified) { + String[] exceptionTypes = method.getExceptionTypes(); + if (exceptionTypes != null && exceptionTypes.length > 0) { + sb.append(" throws "); + for (int i = 0; i < exceptionTypes.length; i++) { + if (i > 0) sb.append(", "); + sb.append(convertTypeSignature(exceptionTypes[i])); + } + } + } else { + sb.append(";"); + } + + // Add JavaDoc if requested + if (includeJavadoc) { + String javadocSummary = extractMethodJavaDocSummary(method); + if (javadocSummary != null && !javadocSummary.isEmpty()) { + return "// " + javadocSummary + "\n " + sb.toString(); + } + } + + return sb.toString(); + } catch (JavaModelException e) { + return simplified ? "// Error generating method signature" : method.getElementName() + "(...)"; + } + } + + /** + * Unified field signature generator (handles both source and binary types) + * @param simplified true for binary types (no constant values, no JavaDoc) + */ + private static String generateFieldSignatureInternal(org.eclipse.jdt.core.IField field, boolean simplified) { + try { + StringBuilder sb = new StringBuilder(); + int flags = field.getFlags(); + + // Modifiers + if (org.eclipse.jdt.core.Flags.isPublic(flags)) sb.append("public "); + if (!simplified) { + if (org.eclipse.jdt.core.Flags.isProtected(flags)) sb.append("protected "); + if (org.eclipse.jdt.core.Flags.isPrivate(flags)) sb.append("private "); + } + if (org.eclipse.jdt.core.Flags.isStatic(flags)) sb.append("static "); + if (org.eclipse.jdt.core.Flags.isFinal(flags)) sb.append("final "); + + // Type and name + String fieldType = simplified ? + simplifyTypeName(org.eclipse.jdt.core.Signature.toString(field.getTypeSignature())) : + convertTypeSignature(field.getTypeSignature()); + sb.append(fieldType).append(" ").append(field.getElementName()); + + // Constant value (only for non-simplified) + if (!simplified && org.eclipse.jdt.core.Flags.isStatic(flags) && org.eclipse.jdt.core.Flags.isFinal(flags)) { + Object constant = field.getConstant(); + if (constant != null) { + sb.append(" = "); + if (constant instanceof String) { + sb.append("\"").append(constant).append("\""); + } else { + sb.append(constant); + } + } + } + + if (simplified) { + sb.append(";"); + } + + // Add JavaDoc if not simplified + if (!simplified) { + String javadocSummary = extractFieldJavaDocSummary(field); + if (javadocSummary != null && !javadocSummary.isEmpty()) { + return "// " + javadocSummary + "\n " + sb.toString(); + } + } + + return sb.toString(); + } catch (JavaModelException e) { + return simplified ? "// Error generating field signature" : field.getElementName(); + } + } + + /** + * Utility method to check if a string is not empty or null + */ + private static boolean isNotEmpty(String value) { + return value != null && !value.isEmpty(); + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ProjectResolver.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ProjectResolver.java new file mode 100644 index 00000000..f00c7b39 --- /dev/null +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ProjectResolver.java @@ -0,0 +1,458 @@ +package com.microsoft.jdtls.ext.core.parser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.ElementChangedEvent; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IElementChangedListener; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaElementDelta; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.launching.JavaRuntime; +import org.eclipse.jdt.ls.core.internal.JDTUtils; + +import com.microsoft.jdtls.ext.core.JdtlsExtActivator; + +public class ProjectResolver { + + // Cache for project dependency information + private static final Map dependencyCache = new ConcurrentHashMap<>(); + + // Flag to track if listeners are registered + private static volatile boolean listenersRegistered = false; + + // Lock for listener registration + private static final Object listenerLock = new Object(); + + /** + * Cached dependency information with timestamp + */ + private static class CachedDependencyInfo { + final List dependencies; + final long timestamp; + final long classpathHash; + + CachedDependencyInfo(List dependencies, long classpathHash) { + this.dependencies = new ArrayList<>(dependencies); + this.timestamp = System.currentTimeMillis(); + this.classpathHash = classpathHash; + } + + boolean isValid() { + // Cache is valid for 5 minutes + return (System.currentTimeMillis() - timestamp) < 300000; + } + } + + /** + * Listener for Java element changes (classpath changes, project references, etc.) + */ + private static final IElementChangedListener javaElementListener = new IElementChangedListener() { + @Override + public void elementChanged(ElementChangedEvent event) { + IJavaElementDelta delta = event.getDelta(); + processDelta(delta); + } + + private void processDelta(IJavaElementDelta delta) { + IJavaElement element = delta.getElement(); + int flags = delta.getFlags(); + + // Check for classpath changes + if ((flags & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0 || + (flags & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0) { + + if (element instanceof IJavaProject) { + IJavaProject project = (IJavaProject) element; + invalidateCache(project.getProject()); + } + } + + // Recursively process children + for (IJavaElementDelta child : delta.getAffectedChildren()) { + processDelta(child); + } + } + }; + + /** + * Listener for resource changes (pom.xml, build.gradle, etc.) + */ + private static final IResourceChangeListener resourceListener = new IResourceChangeListener() { + @Override + public void resourceChanged(IResourceChangeEvent event) { + if (event.getType() != IResourceChangeEvent.POST_CHANGE) { + return; + } + + IResourceDelta delta = event.getDelta(); + if (delta == null) { + return; + } + + try { + delta.accept(new IResourceDeltaVisitor() { + @Override + public boolean visit(IResourceDelta delta) throws CoreException { + IResource resource = delta.getResource(); + + // Check for build file changes + if (resource.getType() == IResource.FILE) { + String fileName = resource.getName(); + if ("pom.xml".equals(fileName) || + "build.gradle".equals(fileName) || + "build.gradle.kts".equals(fileName) || + ".classpath".equals(fileName) || + ".project".equals(fileName)) { + + IProject project = resource.getProject(); + if (project != null) { + invalidateCache(project); + } + } + } + return true; + } + }); + } catch (CoreException e) { + JdtlsExtActivator.logException("Error processing resource delta", e); + } + } + }; + + /** + * Initialize listeners for cache invalidation + */ + private static void ensureListenersRegistered() { + if (!listenersRegistered) { + synchronized (listenerLock) { + if (!listenersRegistered) { + try { + // Register Java element change listener + JavaCore.addElementChangedListener(javaElementListener, + ElementChangedEvent.POST_CHANGE); + + // Register resource change listener + ResourcesPlugin.getWorkspace().addResourceChangeListener( + resourceListener, + IResourceChangeEvent.POST_CHANGE); + + listenersRegistered = true; + JdtlsExtActivator.logInfo("ProjectResolver cache listeners registered successfully"); + } catch (Exception e) { + JdtlsExtActivator.logException("Failed to register ProjectResolver listeners", e); + } + } + } + } + } + + /** + * Invalidate cache for a specific project + */ + private static void invalidateCache(IProject project) { + if (project == null) { + return; + } + + String projectUri = JDTUtils.getFileURI(project); + + if (dependencyCache.remove(projectUri) != null) { + JdtlsExtActivator.logInfo("Cache invalidated for project: " + project.getName()); + } + } + + /** + * Clear all cached dependency information + */ + public static void clearCache() { + dependencyCache.clear(); + JdtlsExtActivator.logInfo("ProjectResolver cache cleared"); + } + + /** + * Calculate a simple hash of classpath entries for cache validation + */ + private static long calculateClasspathHash(IJavaProject javaProject) { + try { + IClasspathEntry[] entries = javaProject.getResolvedClasspath(true); + long hash = 0; + for (IClasspathEntry entry : entries) { + hash = hash * 31 + entry.getPath().toString().hashCode(); + hash = hash * 31 + entry.getEntryKind(); + } + return hash; + } catch (JavaModelException e) { + return 0; + } + } + + // Constants for dependency info keys + private static final String KEY_BUILD_TOOL = "buildTool"; + private static final String KEY_PROJECT_NAME = "projectName"; + private static final String KEY_PROJECT_LOCATION = "projectLocation"; + private static final String KEY_JAVA_VERSION = "javaVersion"; + private static final String KEY_SOURCE_COMPATIBILITY = "sourceCompatibility"; + private static final String KEY_TARGET_COMPATIBILITY = "targetCompatibility"; + private static final String KEY_MODULE_NAME = "moduleName"; + private static final String KEY_TOTAL_LIBRARIES = "totalLibraries"; + private static final String KEY_TOTAL_PROJECT_REFS = "totalProjectReferences"; + private static final String KEY_JRE_CONTAINER = "jreContainer"; + + public static class DependencyInfo { + public String key; + public String value; + + public DependencyInfo(String key, String value) { + this.key = key; + this.value = value; + } + } + + /** + * Resolve project dependencies information including JDK version. + * Supports both single projects and multi-module aggregator projects. + * + * @param fileUri The file URI + * @param monitor Progress monitor for cancellation support + * @return List of DependencyInfo containing key-value pairs of project information + */ + public static List resolveProjectDependencies(String fileUri, IProgressMonitor monitor) { + // Ensure listeners are registered for cache invalidation + ensureListenersRegistered(); + + List result = new ArrayList<>(); + + try { + // Use JDTUtils to convert URI and find the resource + java.net.URI uri = JDTUtils.toURI(fileUri); + IResource resource = JDTUtils.findResource(uri, + ResourcesPlugin.getWorkspace().getRoot()::findFilesForLocationURI); + + if (resource == null) { + return result; + } + + IProject project = resource.getProject(); + if (project == null || !project.isAccessible()) { + return result; + } + + IJavaProject javaProject = JavaCore.create(project); + // Check if this is a Java project + if (javaProject == null || !javaProject.exists()) { + return result; + } + + // Generate cache key based on project URI + String cacheKey = JDTUtils.getFileURI(project); + + // Calculate current classpath hash for validation + long currentClasspathHash = calculateClasspathHash(javaProject); + + // Try to get from cache + CachedDependencyInfo cached = dependencyCache.get(cacheKey); + if (cached != null && cached.isValid() && cached.classpathHash == currentClasspathHash) { + JdtlsExtActivator.logInfo("Using cached dependencies for project: " + project.getName()); + return new ArrayList<>(cached.dependencies); + } + + // Add basic project information + addBasicProjectInfo(result, project, javaProject); + + // Get classpath entries (dependencies) + processClasspathEntries(result, javaProject, monitor); + + // Add build tool info by checking for build files + detectBuildTool(result, project); + + // Store in cache + dependencyCache.put(cacheKey, new CachedDependencyInfo(result, currentClasspathHash)); + + } catch (Exception e) { + JdtlsExtActivator.logException("Error in resolveProjectDependencies", e); + } + + return result; + } + + /** + * Add basic project information including name, location, and Java version settings. + */ + private static void addBasicProjectInfo(List result, IProject project, IJavaProject javaProject) { + result.add(new DependencyInfo(KEY_PROJECT_NAME, project.getName())); + + addIfNotNull(result, KEY_PROJECT_LOCATION, JDTUtils.getFileURI(project)); + + addIfNotNull(result, KEY_JAVA_VERSION, + javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true)); + + addIfNotNull(result, KEY_SOURCE_COMPATIBILITY, + javaProject.getOption(JavaCore.COMPILER_SOURCE, true)); + + addIfNotNull(result, KEY_TARGET_COMPATIBILITY, + javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true)); + + addIfNotNull(result, KEY_MODULE_NAME, getModuleName(javaProject)); + } + + /** + * Process classpath entries to extract library and project reference information. + */ + private static void processClasspathEntries(List result, IJavaProject javaProject, IProgressMonitor monitor) { + try { + IClasspathEntry[] classpathEntries = javaProject.getResolvedClasspath(true); + int libCount = 0; + int projectRefCount = 0; + + for (IClasspathEntry entry : classpathEntries) { + if (monitor.isCanceled()) { + break; + } + + switch (entry.getEntryKind()) { + case IClasspathEntry.CPE_LIBRARY: + libCount++; + processLibraryEntry(result, entry, libCount); + break; + case IClasspathEntry.CPE_PROJECT: + projectRefCount++; + processProjectEntry(result, entry, projectRefCount); + break; + case IClasspathEntry.CPE_CONTAINER: + processContainerEntry(result, entry); + break; + } + } + + // Add summary counts + result.add(new DependencyInfo(KEY_TOTAL_LIBRARIES, String.valueOf(libCount))); + result.add(new DependencyInfo(KEY_TOTAL_PROJECT_REFS, String.valueOf(projectRefCount))); + + } catch (JavaModelException e) { + JdtlsExtActivator.logException("Error getting classpath entries", e); + } + } + + /** + * Process a library classpath entry. + * Only returns the library file name without full path to reduce data size. + */ + private static void processLibraryEntry(List result, IClasspathEntry entry, int libCount) { + IPath libPath = entry.getPath(); + if (libPath != null) { + // Only keep the file name, remove the full path + result.add(new DependencyInfo("library_" + libCount, libPath.lastSegment())); + } + } + + /** + * Process a project reference classpath entry. + * Simplified to only extract essential information. + */ + private static void processProjectEntry(List result, IClasspathEntry entry, int projectRefCount) { + IPath projectRefPath = entry.getPath(); + if (projectRefPath != null) { + result.add(new DependencyInfo("projectReference_" + projectRefCount, + projectRefPath.lastSegment())); + } + } + + /** + * Process a container classpath entry (JRE, Maven, Gradle containers). + */ + private static void processContainerEntry(List result, IClasspathEntry entry) { + String containerPath = entry.getPath().toString(); + + if (containerPath.contains("JRE_CONTAINER")) { + // Only extract the JRE version, not the full container path + try { + String vmInstallName = JavaRuntime.getVMInstallName(entry.getPath()); + addIfNotNull(result, KEY_JRE_CONTAINER, vmInstallName); + } catch (Exception e) { + // Fallback: try to extract version from path + if (containerPath.contains("JavaSE-")) { + int startIdx = containerPath.lastIndexOf("JavaSE-"); + String version = containerPath.substring(startIdx); + // Clean up any trailing characters + if (version.contains("/")) { + version = version.substring(0, version.indexOf("/")); + } + result.add(new DependencyInfo(KEY_JRE_CONTAINER, version)); + } + } + } else if (containerPath.contains("MAVEN")) { + result.add(new DependencyInfo(KEY_BUILD_TOOL, "Maven")); + } else if (containerPath.contains("GRADLE")) { + result.add(new DependencyInfo(KEY_BUILD_TOOL, "Gradle")); + } + } + + /** + * Detect build tool by checking for build configuration files. + * Only adds if not already detected from classpath containers. + */ + private static void detectBuildTool(List result, IProject project) { + // Check if buildTool already set from container + if (hasBuildToolInfo(result)) { + return; + } + + if (project.getFile("pom.xml").exists()) { + result.add(new DependencyInfo(KEY_BUILD_TOOL, "Maven")); + } else if (project.getFile("build.gradle").exists() || project.getFile("build.gradle.kts").exists()) { + result.add(new DependencyInfo(KEY_BUILD_TOOL, "Gradle")); + } + } + + /** + * Get module name for a Java project. + */ + private static String getModuleName(IJavaProject project) { + if (project == null || !JavaRuntime.isModularProject(project)) { + return null; + } + try { + org.eclipse.jdt.core.IModuleDescription module = project.getModuleDescription(); + return module != null ? module.getElementName() : null; + } catch (Exception e) { + return null; + } + } + + /** + * Helper method to add dependency info only if value is not null. + */ + private static void addIfNotNull(List result, String key, String value) { + if (value != null) { + result.add(new DependencyInfo(key, value)); + } + } + + /** + * Check if buildTool info is already present in result list. + */ + private static boolean hasBuildToolInfo(List result) { + for (DependencyInfo info : result) { + if (KEY_BUILD_TOOL.equals(info.key)) { + return true; + } + } + return false; + } +} diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ResourceSet.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ResourceSet.java index dde7eec5..55bfeb89 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ResourceSet.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ResourceSet.java @@ -16,6 +16,7 @@ import java.util.Objects; import org.eclipse.core.internal.utils.FileUtil; +import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -109,7 +110,9 @@ public void accept(ResourceVisitor visitor) { visitor.visit((IFile) resource); } } else if (resource instanceof IFolder) { - if (shouldVisit((IFolder) resource)) { + if (shouldVisit((IFolder) resource) + && (!containsSourceClasspathEntry((IFolder) resource) + || hasVisibleNonJavaResources((IFolder) resource))) { visitor.visit((IFolder) resource); } } else if (resource instanceof IJarEntryResource) { @@ -152,4 +155,49 @@ private boolean shouldVisit(IResource resource) { return JavaCore.create(resource) == null; } + + private boolean containsSourceClasspathEntry(IContainer container) { + try { + IJavaProject javaProject = JavaCore.create(container.getProject()); + if (javaProject == null) { + return false; + } + IPath containerPath = container.getFullPath(); + if (containerPath.equals(javaProject.getOutputLocation())) { + return false; + } + for (IClasspathEntry entry : javaProject.getRawClasspath()) { + if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE + && containerPath.isPrefixOf(entry.getPath())) { + return true; + } + } + } catch (CoreException e) { + JdtlsExtActivator.logException("Failed to inspect Java source entries", e); + } + return false; + } + + private boolean hasVisibleNonJavaResources(IContainer container) { + try { + for (IResource member : container.members()) { + if (JavaCore.create(member) != null) { + continue; + } + if (member instanceof IFile) { + return true; + } + if (member instanceof IContainer) { + IContainer child = (IContainer) member; + if (!containsSourceClasspathEntry(child) || hasVisibleNonJavaResources(child)) { + return true; + } + } + } + } catch (CoreException e) { + JdtlsExtActivator.logException("Failed to inspect non-Java resources", e); + return true; + } + return false; + } } diff --git a/jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target b/jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target index daa2dbf1..9a0e618b 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target +++ b/jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target @@ -10,20 +10,16 @@ - + - + - - - - diff --git a/jdtls.ext/com.microsoft.jdtls.ext.target/pom.xml b/jdtls.ext/com.microsoft.jdtls.ext.target/pom.xml index 405b4e1a..4fae28b3 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.target/pom.xml +++ b/jdtls.ext/com.microsoft.jdtls.ext.target/pom.xml @@ -4,7 +4,7 @@ com.microsoft.jdtls.ext jdtls-ext-parent - 0.24.0 + 0.24.1 com.microsoft.jdtls.ext.tp ${base.name} :: Target Platform diff --git a/jdtls.ext/mvnw b/jdtls.ext/mvnw index e96ccd5f..e9cf8d33 100755 --- a/jdtls.ext/mvnw +++ b/jdtls.ext/mvnw @@ -19,209 +19,277 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.3 # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac -fi +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 fi fi - ;; -esac + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" +} - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - saveddir=`pwd` +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac - M2_HOME=`dirname "$PRG"`/.. +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} - cd "$saveddir" - # echo Using m2 at $M2_HOME +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" fi -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" fi -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi else - JAVACMD="`which java`" + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 fi fi -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" fi +fi - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi fi - # end of workaround done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; + set -f fi -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" fi -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/jdtls.ext/mvnw.cmd b/jdtls.ext/mvnw.cmd index 019bd74d..2e2dbe03 100644 --- a/jdtls.ext/mvnw.cmd +++ b/jdtls.ext/mvnw.cmd @@ -1,3 +1,4 @@ +<# : batch portion @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @@ -18,126 +19,171 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir +@REM Apache Maven Wrapper startup batch script, version 3.3.3 @REM @REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output @REM ---------------------------------------------------------------------------- -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" - -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/jdtls.ext/pom.xml b/jdtls.ext/pom.xml index d1fc175d..6c9688b6 100644 --- a/jdtls.ext/pom.xml +++ b/jdtls.ext/pom.xml @@ -4,7 +4,7 @@ com.microsoft.jdtls.ext jdtls-ext-parent ${base.name} :: Parent - 0.24.0 + 0.24.1 pom Java Project Manager @@ -131,13 +131,4 @@ - - - oss.sonatype.org - https://oss.sonatype.org/content/repositories/snapshots/ - - true - - - diff --git a/package-lock.json b/package-lock.json index ea6b0047..166877f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,161 +1,268 @@ { "name": "vscode-java-dependency", - "version": "0.24.0", + "version": "0.27.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-java-dependency", - "version": "0.24.0", + "version": "0.27.6", "license": "MIT", "dependencies": { + "@github/copilot-language-server": "^1.530.0", + "@octokit/rest": "^21.1.1", "await-lock": "^2.2.2", "fmtr": "^1.1.4", "fs-extra": "^10.1.0", "globby": "^13.1.3", - "lodash": "^4.17.21", - "minimatch": "^5.1.6", + "lodash": "^4.18.0", + "minimatch": "^5.1.9", "semver": "^7.3.8", - "vscode-extension-telemetry-wrapper": "^0.14.0", - "vscode-tas-client": "^0.1.75" + "vscode-extension-telemetry-wrapper": "^0.15.2", + "vscode-tas-client": "^0.3.0" }, "devDependencies": { "@types/fs-extra": "^9.0.13", "@types/glob": "^7.2.0", - "@types/lodash": "^4.14.191", + "@types/lodash": "^4.17.25", "@types/minimatch": "^3.0.3", "@types/mocha": "^9.1.1", - "@types/node": "^16.18.11", + "@types/node": "20.x", "@types/semver": "^7.3.13", - "@types/vscode": "1.83.1", - "@vscode/test-electron": "^2.3.8", - "copy-webpack-plugin": "^11.0.0", + "@types/vscode": "1.95.0", + "@vscode/test-electron": "^3.1.0", + "copy-webpack-plugin": "^14.0.0", "glob": "^7.2.3", - "mocha": "^9.2.2", - "ts-loader": "^9.4.2", + "mocha": "^11.7.5", + "ts-loader": "^9.6.2", "tslint": "^6.1.3", "typescript": "^4.9.4", - "vscode-extension-tester": "^7.0.0", - "webpack": "^5.76.0", + "webpack": "^5.109.0", "webpack-cli": "^4.10.0" }, "engines": { - "vscode": "^1.83.1" + "vscode": "^1.95.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "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, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=10.0.0" } }, - "node_modules/@babel/highlight/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/@github/copilot-darwin-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.78.tgz", + "integrity": "sha512-P11+VyWg8ad0WlywGtO2d7AxqTLJv4hkUicFg6Ycth5lfk00aCu/74YOOZSPO6C2bBBJhAza7oAdmauM6KEojw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "bin": { + "copilot-darwin-arm64": "copilot" } }, - "node_modules/@babel/highlight/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/@github/copilot-darwin-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.78.tgz", + "integrity": "sha512-stimP3WDFs2GU8nJzTJbtRpZViV4bsf80yg7QrFq+G4RISQ3Nihg/3/H0U6UQF1+txMJ/Ohmb5RFYxSw1Hj2sw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "bin": { + "copilot-darwin-x64": "copilot" } }, - "node_modules/@babel/highlight/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, + "node_modules/@github/copilot-language-server": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.530.0.tgz", + "integrity": "sha512-7OjTbKqkA9NSf8Yjms19qglBswdK7IkorbzB0EpfPOPeT8UdmxW0fiYCiaTsyB+VizMzchrPh0nbik8gH8boKw==", "dependencies": { - "color-name": "1.1.3" - } + "vscode-languageserver-protocol": "^3.17.5" + }, + "bin": { + "copilot-language-server": "dist/language-server.js" + }, + "optionalDependencies": { + "@github/copilot-darwin-arm64": "1.0.78", + "@github/copilot-darwin-x64": "1.0.78", + "@github/copilot-language-server-darwin-arm64": "1.530.0", + "@github/copilot-language-server-darwin-x64": "1.530.0", + "@github/copilot-language-server-linux-arm64": "1.530.0", + "@github/copilot-language-server-linux-x64": "1.530.0", + "@github/copilot-language-server-win32-arm64": "1.530.0", + "@github/copilot-language-server-win32-x64": "1.530.0", + "@github/copilot-linux-arm64": "1.0.78", + "@github/copilot-linux-x64": "1.0.78", + "@github/copilot-win32-arm64": "1.0.78", + "@github/copilot-win32-x64": "1.0.78" + } + }, + "node_modules/@github/copilot-language-server-darwin-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-arm64/-/copilot-language-server-darwin-arm64-1.530.0.tgz", + "integrity": "sha512-WREnhFgvqDUHOYZTOmd0XldA3DtJ7XEn4leAezDEW4iwhoTyROmGSjH02ROj2l22Zdtq5byATidjDHGn5CnO/g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@babel/highlight/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/@github/copilot-language-server-darwin-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-x64/-/copilot-language-server-darwin-x64-1.530.0.tgz", + "integrity": "sha512-rHBRaA6MtbQSCOF7vDgcPEiukWmmggwuoOcqqi7yKvcq6/K7MDW9jtydq6HP/mg0fUe44l0sG/h9/MQlQcljvA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@babel/highlight/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/@github/copilot-language-server-linux-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-arm64/-/copilot-language-server-linux-arm64-1.530.0.tgz", + "integrity": "sha512-2Wvdm3IogKHSUsN6zlleK91CdKoiGIf2R0n0P5ZHcLxaGix29fPGMa/hl5A9wkpnnV7szBDUKTHqwZoMxtPOvA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@github/copilot-language-server-linux-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-x64/-/copilot-language-server-linux-x64-1.530.0.tgz", + "integrity": "sha512-1MIg6t+TS67sEpjb5jqf2BhjRrYW3sLlSyCxAT+a76ZUwlLjmrVFlpU2R6B/HIQDQhoxuvZwQ6YXmfxCVufDmw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@github/copilot-language-server-win32-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-arm64/-/copilot-language-server-win32-arm64-1.530.0.tgz", + "integrity": "sha512-xlTuNNZQUg+WM2RJTvdlbcYKyQCCOWQaXTn5sGGZ38tSB+gPKcCDr39c5AgWZ4KS/1jk+pxn0b74+PMkyWyxow==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@github/copilot-language-server-win32-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-x64/-/copilot-language-server-win32-x64-1.530.0.tgz", + "integrity": "sha512-tI2dPAWplfsbLL94CyuFfm3R8YfCGlT8dmPbbaa2e6E9/GoBkYugcTtDH2a5qkaPk1t2LJeUTDiN/Uhr/HNAPw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@github/copilot-linux-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.78.tgz", + "integrity": "sha512-K31PRKGTm252V1Lof7ypjg283R2QSm3BgoCvZfX2taos4wqC3SaTozSQKwW3dgrAx7A3G3SGEoilVCNqfigdZA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "bin": { + "copilot-linux-arm64": "copilot" } }, - "node_modules/@babel/highlight/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/@github/copilot-linux-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.78.tgz", + "integrity": "sha512-QK3oMtAn9dIv+1u1kx0xNpZNtZxdI+uZVIyLl7myp+Oh2Uj8BLagVv6a7uP0cDphO3TgfIdlvpepCe5MIcx0fw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "bin": { + "copilot-linux-x64": "copilot" } }, - "node_modules/@babel/highlight/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/@github/copilot-win32-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.78.tgz", + "integrity": "sha512-ktDkFXaaecEKD3hpM6ydM9lKOdoCfsQsXCmzLzE7DCmSpbbMCdfPfWfZ7MOclmKmpZ5/MNfr4U2l8CUqGerzYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "bin": { + "copilot-win32-arm64": "copilot.exe" } }, - "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/@github/copilot-win32-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.78.tgz", + "integrity": "sha512-Gd8l2T4eqYEWlOEPd0SZznQ+YYgYrwOkE0QXodMkhCBbPdgu/uTzb7mnISWwnVAgqs7pONdF1GOpHkTo+ay8CQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "bin": { + "copilot-win32-x64": "copilot.exe" } }, "node_modules/@isaacs/cliui": { @@ -255,176 +362,182 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "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/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "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.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "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.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "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.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "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" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@microsoft/1ds-core-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.2.2.tgz", - "integrity": "sha512-4c1AXzOj7ZyX7/97v8fEDYcQ8ymTTmj+j9HYYlcO0/cUbDzZGA7/xzb34chvvAbV60qDEbX0Ha/ea7wzgefORg==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.3.10.tgz", + "integrity": "sha512-5fSZmkGwWkH+mrIA5M1GYPZdPM+SjXwCCl2Am7VhFoVwOBJNhRnwvIpAdzw6sFjiebN/rz+/YH0NdxztGZSa9Q==", + "license": "MIT", "dependencies": { - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "node_modules/@microsoft/1ds-post-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.2.2.tgz", - "integrity": "sha512-0k1aSxD03r3ugLaYhI8Y8AonI/whOzSQd66XBYURVTs6uheMMxDQdSnAk/4Dwn/TUK3TCEJZBIwZRVpUJtJX9w==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.3.10.tgz", + "integrity": "sha512-VSLjc9cT+Y+eTiSfYltJHJCejn8oYr0E6Pq2BMhOEO7F6IyLGYIxzKKvo78ze9x+iHX7KPTATcZ+PFgjGXuNqg==", + "license": "MIT", "dependencies": { - "@microsoft/1ds-core-js": "4.2.2", + "@microsoft/1ds-core-js": "4.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "node_modules/@microsoft/applicationinsights-channel-js": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.2.2.tgz", - "integrity": "sha512-4ruoKxgZYYa+K8JJu8RMY0egKazS8xClbx70NQHa/rJ7JYFgN3OIEIBZtFoMcHR8Vg7MEsNE5/wV6o7WWJkVIA==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.3.10.tgz", + "integrity": "sha512-iolFLz1ocWAzIQqHIEjjov3gNTPkgFQ4ArHnBcJEYoffOGWlJt6copaevS5YPI5rHzmbySsengZ8cLJJBBrXzQ==", + "license": "MIT", "dependencies": { - "@microsoft/applicationinsights-common": "3.2.2", - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-common": "3.3.10", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" }, "peerDependencies": { - "tslib": "*" + "tslib": ">= 1.0.0" } }, "node_modules/@microsoft/applicationinsights-common": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.2.2.tgz", - "integrity": "sha512-e1C35gdkFSzWyUUR1S8FvisXW3nT3p6wWsLNs+vUKLOTQzsvW3XpNMVtNCq4MfHWiYDuz1lPSzo2eENaij1fVA==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.3.10.tgz", + "integrity": "sha512-RVIenPIvNgZCbjJdALvLM4rNHgAFuHI7faFzHCgnI6S2WCUNGHeXlQTs9EUUrL+n2TPp9/cd0KKMILU5VVyYiA==", + "license": "MIT", "dependencies": { - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" }, "peerDependencies": { - "tslib": "*" + "tslib": ">= 1.0.0" } }, "node_modules/@microsoft/applicationinsights-core-js": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.2.2.tgz", - "integrity": "sha512-dF6LZ4ahdhoHufw+N7OXRDzWT8QN193Dvpd8GLqEZdR/KtCTofPSI63yumu+ZkzKYadf1S3w2xg0OmbdyXexoQ==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.10.tgz", + "integrity": "sha512-5yKeyassZTq2l+SAO4npu6LPnbS++UD+M+Ghjm9uRzoBwD8tumFx0/F8AkSVqbniSREd+ztH/2q2foewa2RZyg==", + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" }, "peerDependencies": { - "tslib": "*" + "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==", + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.9.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-web-basic": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.2.2.tgz", - "integrity": "sha512-4OdgTurRr/Awm2DcWuAhidFON2UFiirabeO9SSAeTefDCdtzv5fWzntq9zvdV47c+w6WzZkz8nX/bQTgNRb2+w==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.3.10.tgz", + "integrity": "sha512-AZib5DAT3NU0VT0nLWEwXrnoMDDgZ/5S4dso01CNU5ELNxLdg+1fvchstlVdMy4FrAnxzs8Wf/GIQNFYOVgpAw==", + "license": "MIT", "dependencies": { - "@microsoft/applicationinsights-channel-js": "3.2.2", - "@microsoft/applicationinsights-common": "3.2.2", - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-channel-js": "3.3.10", + "@microsoft/applicationinsights-common": "3.3.10", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" }, "peerDependencies": { - "tslib": "*" + "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==", + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.10.4 < 2.x" } }, "node_modules/@nevware21/ts-async": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.1.tgz", - "integrity": "sha512-O2kN8n2HpDWJ7Oji+oTMnhITrCndmrNvrHbGDwAIBydx+FWvLE/vrw4QwnRRMvSCa2AJrcP59Ryklxv30KfkWQ==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.5.tgz", + "integrity": "sha512-vwqaL05iJPjLeh5igPi8MeeAu10i+Aq7xko1fbo9F5Si6MnVN5505qaV7AhSdk5MCBJVT/UYMk3kgInNjDb4Ig==", + "license": "MIT", "dependencies": { - "@nevware21/ts-utils": ">= 0.11.2 < 2.x" + "@nevware21/ts-utils": ">= 0.12.2 < 2.x" } }, "node_modules/@nevware21/ts-utils": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.2.tgz", - "integrity": "sha512-80W8BkS09kkGuUHJX50Fqq+QqAslxUaOQytH+3JhRacXs1EpEt2JOOkYKytqFZAYir3SeH9fahniEaDzIBxlUw==" + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.14.0.tgz", + "integrity": "sha512-WoeqTIXQ8WPhl+lD2NbMHoAQ4sJl0n7EoRoDmVJui//Usg512enl9q1fdbVobuZt3omnxnmVsDrNIvPBvFgddQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nevware21" + }, + { + "type": "other", + "url": "https://buymeacoffee.com/nevware21" + } + ] }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -458,73 +571,188 @@ "node": ">= 8" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, + "node_modules/@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@sindresorhus/is": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.5.2.tgz", - "integrity": "sha512-8ZMK+V6YpeZFfW6hU9uAeWVuq8v3t7BaG276gIO+kVqnAcLrHCXdFUOf7kgouyfAarkZtuavIqY3RsXTsTWviw==", - "dev": true, + "node_modules/@octokit/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", + "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">= 18" } }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, + "node_modules/@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", "dependencies": { - "defer-to-connect": "^2.0.1" + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">=14.16" + "node": ">= 18" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, + "node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "dependencies": { + "@octokit/types": "^13.10.0" + }, "engines": { - "node": ">= 6" + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@types/eslint": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", - "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", - "dev": true, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", + "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "dependencies": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "dependencies": { + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true }, "node_modules/@types/fs-extra": { @@ -546,22 +774,16 @@ "@types/node": "*" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "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.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.25.tgz", + "integrity": "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==", "dev": true }, "node_modules/@types/minimatch": { @@ -577,18 +799,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.38", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.38.tgz", - "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==", - "dev": true - }, - "node_modules/@types/selenium-webdriver": { - "version": "4.1.21", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-4.1.21.tgz", - "integrity": "sha512-QGURnImvxYlIQz5DVhvHdqpYNLBjhJ2Vm+cnQI2G9QZzkWlZm0LkLcvDcHp+qE6N2KBz4CeuvXgPO7W3XQ0Tyw==", + "version": "20.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz", + "integrity": "sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==", "dev": true, "dependencies": { - "@types/ws": "*" + "undici-types": "~6.19.2" } }, "node_modules/@types/semver": { @@ -598,336 +814,186 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.83.1", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", - "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "version": "1.95.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.95.0.tgz", + "integrity": "sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==", "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true + "license": "MIT" }, "node_modules/@vscode/extension-telemetry": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.6.tgz", - "integrity": "sha512-qWK2GNw+b69QRYpjuNM9g3JKToMICoNIdc0rQMtvb4gIG9vKKCZCVCz+ZOx6XM/YlfWAyuPiyxcjIY0xyF+Djg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-1.2.0.tgz", + "integrity": "sha512-En6dTwfy5NFzSMibvOpx/lKq2jtgWuR4++KJbi3SpQ2iT8gm+PHo9868/scocW122KDwTxl4ruxZ7i4rHmJJnQ==", + "license": "MIT", "dependencies": { - "@microsoft/1ds-core-js": "^4.1.2", - "@microsoft/1ds-post-js": "^4.1.2", - "@microsoft/applicationinsights-web-basic": "^3.1.2" + "@microsoft/1ds-core-js": "^4.3.10", + "@microsoft/1ds-post-js": "^4.3.10", + "@microsoft/applicationinsights-web-basic": "^3.3.10" }, "engines": { "vscode": "^1.75.0" } }, "node_modules/@vscode/test-electron": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.8.tgz", - "integrity": "sha512-b4aZZsBKtMGdDljAsOPObnAi7+VWIaYl3ylCz1jTs+oV6BZ4TNHcVNC3xUn0azPeszBmwSBDQYfFESIaUQnrOg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-3.1.0.tgz", + "integrity": "sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw==", "dev": true, + "license": "MIT", "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@vscode/vsce": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.22.0.tgz", - "integrity": "sha512-8df4uJiM3C6GZ2Sx/KilSKVxsetrTBBIUb3c0W4B1EWHcddioVs5mkyDKtMNP0khP/xBILVSzlXxhV+nm2rC9A==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.2.1", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "jsonc-parser": "^3.2.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^7.5.2", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.5.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" + "ora": "^8.1.0", + "semver": "^7.6.2" }, "engines": { - "node": ">= 14" - }, - "optionalDependencies": { - "keytar": "^7.7.0" - } - }, - "node_modules/@vscode/vsce/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/@vscode/vsce/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/@vscode/vsce/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/@vscode/vsce/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/@vscode/vsce/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/@vscode/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@vscode/vsce/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/@vscode/vsce/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/@vscode/vsce/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@vscode/vsce/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": ">=22" } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "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.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "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.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "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.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "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.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "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.11.6", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -980,9 +1046,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -991,37 +1057,29 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "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" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -1057,15 +1115,6 @@ "ajv": "^8.8.2" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1090,155 +1139,40 @@ "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/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, "node_modules/await-lock": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==" }, - "node_modules/axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz", - "integrity": "sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/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==", + "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, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" }, "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==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dependencies": { "balanced-match": "^1.0.0" } @@ -1261,9 +1195,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -1280,10 +1214,11 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "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" @@ -1292,86 +1227,12 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", - "dev": true - }, "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/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1381,47 +1242,6 @@ "node": ">=0.10.0" } }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.12", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.12.tgz", - "integrity": "sha512-qtWGB5kn2OLjx47pYUkWicyOpK1vy9XZhq8yRTXOy+KAmjjESSRLx6SiExnnaGGUP1NM6/vmygMu0fGylNh9tw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "^4.0.1", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.2", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -1435,9 +1255,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001517", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", - "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", + "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": [ { @@ -1454,18 +1274,6 @@ } ] }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1494,89 +1302,21 @@ "node": ">=8" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 6" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -1586,15 +1326,14 @@ "node": ">=6.0" } }, - "node_modules/clipboardy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", - "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, + "license": "MIT", "dependencies": { - "execa": "^8.0.1", - "is-wsl": "^3.1.0", - "is64bit": "^2.0.0" + "restore-cursor": "^5.0.0" }, "engines": { "node": ">=18" @@ -1603,15 +1342,31 @@ "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, + "license": "MIT", + "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==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/clone-deep": { @@ -1652,29 +1407,12 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "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": "6.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", - "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", - "dev": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1682,20 +1420,19 @@ "dev": true }, "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-14.0.0.tgz", + "integrity": "sha512-3JLW90aBGeaTLpM7mYQKpnVdgsUZRExY55giiZgLuX/xTQRUs1dOCwbBnWnvY6Q6rfZoXMNwzOQJCSZPppfqXA==", "dev": true, "dependencies": { - "fast-glob": "^3.2.11", "glob-parent": "^6.0.1", - "globby": "^13.1.1", "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "schema-utils": "^4.2.0", + "serialize-javascript": "^7.0.3", + "tinyglobby": "^0.2.12" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 20.9.0" }, "funding": { "type": "opencollective", @@ -1712,10 +1449,11 @@ "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1725,41 +1463,14 @@ "node": ">= 8" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1782,88 +1493,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "engines": { "node": ">=0.3.1" @@ -1880,70 +1513,6 @@ "node": ">=8" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1951,9 +1520,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.467", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", - "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", + "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": { @@ -1962,40 +1531,19 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/envinfo": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", @@ -2009,15 +1557,15 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", - "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "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" @@ -2100,50 +1648,20 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -2152,15 +1670,16 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2177,11 +1696,21 @@ "node": ">= 6" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "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", @@ -2200,15 +1729,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -2253,32 +1773,14 @@ "lodash": "^4.17.21" } }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -2288,34 +1790,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -2335,47 +1809,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2394,40 +1827,19 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true, - "optional": true - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2460,16 +1872,10 @@ "node": ">=10.13.0" } }, - "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/glob/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==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", @@ -2477,9 +1883,9 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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" @@ -2506,57 +1912,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, "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==" }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2578,54 +1938,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "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", @@ -2635,122 +1947,32 @@ "he": "bin/he" } }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hpagent": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", - "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "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": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=10.19.0" + "node": ">= 14" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "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": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" + "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" - } - ], - "optional": true - }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2800,13 +2022,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "optional": true - }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -2816,18 +2031,6 @@ "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.12.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", @@ -2840,21 +2043,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2883,19 +2071,14 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "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, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, + "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2909,6 +2092,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2930,18 +2122,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2954,36 +2134,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is64bit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is64bit/-/is64bit-2.0.0.tgz", - "integrity": "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==", - "dev": true, - "dependencies": { - "system-architecture": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "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", @@ -3005,24 +2155,6 @@ "node": ">=0.10.0" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -3041,13 +2173,25 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3055,30 +2199,12 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "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/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -3102,27 +2228,6 @@ "setimmediate": "^1.0.5" } }, - "node_modules/keytar": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", - "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.0.1" - } - }, - "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3132,15 +2237,6 @@ "node": ">=0.10.0" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -3150,30 +2246,6 @@ "immediate": "~3.0.5" } }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3190,9 +2262,10 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -3210,60 +2283,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -3279,76 +2298,34 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "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==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3365,11 +2342,72 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -3386,209 +2424,98 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "optional": true - }, "node_modules/mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/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/mocha/node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mocha/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": "*" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/mocha/node_modules/minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/ms": { + "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/monaco-page-objects": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/monaco-page-objects/-/monaco-page-objects-3.12.0.tgz", - "integrity": "sha512-JiA24MmjeilFUumMtch9v/nzHWFt1TgMt9oRYmQJ7BwOFucFFxU+ksNmEwp5Je3b3tn1F+gDI3A1QwEhdOxXOg==", - "dev": true, - "dependencies": { - "clipboardy": "^4.0.0", - "clone-deep": "^4.0.1", - "compare-versions": "^6.1.0", - "fs-extra": "^11.2.0", - "ts-essentials": "^9.4.1" - }, - "peerDependencies": { - "selenium-webdriver": "^4.6.1", - "typescript": ">=4.6.2" - } - }, - "node_modules/monaco-page-objects/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true, - "optional": true + "license": "MIT" }, "node_modules/neo-async": { "version": "2.6.2", @@ -3596,30 +2523,10 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/node-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", - "dev": true, - "optional": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true, - "optional": true - }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "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": { @@ -3631,97 +2538,163 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "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": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, - "dependencies": { - "boolbase": "^1.0.0" + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, + "license": "MIT", "dependencies": { - "wrappy": "1" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "node_modules/ora/node_modules/log-symbols/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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, "engines": { - "node": ">=12.20" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/p-limit": { @@ -3763,55 +2736,18 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "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/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.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/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3846,29 +2782,26 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -3878,22 +2811,16 @@ "node": ">=8" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "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==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "engines": { "node": ">=8.6" }, @@ -3965,156 +2892,30 @@ "node": ">=8" } }, - "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "dev": true, - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/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/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "optional": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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/readable-stream": { "version": "2.3.8", @@ -4132,15 +2933,16 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/rechoir": { @@ -4190,12 +2992,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", @@ -4217,16 +3013,18 @@ "node": ">=8" } }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { - "lowercase-keys": "^3.0.0" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4241,21 +3039,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4284,25 +3067,10 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dev": true, - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true - }, "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "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", @@ -4311,34 +3079,17 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" } }, - "node_modules/selenium-webdriver": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.16.0.tgz", - "integrity": "sha512-IbqpRpfGE7JDGgXHJeWuCqT/tUqnLvZ14csSwt+S8o4nJo3RtQoE9VR4jB47tP/A8ArkYsh/THuMY6kyRP6kuA==", - "dev": true, - "dependencies": { - "jszip": "^3.10.1", - "tmp": "^0.2.1", - "ws": ">=8.14.2" - }, - "engines": { - "node": ">= 14.20.0" - } - }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -4347,27 +3098,13 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.4" + "node": ">=20.0.0" } }, "node_modules/setimmediate": { @@ -4409,20 +3146,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4435,53 +3158,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true, - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -4518,6 +3194,19 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "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", @@ -4581,18 +3270,6 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4632,147 +3309,35 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/system-architecture": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", - "integrity": "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "optional": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, - "optional": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, "engines": { "node": ">=6" - } - }, - "node_modules/tar-stream/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, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/targz": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/targz/-/targz-1.0.1.tgz", - "integrity": "sha512-6q4tP9U55mZnRuMTBqnqc3nwYQY3kv+QthCFZuMk+Tn1qYUnMPmL/JZ/mzgXINzFpSqfU+242IFmFU9VPvqaQw==", - "dev": true, - "dependencies": { - "tar-fs": "^1.8.1" - } - }, - "node_modules/targz/node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/targz/node_modules/pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/targz/node_modules/tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", - "dev": true, - "dependencies": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" - } - }, - "node_modules/targz/node_modules/tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tas-client": { - "version": "0.1.73", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.73.tgz", - "integrity": "sha512-UDdUF9kV2hYdlv+7AgqP2kXarVSUhjK7tg1BUflIRGEgND0/QoNpN64rcEuhEcM8AIbW65yrCopJWqRhLZ3m8w==", - "dependencies": { - "axios": "^1.6.1" + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.4.3.tgz", + "integrity": "sha512-6bqNgMv7ys5PL6Zqz+EoR8J5KrhAGFjodUPkcpM80DHFakKiWcjqKiID5qxsssC/E70fcgYYWPAUK7CWS29b+Q==", + "engines": { + "node": ">=22" } }, "node_modules/terser": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.1.tgz", - "integrity": "sha512-27hxBUVdV6GoNg1pKQ7Z5cbR6V9txPVyBA+FQw3BaZ1Wuzvztce5p156DaP0NVZNrMZZ+6iG9Syf7WgMNKDg2Q==", + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.2.tgz", + "integrity": "sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -4783,107 +3348,51 @@ "node": ">=10" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": ">= 10.13.0" + "node": ">=12.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" }, "peerDependencies": { - "webpack": "^5.1.0" + "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { + "picomatch": { "optional": true } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, "engines": { - "node": ">= 10.13.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": 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", @@ -4895,55 +3404,49 @@ "node": ">=8.0" } }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "node_modules/ts-loader": { + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz", + "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==", "dev": true, "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, - "node_modules/ts-essentials": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.1.tgz", - "integrity": "sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==", - "dev": true, + "chalk": "^4.1.0", + "picomatch": "^4.0.0", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { - "typescript": ">=4.1.0" + "loader-utils": "*", + "typescript": "*", + "webpack": "^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { - "typescript": { + "loader-utils": { "optional": true } } }, - "node_modules/ts-loader": { - "version": "9.4.4", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz", - "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==", + "node_modules/ts-loader/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, "engines": { - "node": ">=12.0.0" + "node": ">=12" }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/ts-loader/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/tslib": { @@ -5004,9 +3507,9 @@ } }, "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==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", @@ -5070,9 +3573,9 @@ } }, "node_modules/tslint/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "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", @@ -5083,9 +3586,9 @@ } }, "node_modules/tslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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" @@ -5127,39 +3630,6 @@ "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/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", - "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -5173,17 +3643,16 @@ "node": ">=4.2.0" } }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==" }, "node_modules/universalify": { "version": "2.0.0", @@ -5193,28 +3662,10 @@ "node": ">= 10.0.0" } }, - "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "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": [ { @@ -5231,8 +3682,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -5241,168 +3692,94 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "node_modules/utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", - "dev": true - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/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==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry-wrapper/-/vscode-extension-telemetry-wrapper-0.15.2.tgz", + "integrity": "sha512-efKkHF8c4kTKyBhBH2k0bZU4drqIic2jBYw/j1ixKOEEsa/WIiuUsdrBPD5uaRIoZ/91GzNCLiiV4ckIrf581g==", + "license": "MIT", "dependencies": { - "@vscode/extension-telemetry": "^0.9.6", - "uuid": "^8.3.2" + "@microsoft/applicationinsights-common": "^3.4.1", + "@vscode/extension-telemetry": "^1.2.0" } }, - "node_modules/vscode-extension-tester": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-extension-tester/-/vscode-extension-tester-7.0.0.tgz", - "integrity": "sha512-ICl/ITfPZnvx9ofY2gcOg5ZndQo3MSGu6iNa2TdkPLysAYnm5H/hY3IrmwqQqjXI+id+kcxoZMB/SZlsBlxiVw==", - "dev": true, - "dependencies": { - "@types/selenium-webdriver": "^4.1.21", - "@vscode/vsce": "^2.22.0", - "commander": "^11.1.0", - "compare-versions": "^6.1.0", - "fs-extra": "^11.2.0", - "glob": "^10.3.10", - "got": "^13.0.0", - "hpagent": "^1.2.0", - "js-yaml": "^4.1.0", - "monaco-page-objects": "^3.12.0", - "sanitize-filename": "^1.6.3", - "selenium-webdriver": "^4.16.0", - "targz": "^1.0.1", - "unzipper": "^0.10.14", - "vscode-extension-tester-locators": "^3.10.0" - }, - "bin": { - "extest": "out/cli.js" + "node_modules/vscode-extension-telemetry-wrapper/node_modules/@microsoft/applicationinsights-common": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.4.1.tgz", + "integrity": "sha512-CTbD0g/68tiv2yCItsodDQBYxyHdfQkG7VhvVU8OHenukpl/7W4wEuxZuOntqhv5m9Nx/DFncbz+T83nvYTG3g==", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-core-js": "3.4.1", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-utils": ">= 0.12.6 < 2.x" }, "peerDependencies": { - "mocha": ">=5.2.0", - "typescript": ">=4.6.2" - } - }, - "node_modules/vscode-extension-tester-locators": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/vscode-extension-tester-locators/-/vscode-extension-tester-locators-3.10.0.tgz", - "integrity": "sha512-smhCxci1FtaK1ZHVnRtrnv+5YIDAFPkXBWRkyKzrf7CBA4Zpg5hleLKipEVEygBj/MrFCW4oYexqti9hOJX3bw==", - "dev": true, - "peerDependencies": { - "monaco-page-objects": "^3.12.0", - "selenium-webdriver": "^4.6.1" + "tslib": ">= 1.0.0" } }, - "node_modules/vscode-extension-tester/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/vscode-extension-tester/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, + "node_modules/vscode-extension-telemetry-wrapper/node_modules/@microsoft/applicationinsights-core-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.4.1.tgz", + "integrity": "sha512-eXIHZ1+nvBiJgVpufBiTP801Vtr5FEwjWZioUsb44NC/z/UcsZh2MDJ1mBpjaDO73LVYUw/ZZmDCCo6Pg/61kA==", + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.5 < 2.x", + "@nevware21/ts-utils": ">= 0.12.6 < 2.x" }, - "engines": { - "node": ">=14.14" + "peerDependencies": { + "tslib": ">= 1.0.0" } }, - "node_modules/vscode-extension-tester/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, + "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==", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=14.0.0" } }, - "node_modules/vscode-extension-tester/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, + "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==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" } }, + "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==", + "license": "MIT" + }, "node_modules/vscode-tas-client": { - "version": "0.1.75", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.75.tgz", - "integrity": "sha512-/+ALFWPI4U3obeRvLFSt39guT7P9bZQrkmcLoiS+2HtzJ/7iPKNt5Sj+XTiitGlPYVFGFc0plxX8AAp6Uxs0xQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.3.0.tgz", + "integrity": "sha512-69e8Ek86+LwfNp9oh6b7xEnM9M15IX8W+ZhHo2/tCbbnB/TOPK3aDle3iOZa8aeBoGKeaStUkSKaloIvIkmNXg==", "dependencies": { - "tas-client": "0.1.73" + "tas-client": "^0.4.2" }, "engines": { - "vscode": "^1.19.1" + "vscode": "^1.85.0" } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "dev": true, "dependencies": { - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { @@ -5410,35 +3787,31 @@ } }, "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "version": "5.109.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.109.0.tgz", + "integrity": "sha512-vomrngskVVXEZF9sMZfYAd4pXZUnfaWdJGlF+BTNF+gJBCKYCQBnOeVPlrh39Ewl7nlCsirDplMy6o5g9xJHBg==", + "dev": true, + "dependencies": { + "@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.16.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.24.2", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", + "graceful-fs": "^4.2.11", + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.6.1", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.1" }, "bin": { "webpack": "bin/webpack.js" @@ -5526,61 +3899,21 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz", + "integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==", "dev": true, "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.6" } }, "node_modules/which": { @@ -5605,9 +3938,9 @@ "dev": true }, "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true }, "node_modules/wrap-ansi": { @@ -5651,58 +3984,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5712,36 +3993,31 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -5759,25 +4035,6 @@ "node": ">=10" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5793,95 +4050,120 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "requires": { - "@babel/highlight": "^7.22.5" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true }, - "@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.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 - }, - "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 - }, - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "@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 }, + "@github/copilot-darwin-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.78.tgz", + "integrity": "sha512-P11+VyWg8ad0WlywGtO2d7AxqTLJv4hkUicFg6Ycth5lfk00aCu/74YOOZSPO6C2bBBJhAza7oAdmauM6KEojw==", + "optional": true + }, + "@github/copilot-darwin-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.78.tgz", + "integrity": "sha512-stimP3WDFs2GU8nJzTJbtRpZViV4bsf80yg7QrFq+G4RISQ3Nihg/3/H0U6UQF1+txMJ/Ohmb5RFYxSw1Hj2sw==", + "optional": true + }, + "@github/copilot-language-server": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.530.0.tgz", + "integrity": "sha512-7OjTbKqkA9NSf8Yjms19qglBswdK7IkorbzB0EpfPOPeT8UdmxW0fiYCiaTsyB+VizMzchrPh0nbik8gH8boKw==", + "requires": { + "@github/copilot-darwin-arm64": "1.0.78", + "@github/copilot-darwin-x64": "1.0.78", + "@github/copilot-language-server-darwin-arm64": "1.530.0", + "@github/copilot-language-server-darwin-x64": "1.530.0", + "@github/copilot-language-server-linux-arm64": "1.530.0", + "@github/copilot-language-server-linux-x64": "1.530.0", + "@github/copilot-language-server-win32-arm64": "1.530.0", + "@github/copilot-language-server-win32-x64": "1.530.0", + "@github/copilot-linux-arm64": "1.0.78", + "@github/copilot-linux-x64": "1.0.78", + "@github/copilot-win32-arm64": "1.0.78", + "@github/copilot-win32-x64": "1.0.78", + "vscode-languageserver-protocol": "^3.17.5" + } + }, + "@github/copilot-language-server-darwin-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-arm64/-/copilot-language-server-darwin-arm64-1.530.0.tgz", + "integrity": "sha512-WREnhFgvqDUHOYZTOmd0XldA3DtJ7XEn4leAezDEW4iwhoTyROmGSjH02ROj2l22Zdtq5byATidjDHGn5CnO/g==", + "optional": true + }, + "@github/copilot-language-server-darwin-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-x64/-/copilot-language-server-darwin-x64-1.530.0.tgz", + "integrity": "sha512-rHBRaA6MtbQSCOF7vDgcPEiukWmmggwuoOcqqi7yKvcq6/K7MDW9jtydq6HP/mg0fUe44l0sG/h9/MQlQcljvA==", + "optional": true + }, + "@github/copilot-language-server-linux-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-arm64/-/copilot-language-server-linux-arm64-1.530.0.tgz", + "integrity": "sha512-2Wvdm3IogKHSUsN6zlleK91CdKoiGIf2R0n0P5ZHcLxaGix29fPGMa/hl5A9wkpnnV7szBDUKTHqwZoMxtPOvA==", + "optional": true + }, + "@github/copilot-language-server-linux-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-x64/-/copilot-language-server-linux-x64-1.530.0.tgz", + "integrity": "sha512-1MIg6t+TS67sEpjb5jqf2BhjRrYW3sLlSyCxAT+a76ZUwlLjmrVFlpU2R6B/HIQDQhoxuvZwQ6YXmfxCVufDmw==", + "optional": true + }, + "@github/copilot-language-server-win32-arm64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-arm64/-/copilot-language-server-win32-arm64-1.530.0.tgz", + "integrity": "sha512-xlTuNNZQUg+WM2RJTvdlbcYKyQCCOWQaXTn5sGGZ38tSB+gPKcCDr39c5AgWZ4KS/1jk+pxn0b74+PMkyWyxow==", + "optional": true + }, + "@github/copilot-language-server-win32-x64": { + "version": "1.530.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-x64/-/copilot-language-server-win32-x64-1.530.0.tgz", + "integrity": "sha512-tI2dPAWplfsbLL94CyuFfm3R8YfCGlT8dmPbbaa2e6E9/GoBkYugcTtDH2a5qkaPk1t2LJeUTDiN/Uhr/HNAPw==", + "optional": true + }, + "@github/copilot-linux-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.78.tgz", + "integrity": "sha512-K31PRKGTm252V1Lof7ypjg283R2QSm3BgoCvZfX2taos4wqC3SaTozSQKwW3dgrAx7A3G3SGEoilVCNqfigdZA==", + "optional": true + }, + "@github/copilot-linux-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.78.tgz", + "integrity": "sha512-QK3oMtAn9dIv+1u1kx0xNpZNtZxdI+uZVIyLl7myp+Oh2Uj8BLagVv6a7uP0cDphO3TgfIdlvpepCe5MIcx0fw==", + "optional": true + }, + "@github/copilot-win32-arm64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.78.tgz", + "integrity": "sha512-ktDkFXaaecEKD3hpM6ydM9lKOdoCfsQsXCmzLzE7DCmSpbbMCdfPfWfZ7MOclmKmpZ5/MNfr4U2l8CUqGerzYA==", + "optional": true + }, + "@github/copilot-win32-x64": { + "version": "1.0.78", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.78.tgz", + "integrity": "sha512-Gd8l2T4eqYEWlOEPd0SZznQ+YYgYrwOkE0QXodMkhCBbPdgu/uTzb7mnISWwnVAgqs7pONdF1GOpHkTo+ay8CQ==", + "optional": true + }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -5948,111 +4230,104 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "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/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "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.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "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.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "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.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "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" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@microsoft/1ds-core-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.2.2.tgz", - "integrity": "sha512-4c1AXzOj7ZyX7/97v8fEDYcQ8ymTTmj+j9HYYlcO0/cUbDzZGA7/xzb34chvvAbV60qDEbX0Ha/ea7wzgefORg==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-4.3.10.tgz", + "integrity": "sha512-5fSZmkGwWkH+mrIA5M1GYPZdPM+SjXwCCl2Am7VhFoVwOBJNhRnwvIpAdzw6sFjiebN/rz+/YH0NdxztGZSa9Q==", "requires": { - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/1ds-post-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.2.2.tgz", - "integrity": "sha512-0k1aSxD03r3ugLaYhI8Y8AonI/whOzSQd66XBYURVTs6uheMMxDQdSnAk/4Dwn/TUK3TCEJZBIwZRVpUJtJX9w==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-4.3.10.tgz", + "integrity": "sha512-VSLjc9cT+Y+eTiSfYltJHJCejn8oYr0E6Pq2BMhOEO7F6IyLGYIxzKKvo78ze9x+iHX7KPTATcZ+PFgjGXuNqg==", "requires": { - "@microsoft/1ds-core-js": "4.2.2", + "@microsoft/1ds-core-js": "4.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/applicationinsights-channel-js": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.2.2.tgz", - "integrity": "sha512-4ruoKxgZYYa+K8JJu8RMY0egKazS8xClbx70NQHa/rJ7JYFgN3OIEIBZtFoMcHR8Vg7MEsNE5/wV6o7WWJkVIA==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.3.10.tgz", + "integrity": "sha512-iolFLz1ocWAzIQqHIEjjov3gNTPkgFQ4ArHnBcJEYoffOGWlJt6copaevS5YPI5rHzmbySsengZ8cLJJBBrXzQ==", "requires": { - "@microsoft/applicationinsights-common": "3.2.2", - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-common": "3.3.10", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/applicationinsights-common": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.2.2.tgz", - "integrity": "sha512-e1C35gdkFSzWyUUR1S8FvisXW3nT3p6wWsLNs+vUKLOTQzsvW3XpNMVtNCq4MfHWiYDuz1lPSzo2eENaij1fVA==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.3.10.tgz", + "integrity": "sha512-RVIenPIvNgZCbjJdALvLM4rNHgAFuHI7faFzHCgnI6S2WCUNGHeXlQTs9EUUrL+n2TPp9/cd0KKMILU5VVyYiA==", "requires": { - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/applicationinsights-core-js": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.2.2.tgz", - "integrity": "sha512-dF6LZ4ahdhoHufw+N7OXRDzWT8QN193Dvpd8GLqEZdR/KtCTofPSI63yumu+ZkzKYadf1S3w2xg0OmbdyXexoQ==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.10.tgz", + "integrity": "sha512-5yKeyassZTq2l+SAO4npu6LPnbS++UD+M+Ghjm9uRzoBwD8tumFx0/F8AkSVqbniSREd+ztH/2q2foewa2RZyg==", "requires": { "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/applicationinsights-shims": { @@ -6064,17 +4339,17 @@ } }, "@microsoft/applicationinsights-web-basic": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.2.2.tgz", - "integrity": "sha512-4OdgTurRr/Awm2DcWuAhidFON2UFiirabeO9SSAeTefDCdtzv5fWzntq9zvdV47c+w6WzZkz8nX/bQTgNRb2+w==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.3.10.tgz", + "integrity": "sha512-AZib5DAT3NU0VT0nLWEwXrnoMDDgZ/5S4dso01CNU5ELNxLdg+1fvchstlVdMy4FrAnxzs8Wf/GIQNFYOVgpAw==", "requires": { - "@microsoft/applicationinsights-channel-js": "3.2.2", - "@microsoft/applicationinsights-common": "3.2.2", - "@microsoft/applicationinsights-core-js": "3.2.2", + "@microsoft/applicationinsights-channel-js": "3.3.10", + "@microsoft/applicationinsights-common": "3.3.10", + "@microsoft/applicationinsights-core-js": "3.3.10", "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.1 < 2.x", - "@nevware21/ts-utils": ">= 0.11.1 < 2.x" + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" } }, "@microsoft/dynamicproto-js": { @@ -6086,17 +4361,17 @@ } }, "@nevware21/ts-async": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.1.tgz", - "integrity": "sha512-O2kN8n2HpDWJ7Oji+oTMnhITrCndmrNvrHbGDwAIBydx+FWvLE/vrw4QwnRRMvSCa2AJrcP59Ryklxv30KfkWQ==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.5.tgz", + "integrity": "sha512-vwqaL05iJPjLeh5igPi8MeeAu10i+Aq7xko1fbo9F5Si6MnVN5505qaV7AhSdk5MCBJVT/UYMk3kgInNjDb4Ig==", "requires": { - "@nevware21/ts-utils": ">= 0.11.2 < 2.x" + "@nevware21/ts-utils": ">= 0.12.2 < 2.x" } }, "@nevware21/ts-utils": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.2.tgz", - "integrity": "sha512-80W8BkS09kkGuUHJX50Fqq+QqAslxUaOQytH+3JhRacXs1EpEt2JOOkYKytqFZAYir3SeH9fahniEaDzIBxlUw==" + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.14.0.tgz", + "integrity": "sha512-WoeqTIXQ8WPhl+lD2NbMHoAQ4sJl0n7EoRoDmVJui//Usg512enl9q1fdbVobuZt3omnxnmVsDrNIvPBvFgddQ==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -6121,58 +4396,151 @@ "fastq": "^1.6.0" } }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true + "@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==" }, - "@sindresorhus/is": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.5.2.tgz", - "integrity": "sha512-8ZMK+V6YpeZFfW6hU9uAeWVuq8v3t7BaG276gIO+kVqnAcLrHCXdFUOf7kgouyfAarkZtuavIqY3RsXTsTWviw==", - "dev": true + "@octokit/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", + "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "requires": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + } }, - "@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, + "@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", "requires": { - "defer-to-connect": "^2.0.1" + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" } }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true + "@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "requires": { + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + } }, - "@types/eslint": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", - "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", - "dev": true, + "@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==" + }, + "@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "requires": { + "@octokit/types": "^13.10.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "requires": { + "@octokit/openapi-types": "^24.2.0" + } + } + } + }, + "@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", + "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "requires": { + "@octokit/types": "^13.10.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "requires": { + "@octokit/openapi-types": "^24.2.0" + } + } + } + }, + "@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", "requires": { - "@types/estree": "*", - "@types/json-schema": "*" + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" } }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, + "@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "requires": { + "@octokit/types": "^14.0.0" + } + }, + "@octokit/rest": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "requires": { + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" + } + }, + "@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", "requires": { - "@types/eslint": "*", - "@types/estree": "*" + "@octokit/openapi-types": "^25.1.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true }, "@types/fs-extra": { @@ -6194,22 +4562,16 @@ "@types/node": "*" } }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "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.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.25.tgz", + "integrity": "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==", "dev": true }, "@types/minimatch": { @@ -6225,18 +4587,12 @@ "dev": true }, "@types/node": { - "version": "16.18.38", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.38.tgz", - "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==", - "dev": true - }, - "@types/selenium-webdriver": { - "version": "4.1.21", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-4.1.21.tgz", - "integrity": "sha512-QGURnImvxYlIQz5DVhvHdqpYNLBjhJ2Vm+cnQI2G9QZzkWlZm0LkLcvDcHp+qE6N2KBz4CeuvXgPO7W3XQ0Tyw==", + "version": "20.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz", + "integrity": "sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==", "dev": true, "requires": { - "@types/ws": "*" + "undici-types": "~6.19.2" } }, "@types/semver": { @@ -6246,303 +4602,177 @@ "dev": true }, "@types/vscode": { - "version": "1.83.1", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", - "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", - "dev": true - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "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.6", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.6.tgz", - "integrity": "sha512-qWK2GNw+b69QRYpjuNM9g3JKToMICoNIdc0rQMtvb4gIG9vKKCZCVCz+ZOx6XM/YlfWAyuPiyxcjIY0xyF+Djg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-1.2.0.tgz", + "integrity": "sha512-En6dTwfy5NFzSMibvOpx/lKq2jtgWuR4++KJbi3SpQ2iT8gm+PHo9868/scocW122KDwTxl4ruxZ7i4rHmJJnQ==", "requires": { - "@microsoft/1ds-core-js": "^4.1.2", - "@microsoft/1ds-post-js": "^4.1.2", - "@microsoft/applicationinsights-web-basic": "^3.1.2" + "@microsoft/1ds-core-js": "^4.3.10", + "@microsoft/1ds-post-js": "^4.3.10", + "@microsoft/applicationinsights-web-basic": "^3.3.10" } }, "@vscode/test-electron": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.8.tgz", - "integrity": "sha512-b4aZZsBKtMGdDljAsOPObnAi7+VWIaYl3ylCz1jTs+oV6BZ4TNHcVNC3xUn0azPeszBmwSBDQYfFESIaUQnrOg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-3.1.0.tgz", + "integrity": "sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw==", "dev": true, "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", - "semver": "^7.5.2" - } - }, - "@vscode/vsce": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.22.0.tgz", - "integrity": "sha512-8df4uJiM3C6GZ2Sx/KilSKVxsetrTBBIUb3c0W4B1EWHcddioVs5mkyDKtMNP0khP/xBILVSzlXxhV+nm2rC9A==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.2.1", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "jsonc-parser": "^3.2.0", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^7.5.2", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.5.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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, - "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 - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "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": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "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 - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "ora": "^8.1.0", + "semver": "^7.6.2" } }, "@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "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.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "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.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "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.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "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.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "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.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@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.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "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.11.6", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -6582,37 +4812,30 @@ "dev": true }, "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} - }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "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" + "debug": "^4.3.4" } }, "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "ajv-formats": { @@ -6633,12 +4856,6 @@ "fast-deep-equal": "^3.1.3" } }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6654,128 +4871,37 @@ "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 }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, "await-lock": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==" }, - "axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "azure-devops-node-api": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz", - "integrity": "sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "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, - "optional": true - }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^5.5.0", - "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, - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "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 }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" }, "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "requires": { "balanced-match": "^1.0.0" } @@ -6795,112 +4921,30 @@ "dev": true }, "browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "optional": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "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-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", - "dev": true - }, "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 }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "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 }, - "cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true - }, - "cacheable-request": { - "version": "10.2.12", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.12.tgz", - "integrity": "sha512-qtWGB5kn2OLjx47pYUkWicyOpK1vy9XZhq8yRTXOy+KAmjjESSRLx6SiExnnaGGUP1NM6/vmygMu0fGylNh9tw==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "^4.0.1", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.2", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - } - }, - "call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "requires": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - } - }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -6908,20 +4952,11 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001517", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", - "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", + "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 }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6943,93 +4978,44 @@ } } }, - "cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "requires": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - } - }, - "cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - } - }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "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" - }, - "dependencies": { - "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" - } - } + "readdirp": "^4.0.1" } }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true }, - "clipboardy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", - "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==", + "cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "requires": { - "execa": "^8.0.1", - "is-wsl": "^3.1.0", - "is64bit": "^2.0.0" + "restore-cursor": "^5.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==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, @@ -7065,26 +5051,12 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "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": "6.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", - "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7092,17 +5064,16 @@ "dev": true }, "copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-14.0.0.tgz", + "integrity": "sha512-3JLW90aBGeaTLpM7mYQKpnVdgsUZRExY55giiZgLuX/xTQRUs1dOCwbBnWnvY6Q6rfZoXMNwzOQJCSZPppfqXA==", "dev": true, "requires": { - "fast-glob": "^3.2.11", "glob-parent": "^6.0.1", - "globby": "^13.1.1", "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "schema-utils": "^4.2.0", + "serialize-javascript": ">=7.0.5", + "tinyglobby": "^0.2.12" } }, "core-util-is": { @@ -7112,9 +5083,9 @@ "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -7122,32 +5093,13 @@ "which": "^2.0.1" } }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "decamelize": { @@ -7156,63 +5108,10 @@ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "optional": true - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "dev": true, - "optional": true - }, "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true }, "dir-glob": { @@ -7223,52 +5122,6 @@ "path-type": "^4.0.0" } }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -7276,9 +5129,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.467", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", - "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", + "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": { @@ -7287,31 +5140,16 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", "dev": true, "requires": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" } }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - }, "envinfo": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", @@ -7319,15 +5157,15 @@ "dev": true }, "es-module-lexer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", - "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", "dev": true }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "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": { @@ -7381,37 +5219,10 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true }, - "execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - } - } - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "optional": true + "fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==" }, "fast-deep-equal": { "version": "3.1.3", @@ -7420,15 +5231,15 @@ "dev": true }, "fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "dependencies": { "glob-parent": { @@ -7441,10 +5252,10 @@ } } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "dev": true }, "fastest-levenshtein": { @@ -7461,15 +5272,6 @@ "reusify": "^1.0.4" } }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -7502,43 +5304,16 @@ "lodash": "^4.17.21" } }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" - }, "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "requires": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, "fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -7555,36 +5330,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -7597,31 +5342,12 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "requires": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", "dev": true }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true, - "optional": true - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -7637,9 +5363,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -7647,9 +5373,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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" @@ -7666,12 +5392,6 @@ "is-glob": "^4.0.3" } }, - "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 - }, "globby": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", @@ -7684,45 +5404,11 @@ "slash": "^4.0.0" } }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", - "dev": true, - "requires": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - } - }, "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==" }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -7738,119 +5424,32 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.2" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "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 }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "hpagent": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", - "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", - "dev": true - }, - "htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "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": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "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": "6", + "agent-base": "^7.0.2", "debug": "4" } }, - "human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "optional": true - }, "ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -7888,28 +5487,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "optional": true - }, "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.12.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", @@ -7919,12 +5502,6 @@ "has": "^1.0.3" } }, - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7944,20 +5521,23 @@ "is-extglob": "^2.1.1" } }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "requires": { - "is-docker": "^3.0.0" - } + "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==" }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -7973,35 +5553,11 @@ "isobject": "^3.0.1" } }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "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 - }, - "is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "requires": { - "is-inside-container": "^1.0.0" - } - }, - "is64bit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is64bit/-/is64bit-2.0.0.tgz", - "integrity": "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==", - "dev": true, - "requires": { - "system-architecture": "^0.1.0" - } + "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", @@ -8021,16 +5577,6 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, "jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -8049,38 +5595,20 @@ "dev": true }, "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, "requires": { "argparse": "^2.0.1" } }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "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 }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -8102,38 +5630,12 @@ "setimmediate": "^1.0.5" } }, - "keytar": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", - "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", - "dev": true, - "optional": true, - "requires": { - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.0.1" - } - }, - "keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, "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 }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, "lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -8143,27 +5645,6 @@ "immediate": "~3.0.5" } }, - "linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "dev": true - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8174,9 +5655,9 @@ } }, "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==" }, "log-symbols": { "version": "4.1.0", @@ -8188,47 +5669,6 @@ "is-unicode-supported": "^0.1.0" } }, - "lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "requires": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - } - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -8241,49 +5681,24 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "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==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "requires": { "brace-expansion": "^2.0.1" } @@ -8294,10 +5709,22 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "minimizer-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + } + }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true }, "mkdirp": { @@ -8309,201 +5736,86 @@ "minimist": "^1.2.6" } }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "optional": true - }, "mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "requires": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": ">=7.0.5", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" }, "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" } }, - "minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.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 - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "monaco-page-objects": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/monaco-page-objects/-/monaco-page-objects-3.12.0.tgz", - "integrity": "sha512-JiA24MmjeilFUumMtch9v/nzHWFt1TgMt9oRYmQJ7BwOFucFFxU+ksNmEwp5Je3b3tn1F+gDI3A1QwEhdOxXOg==", - "dev": true, - "requires": { - "clipboardy": "^4.0.0", - "clone-deep": "^4.0.1", - "compare-versions": "^6.1.0", - "fs-extra": "^11.2.0", - "ts-essentials": "^9.4.1" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "brace-expansion": "^2.0.2" } } } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true, - "optional": true - }, "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-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", - "dev": true, - "optional": true, - "requires": { - "semver": "^7.3.5" - } - }, - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true, - "optional": true - }, "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "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": { @@ -8512,44 +5824,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "dev": true - }, - "npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8560,19 +5834,94 @@ } }, "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "requires": { - "mimic-fn": "^4.0.0" + "mimic-function": "^5.0.0" } }, - "p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true + "ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, + "requires": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true + }, + "chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true + }, + "emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true + }, + "is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true + }, + "log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "requires": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "dependencies": { + "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 + } + } + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + } + } }, "p-limit": { "version": "3.1.0", @@ -8598,48 +5947,18 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "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 }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "requires": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - } - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8665,19 +5984,19 @@ "dev": true }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true } } @@ -8687,22 +6006,16 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "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==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==" }, "pkg-dir": { "version": "4.2.0", @@ -8752,115 +6065,17 @@ } } }, - "prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - } - }, "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 - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "optional": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } + "dev": true }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "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" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "optional": true - } - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, "readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -8877,13 +6092,10 @@ } }, "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" - } + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true }, "rechoir": { "version": "0.7.1", @@ -8917,12 +6129,6 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, "resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", @@ -8938,13 +6144,14 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "requires": { - "lowercase-keys": "^3.0.0" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" } }, "reusify": { @@ -8952,15 +6159,6 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8975,25 +6173,10 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dev": true, - "requires": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true - }, "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "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", @@ -9002,45 +6185,16 @@ "ajv-keywords": "^5.1.0" } }, - "selenium-webdriver": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.16.0.tgz", - "integrity": "sha512-IbqpRpfGE7JDGgXHJeWuCqT/tUqnLvZ14csSwt+S8o4nJo3RtQoE9VR4jB47tP/A8ArkYsh/THuMY6kyRP6kuA==", - "dev": true, - "requires": { - "jszip": "^3.10.1", - "tmp": "^0.2.1", - "ws": ">=8.14.2" - } - }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "requires": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - } + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", + "dev": true }, "setimmediate": { "version": "1.0.5", @@ -9072,42 +6226,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, "signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "optional": true - }, - "simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "dev": true, - "optional": true, - "requires": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -9135,6 +6259,12 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9184,12 +6314,6 @@ "ansi-regex": "^5.0.1" } }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9211,203 +6335,54 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "system-architecture": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", - "integrity": "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==", - "dev": true - }, "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "optional": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "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, - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "targz": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/targz/-/targz-1.0.1.tgz", - "integrity": "sha512-6q4tP9U55mZnRuMTBqnqc3nwYQY3kv+QthCFZuMk+Tn1qYUnMPmL/JZ/mzgXINzFpSqfU+242IFmFU9VPvqaQw==", - "dev": true, - "requires": { - "tar-fs": "^1.8.1" - }, - "dependencies": { - "bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", - "dev": true, - "requires": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } - } - } - }, "tas-client": { - "version": "0.1.73", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.73.tgz", - "integrity": "sha512-UDdUF9kV2hYdlv+7AgqP2kXarVSUhjK7tg1BUflIRGEgND0/QoNpN64rcEuhEcM8AIbW65yrCopJWqRhLZ3m8w==", - "requires": { - "axios": "^1.6.1" - } + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.4.3.tgz", + "integrity": "sha512-6bqNgMv7ys5PL6Zqz+EoR8J5KrhAGFjodUPkcpM80DHFakKiWcjqKiID5qxsssC/E70fcgYYWPAUK7CWS29b+Q==" }, "terser": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.1.tgz", - "integrity": "sha512-27hxBUVdV6GoNg1pKQ7Z5cbR6V9txPVyBA+FQw3BaZ1Wuzvztce5p156DaP0NVZNrMZZ+6iG9Syf7WgMNKDg2Q==", + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.2.tgz", + "integrity": "sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" } }, - "terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "requires": {} }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } } } }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9416,38 +6391,29 @@ "is-number": "^7.0.0" } }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "dev": true - }, - "truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "dev": true, - "requires": { - "utf8-byte-length": "^1.0.1" - } - }, - "ts-essentials": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.1.tgz", - "integrity": "sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==", - "dev": true, - "requires": {} - }, "ts-loader": { - "version": "9.4.4", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz", - "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz", + "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==", "dev": true, "requires": { "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" + "picomatch": "^4.0.0", + "source-map": "^0.7.4" + }, + "dependencies": { + "picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "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 + } } }, "tslib": { @@ -9495,9 +6461,9 @@ } }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -9549,9 +6515,9 @@ "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "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", @@ -9559,9 +6525,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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" @@ -9593,281 +6559,146 @@ "tslib": "^1.8.1" } }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "typed-rest-client": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", - "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, - "underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true + "universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==" }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, - "unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "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": { - "punycode": "^2.1.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" } }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", - "dev": true - }, "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==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry-wrapper/-/vscode-extension-telemetry-wrapper-0.15.2.tgz", + "integrity": "sha512-efKkHF8c4kTKyBhBH2k0bZU4drqIic2jBYw/j1ixKOEEsa/WIiuUsdrBPD5uaRIoZ/91GzNCLiiV4ckIrf581g==", "requires": { - "@vscode/extension-telemetry": "^0.9.6", - "uuid": "^8.3.2" - } - }, - "vscode-extension-tester": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-extension-tester/-/vscode-extension-tester-7.0.0.tgz", - "integrity": "sha512-ICl/ITfPZnvx9ofY2gcOg5ZndQo3MSGu6iNa2TdkPLysAYnm5H/hY3IrmwqQqjXI+id+kcxoZMB/SZlsBlxiVw==", - "dev": true, - "requires": { - "@types/selenium-webdriver": "^4.1.21", - "@vscode/vsce": "^2.22.0", - "commander": "^11.1.0", - "compare-versions": "^6.1.0", - "fs-extra": "^11.2.0", - "glob": "^10.3.10", - "got": "^13.0.0", - "hpagent": "^1.2.0", - "js-yaml": "^4.1.0", - "monaco-page-objects": "^3.12.0", - "sanitize-filename": "^1.6.3", - "selenium-webdriver": "^4.16.0", - "targz": "^1.0.1", - "unzipper": "^0.10.14", - "vscode-extension-tester-locators": "^3.10.0" + "@microsoft/applicationinsights-common": "^3.4.1", + "@vscode/extension-telemetry": "^1.2.0" }, "dependencies": { - "commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, + "@microsoft/applicationinsights-common": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.4.1.tgz", + "integrity": "sha512-CTbD0g/68tiv2yCItsodDQBYxyHdfQkG7VhvVU8OHenukpl/7W4wEuxZuOntqhv5m9Nx/DFncbz+T83nvYTG3g==", "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "@microsoft/applicationinsights-core-js": "3.4.1", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-utils": ">= 0.12.6 < 2.x" } }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, + "@microsoft/applicationinsights-core-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.4.1.tgz", + "integrity": "sha512-eXIHZ1+nvBiJgVpufBiTP801Vtr5FEwjWZioUsb44NC/z/UcsZh2MDJ1mBpjaDO73LVYUw/ZZmDCCo6Pg/61kA==", "requires": { - "brace-expansion": "^2.0.1" + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.5 < 2.x", + "@nevware21/ts-utils": ">= 0.12.6 < 2.x" } } } }, - "vscode-extension-tester-locators": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/vscode-extension-tester-locators/-/vscode-extension-tester-locators-3.10.0.tgz", - "integrity": "sha512-smhCxci1FtaK1ZHVnRtrnv+5YIDAFPkXBWRkyKzrf7CBA4Zpg5hleLKipEVEygBj/MrFCW4oYexqti9hOJX3bw==", - "dev": true, - "requires": {} + "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-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" + } + }, + "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-tas-client": { - "version": "0.1.75", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.75.tgz", - "integrity": "sha512-/+ALFWPI4U3obeRvLFSt39guT7P9bZQrkmcLoiS+2HtzJ/7iPKNt5Sj+XTiitGlPYVFGFc0plxX8AAp6Uxs0xQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.3.0.tgz", + "integrity": "sha512-69e8Ek86+LwfNp9oh6b7xEnM9M15IX8W+ZhHo2/tCbbnB/TOPK3aDle3iOZa8aeBoGKeaStUkSKaloIvIkmNXg==", "requires": { - "tas-client": "0.1.73" + "tas-client": "^0.4.2" } }, "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "dev": true, "requires": { - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "version": "5.109.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.109.0.tgz", + "integrity": "sha512-vomrngskVVXEZF9sMZfYAd4pXZUnfaWdJGlF+BTNF+gJBCKYCQBnOeVPlrh39Ewl7nlCsirDplMy6o5g9xJHBg==", + "dev": true, + "requires": { + "@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.16.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.24.2", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", + "graceful-fs": "^4.2.11", + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.6.1", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.1" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } } } }, @@ -9910,9 +6741,9 @@ } }, "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz", + "integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==", "dev": true }, "which": { @@ -9931,9 +6762,9 @@ "dev": true }, "workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true }, "wrap-ansi": { @@ -9964,65 +6795,31 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true, - "requires": {} - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "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 }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, "yargs-unparser": { @@ -10037,25 +6834,6 @@ "is-plain-obj": "^2.1.0" } }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index b72d6b19..9206965c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-java-dependency", "displayName": "Project Manager for Java", "description": "%description%", - "version": "0.24.0", + "version": "0.27.6", "publisher": "vscjava", "preview": false, "aiKey": "5c642b22-e845-4400-badb-3f8509a70777", @@ -12,7 +12,7 @@ "explorer" ], "engines": { - "vscode": "^1.83.1" + "vscode": "^1.95.0" }, "repository": { "type": "git", @@ -46,7 +46,73 @@ "main": "./main.js", "contributes": { "javaExtensions": [ - "./server/com.microsoft.jdtls.ext.core-0.24.0.jar" + "./server/com.microsoft.jdtls.ext.core-0.24.1.jar" + ], + "languageModelTools": [ + { + "name": "lsp_java_getFileStructure", + "toolReferenceName": "javaFileStructure", + "modelDescription": "Outline a known Java file (classes, methods, fields with line ranges) to pick a precise read_file range instead of reading the whole file. Needs a path from lsp_java_findSymbol or the user — do not guess. Returns file plus per-symbol readFileRange ({ offset, limit }) for read_file. Use limit to cap outline items (default 20, max 60). Not for workspace search (use lsp_java_findSymbol).", + "displayName": "Java: Get File Structure", + "userDescription": "Get a Java file outline with classes, methods, fields, and line ranges.", + "tags": [ + "java", + "lsp", + "code-navigation", + "file-outline" + ], + "canBeReferencedInPrompt": true, + "icon": "$(symbol-class)", + "when": "config.vscode-java-dependency.enableLspTools && javaLSReady", + "inputSchema": { + "type": "object", + "properties": { + "uri": { + "type": "string", + "description": "Workspace-relative path to a Java file, from lsp_java_findSymbol or user input — do not guess." + }, + "limit": { + "type": "number", + "description": "Maximum outline items to return (default: 20, max: 60). Use a smaller value when only top-level context is needed." + } + }, + "required": [ + "uri" + ] + } + }, + { + "name": "lsp_java_findSymbol", + "toolReferenceName": "javaFindSymbol", + "modelDescription": "Find Java class/interface/method/field definitions across the workspace by name or partial identifier. Prefer over grep_search, file_search, or semantic_search for Java symbol lookup. Each result has file and readFileInput ({ filePath, offset, limit }) for read_file; use it when source is needed, or lsp_java_getFileStructure with file for broader context. On empty results don't re-search (it retries internally); retry once only if it reports indexing in progress, else use generic search. Not for non-Java files, literals, comments, or build/XML files.", + "displayName": "Java: Find Symbol", + "userDescription": "Find Java class, method, field, or interface definitions by name.", + "tags": [ + "java", + "lsp", + "code-navigation", + "symbol-search" + ], + "canBeReferencedInPrompt": true, + "icon": "$(search)", + "when": "config.vscode-java-dependency.enableLspTools && javaLSReady", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Symbol name or pattern to search for" + }, + "limit": { + "type": "number", + "description": "Maximum results (default: 20, max: 50)" + } + }, + "required": [ + "query" + ] + } + } ], "commands": [ { @@ -114,6 +180,16 @@ "title": "%contributes.commands.java.project.build.workspace%", "icon": "$(tools)" }, + { + "command": "java.project.rebuild.workspace", + "title": "%contributes.commands.java.project.rebuild.workspace%", + "icon": "$(refresh)" + }, + { + "command": "java.project.build.project", + "title": "%contributes.commands.java.project.build.project%", + "category": "Java" + }, { "command": "java.project.clean.workspace", "title": "%contributes.commands.java.project.clean.workspace%" @@ -130,7 +206,8 @@ }, { "command": "java.project.rebuild", - "title": "%contributes.commands.java.project.rebuild%" + "title": "%contributes.commands.java.project.rebuild%", + "category": "Java" }, { "command": "java.view.package.revealInProjectExplorer", @@ -288,6 +365,16 @@ "command": "java.view.package.renameFile", "title": "%contributes.commands.java.view.package.renameFile%", "category": "Java" + }, + { + "command": "_java.view.modernizeJavaProject", + "title": "%contributes.commands.java.view.modernizeJavaProject%", + "category": "Java" + }, + { + "command": "_java.upgradeWithCopilot", + "title": "%contributes.commands.java.upgradeWithCopilot%", + "category": "Java" } ], "configuration": { @@ -323,6 +410,11 @@ "description": "%configuration.java.dependency.packagePresentation%", "default": "flat" }, + "java.dependency.enableDependencyCheckup": { + "type": "boolean", + "description": "%configuration.java.dependency.enableDependencyCheckup%", + "default": true + }, "java.project.exportJar.targetPath": { "type": "string", "anyOf": [ @@ -345,6 +437,18 @@ "type": "boolean", "description": "%configuration.java.project.explorer.showNonJavaResources%", "default": true + }, + "vscode-java-dependency.enableLspTools": { + "type": "boolean", + "scope": "application", + "description": "%configuration.vscode-java-dependency.enableLspTools.description%", + "default": false, + "tags": [ + "experimental" + ], + "experiment": { + "mode": "startup" + } } } }, @@ -550,6 +654,14 @@ { "command": "_java.project.create.from.javaprojectexplorer", "when": "false" + }, + { + "command": "_java.view.modernizeJavaProject", + "when": "false" + }, + { + "command": "_java.upgradeWithCopilot", + "when": "false" } ], "explorer/context": [ @@ -568,6 +680,11 @@ "when": "explorerResourceIsFolder", "group": "1_javaactions@30" }, + { + "command": "_java.view.modernizeJavaProject", + "when": "explorerResourceIsFolder && java:serverMode", + "group": "1_javaactions@40" + }, { "command": "java.view.package.revealInProjectExplorer", "when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/ && java:serverMode == Standard", @@ -644,6 +761,11 @@ "when": "view == javaProjectExplorer && java:serverMode == Standard && config.java.project.explorer.showNonJavaResources", "group": "overflow_10@30" }, + { + "command": "java.project.rebuild.workspace", + "when": "view == javaProjectExplorer && java:serverMode == Standard && !java:noJavaProjects && !java:importFailed", + "group": "overflow_20@5" + }, { "command": "java.project.clean.workspace", "when": "view == javaProjectExplorer && java:serverMode == Standard && !java:noJavaProjects", @@ -702,7 +824,7 @@ "group": "7_modification@20" }, { - "command": "java.project.build.workspace", + "command": "java.project.build.project", "when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/", "group": "8_execution@5" }, @@ -987,7 +1109,7 @@ }, "isFullBuild": { "type": "boolean", - "default": "true", + "default": false, "description": "%taskDefinitions.java.project.build.isFullBuild%" } } @@ -1050,13 +1172,25 @@ } } } + ], + "chatSkills": [ + { + "path": "./resources/skills/java-lsp-tools/SKILL.md", + "when": "config.vscode-java-dependency.enableLspTools && javaLSReady" + } + ], + "chatInstructions": [ + { + "path": "./resources/instruments/javaLspContext.instructions.md", + "when": "config.vscode-java-dependency.enableLspTools && javaLSReady" + } ] }, "scripts": { "compile": "tsc -p . && webpack --config webpack.config.js --mode development", "watch": "webpack --mode development --watch", "test": "tsc -p . && webpack --config webpack.config.js --mode development && node ./dist/test/index.js", - "test-ui": "tsc -p . && webpack --config webpack.config.js --mode development && node ./dist/test/ui/index.js", + "test-e2e": "autotest run-all test/e2e-plans --no-llm", "build-server": "node scripts/buildJdtlsExt.js", "vscode:prepublish": "tsc -p ./ && webpack --mode production", "tslint": "tslint -t verbose --project tsconfig.json" @@ -1064,32 +1198,36 @@ "devDependencies": { "@types/fs-extra": "^9.0.13", "@types/glob": "^7.2.0", - "@types/lodash": "^4.14.191", + "@types/lodash": "^4.17.25", "@types/minimatch": "^3.0.3", "@types/mocha": "^9.1.1", - "@types/node": "^16.18.11", + "@types/node": "20.x", "@types/semver": "^7.3.13", - "@types/vscode": "1.83.1", - "@vscode/test-electron": "^2.3.8", - "copy-webpack-plugin": "^11.0.0", + "@types/vscode": "1.95.0", + "@vscode/test-electron": "^3.1.0", + "copy-webpack-plugin": "^14.0.0", "glob": "^7.2.3", - "mocha": "^9.2.2", - "ts-loader": "^9.4.2", + "mocha": "^11.7.5", + "ts-loader": "^9.6.2", "tslint": "^6.1.3", "typescript": "^4.9.4", - "vscode-extension-tester": "^7.0.0", - "webpack": "^5.76.0", + "webpack": "^5.109.0", "webpack-cli": "^4.10.0" }, "dependencies": { + "@github/copilot-language-server": "^1.530.0", + "@octokit/rest": "^21.1.1", "await-lock": "^2.2.2", "fmtr": "^1.1.4", "fs-extra": "^10.1.0", "globby": "^13.1.3", - "lodash": "^4.17.21", - "minimatch": "^5.1.6", + "lodash": "^4.18.0", + "minimatch": "^5.1.9", "semver": "^7.3.8", - "vscode-extension-telemetry-wrapper": "^0.14.0", - "vscode-tas-client": "^0.1.75" + "vscode-extension-telemetry-wrapper": "^0.15.2", + "vscode-tas-client": "^0.3.0" + }, + "overrides": { + "serialize-javascript": ">=7.0.5" } } diff --git a/package.nls.json b/package.nls.json index 8feb8343..ba8bf485 100644 --- a/package.nls.json +++ b/package.nls.json @@ -6,7 +6,9 @@ "contributes.commands.java.project.addLibraryFolders": "Add Library Folders to Project Classpath...", "contributes.commands.java.project.removeLibrary": "Remove from Project Classpath", "contributes.commands.java.view.package.refresh": "Refresh", - "contributes.commands.java.project.build.workspace": "Rebuild All", + "contributes.commands.java.project.build.workspace": "Build All", + "contributes.commands.java.project.rebuild.workspace": "Rebuild All", + "contributes.commands.java.project.build.project": "Build Project", "contributes.commands.java.project.clean.workspace": "Clean Workspace", "contributes.commands.java.project.rebuild": "Rebuild Project", "contributes.commands.java.project.update": "Reload Project", @@ -24,6 +26,7 @@ "contributes.commands.java.view.package.copyRelativeFilePath": "Copy Relative Path", "contributes.commands.java.view.package.new": "New...", "contributes.commands.java.view.package.newJavaClass": "Class...", + "contributes.commands.java.view.modernizeJavaProject": "Modernize Java project", "contributes.commands.java.view.package.newJavaInterface": "Interface...", "contributes.commands.java.view.package.newJavaEnum": "Enum...", "contributes.commands.java.view.package.newJavaRecord": "Record...", @@ -38,15 +41,18 @@ "contributes.commands.java.view.fileExplorer.newPackage": "New Java Package...", "contributes.submenus.javaProject.new": "New", "contributes.commands.java.view.menus.file.newJavaClass": "New Java File", + "contributes.commands.java.upgradeWithCopilot": "Upgrade dependencies", "configuration.java.dependency.showMembers": "Show the members in the explorer", "configuration.java.dependency.syncWithFolderExplorer": "Link Java Projects Explorer with the active editor", "configuration.java.dependency.autoRefresh": "Synchronize Java Projects explorer with changes", "configuration.java.dependency.refreshDelay": "The delay time (ms) the auto refresh is invoked when changes are detected", "configuration.java.dependency.packagePresentation": "Package presentation mode: flat or hierarchical", + "configuration.java.dependency.enableDependencyCheckup": "Show reminders when your Java runtimes or dependencies need an upgrade.", "configuration.java.project.explorer.showNonJavaResources": "When enabled, the explorer shows non-Java resources.", "configuration.java.project.exportJar.targetPath.customization": "The output path of the exported jar. Leave it empty if you want to manually pick the output location.", "configuration.java.project.exportJar.targetPath.workspaceFolder": "Export the jar file into the workspace folder. Its name is the same as the folder's.", "configuration.java.project.exportJar.targetPath.select": "Select output location manually when exporting the jar file.", + "configuration.vscode-java-dependency.enableLspTools.description": "Enable LSP tools for Java projects.", "taskDefinitions.java.project.exportJar.label": "The label of export jar task.", "taskDefinitions.java.project.exportJar.elements": "The content list of the exported jar.", "taskDefinitions.java.project.exportJar.mainClass": "The main class in the manifest of the exported jar.", diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index c962108c..c7b0b8ab 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -6,7 +6,9 @@ "contributes.commands.java.project.addLibraryFolders": "添加文件夹至项目 Classpath...", "contributes.commands.java.project.removeLibrary": "从项目 Classpath 中移除", "contributes.commands.java.view.package.refresh": "刷新", - "contributes.commands.java.project.build.workspace": "重新构建所有项目", + "contributes.commands.java.project.build.workspace": "构建所有项目", + "contributes.commands.java.project.rebuild.workspace": "重新构建所有项目", + "contributes.commands.java.project.build.project": "构建项目", "contributes.commands.java.project.clean.workspace": "清理工作空间", "contributes.commands.java.project.rebuild": "重新构建项目", "contributes.commands.java.project.update": "重新加载项目", @@ -56,7 +58,7 @@ "taskDefinitions.java.project.build.path": "被构建项目的根目录路径。绝对路径或者相对于工作空间目录的相对路径都可以使用。", "taskDefinitions.java.project.build.path.workspace": "工作空间中的所有项目。", "taskDefinitions.java.project.build.path.exclude": "'!' 后的路径将会从待构建项目路径中移除。", - "taskDefinitions.java.project.build.isFullBuild": "是否要重新构建项目。", + "taskDefinitions.java.project.build.isFullBuild": "是否要执行清理构建。", "viewsWelcome.workbench.createNewJavaProject": "您也可以[打开一个 Java 项目目录](command:_java.project.open),或点击下方按钮创建一个新的 Java 项目。\n[创建 Java 项目](command:_java.project.create.from.fileexplorer.welcome)", "viewsWelcome.workbench.noJavaProject": "当前工作空间未发现 Java 项目,您可以[打开一个 Java 项目目录](command:_java.project.open),或点击下方按钮创建一个新的 Java 项目。\n[创建 Java 项目](command:_java.project.create.from.javaprojectexplorer.welcome)", "viewsWelcome.workbench.importFailed": "加载 Java 项目时出现错误,请通过以下方式查看错误相关信息:\n[打开问题视图](command:workbench.panel.markers.view.focus)", diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json index e5de9002..cfa7462d 100644 --- a/package.nls.zh-tw.json +++ b/package.nls.zh-tw.json @@ -6,7 +6,9 @@ "contributes.commands.java.project.addLibraryFolders": "新增資料夾至專案 Classpath...", "contributes.commands.java.project.removeLibrary": "從專案 Classpath 中移除", "contributes.commands.java.view.package.refresh": "重新整理", - "contributes.commands.java.project.build.workspace": "重新建置所有專案", + "contributes.commands.java.project.build.workspace": "建置所有專案", + "contributes.commands.java.project.rebuild.workspace": "重新建置所有專案", + "contributes.commands.java.project.build.project": "建置專案", "contributes.commands.java.project.clean.workspace": "清理工作區", "contributes.commands.java.project.rebuild": "重新建置專案", "contributes.commands.java.project.update": "重新載入專案", @@ -48,10 +50,10 @@ "taskDefinitions.java.project.build.path": "被建置專案的根目錄路徑。絕對路徑或者相對於工作區目錄的相對路徑都可以使用。", "taskDefinitions.java.project.build.path.workspace": "工作區中的所有專案。", "taskDefinitions.java.project.build.path.exclude": "'!' 後的路徑將會從待建置專案路徑中移除。", - "taskDefinitions.java.project.build.isFullBuild": "是否要重新建置專案。", + "taskDefinitions.java.project.build.isFullBuild": "是否要執行清理建置。", "viewsWelcome.workbench.createNewJavaProject": "您也可以[開啟一個 Java 專案目錄](command:_java.project.open),或點擊下方按鈕建立一個新的 Java 專案。\n[建立 Java 專案](command:_java.project.create.from.fileexplorer.welcome)", "viewsWelcome.workbench.noJavaProject": "當前工作區未發現 Java 專案,您可以[開啟一個 Java 專案目錄](command:_java.project.open),或點擊下方按鈕建立一個新的 Java 專案。\n[建立 Java 專案](command:_java.project.create.from.javaprojectexplorer.welcome)", "viewsWelcome.workbench.importFailed": "加載 Java 專案時出現錯誤,請通過以下方式查看錯誤相關信息:\n[打開問題視圖](command:workbench.panel.markers.view.focus)", "viewsWelcome.workbench.inLightWeightMode": "若要檢視各專案,你可以將專案匯入到工作區中。\n[匯入專案](command:java.server.mode.switch?%5B%22Standard%22,true%5D)", "viewsWelcome.workbench.installLanguageSupport": "Java 專案視圖需要安裝並啟用 [Extension Pack for Java](command:extension.open?%5B%22vscjava.vscode-java-pack%22%5D) 以提供完整的功能。\n[安裝](command:java.project.installExtension?%5B%22vscjava.vscode-java-pack%22%5D)" -} \ No newline at end of file +} diff --git a/resources/instruments/javaLspContext.instructions.md b/resources/instruments/javaLspContext.instructions.md new file mode 100644 index 00000000..6c5d10a4 --- /dev/null +++ b/resources/instruments/javaLspContext.instructions.md @@ -0,0 +1,15 @@ +--- +description: Use Java LSP tools for precise Java symbol navigation. Prefer lsp_java_findSymbol and lsp_java_getFileStructure over generic search only when locating Java classes, methods, fields, or file outlines. +applyTo: '**/*.java' +--- + +For Java symbol navigation, two compiler-accurate `lsp_java_*` tools are available and return structured results with smaller, easier-to-interpret payloads than generic search: + +- `lsp_java_findSymbol(query)` — find class/method/field definitions by name across the workspace +- `lsp_java_getFileStructure(uri)` — get file outline (classes, methods, fields) with line ranges + +If these tools are not already available in the current tool list, load them with `tool_search` using a query such as `Java LSP symbol navigation lsp_java`. + +Use `lsp_java_findSymbol` before `grep_search`, `search_subagent`, `semantic_search`, or `file_search` only when the task is to locate Java symbols by name or partial identifier. If it returns relevant symbols and source is needed, call `read_file` with the returned `readFileInput`, or call `lsp_java_getFileStructure` with the returned `file` when broader file context is needed. + +Use `lsp_java_getFileStructure` only with a path confirmed by the user or a previous tool result. Prefer `file` from `lsp_java_findSymbol`; do not guess paths. Its output includes a top-level `file` and per-symbol `readFileRange`; to read a selected symbol, call `read_file` with `filePath=file` and that `readFileRange`. Use `limit` to keep large outlines small. Use generic search for string literals, comments, XML, Gradle/Maven files, non-Java files, or broad conceptual exploration. `lsp_java_findSymbol` already retries internally with a normalized identifier, so do not re-issue the same search on an empty result: if it reports indexing in progress, retry once after a short pause; otherwise fall back to generic search. diff --git a/resources/skills/java-lsp-tools/SKILL.md b/resources/skills/java-lsp-tools/SKILL.md new file mode 100644 index 00000000..4535b75d --- /dev/null +++ b/resources/skills/java-lsp-tools/SKILL.md @@ -0,0 +1,45 @@ +--- +name: java-lsp-tools +description: Compiler-accurate Java symbol navigation via the Java Language Server. Use lsp_java_findSymbol for Java identifiers and lsp_java_getFileStructure for known Java files; prefer them over generic search only for symbol/file-outline navigation. +--- + +# Java LSP Tools + +Two compiler-accurate tools backed by the Java Language Server (jdtls). They return structured JSON that is easier to interpret than generic search results for Java symbol navigation. + +## Tools + +### `lsp_java_findSymbol` +Search for Java symbol definitions (classes, methods, fields) by name across the workspace. Supports partial matching. +- Input: `{ query, limit? }` — limit defaults to 20, max 50 +- Output: `{ results: [{ name, kind, container?, file, startLine, endLine, readFileInput, range }], total }`; `readFileInput` is `{ filePath, offset, limit }` for `read_file`, and `file` can be passed to `lsp_java_getFileStructure` +- **Use instead of** `grep_search`, `file_search`, `semantic_search`, or `search_subagent` when looking for where a Java class/method/field is defined by identifier +- When source is needed for a returned symbol, use its `readFileInput` directly + +### `lsp_java_getFileStructure` +Get hierarchical outline of a Java file (classes, methods, fields) with line ranges. +- Input: `{ uri, limit? }` — workspace-relative path plus max outline items. Prefer `file` from `lsp_java_findSymbol`; limit defaults to 20, max 60. Must be a known path from prior tool results or user input — do not guess +- Output: `{ file, symbols: [{ name, kind, startLine, endLine, readFileRange, range, detail?, children? }], truncated? }`; call `read_file` with `filePath=file` and the selected symbol's `readFileRange` +- **Use before** `read_file` when you need to choose a precise line range in a known Java file + +## When to Use + +| Task | Use | Not | +|---|---|---| +| Find class/method/field definition | `lsp_java_findSymbol` | `grep_search` | +| See known Java file outline before reading | `lsp_java_getFileStructure` | `read_file` full file | +| Search non-Java files (xml, gradle) | `grep_search` | lsp tools | +| Search string literals or comments | `grep_search` | lsp tools | +| Explore broad concepts without identifiers | `semantic_search` or `search_subagent` | lsp tools | + +## Typical Workflow + +**lsp_java_findSymbol → lsp_java_getFileStructure → read_file (specific lines only)** + +If `lsp_java_findSymbol` returns relevant symbols and source is needed, call `read_file` with the returned `readFileInput`, or call `lsp_java_getFileStructure` with the returned `file` when broader file context is needed. + +## Fallback + +- `findSymbol` returns empty → it already retried internally with a normalized identifier, so do not re-issue the same search. If the result says indexing is in progress, retry once after a short pause; otherwise fall back to `grep_search` +- Path error (`fileNotFound`) → use `findSymbol` to discover the correct path first; do not guess paths +- Tool error / jdtls not ready → fall back to `grep_search` + `read_file`, don't retry more than once diff --git a/scripts/buildJdtlsExt.js b/scripts/buildJdtlsExt.js index c6623dbf..f3356211 100644 --- a/scripts/buildJdtlsExt.js +++ b/scripts/buildJdtlsExt.js @@ -7,7 +7,22 @@ const path = require('path'); const server_dir = path.resolve('jdtls.ext'); -cp.execSync(mvnw()+ ' clean package', {cwd:server_dir, stdio:[0,1,2]} ); +// Set JVM options to increase XML entity size limits +// JDK 24 contains changes to JAXP limits, see: https://bugs.openjdk.org/browse/JDK-8343022 +const jvmOptions = [ + '-Djdk.xml.maxGeneralEntitySizeLimit=0', + '-Djdk.xml.totalEntitySizeLimit=0' +].join(' '); + +// Set MAVEN_OPTS environment variable with JVM options +const env = { ...process.env }; +env.MAVEN_OPTS = env.MAVEN_OPTS ? env.MAVEN_OPTS + ' ' + jvmOptions : jvmOptions; + +// `eclipse.p2.mirrors=false` stops p2 from following download.eclipse.org's mirror +// redirect, which hands out a different third party host per request and makes the +// set of addresses the build contacts impossible to express as an allow list. +const mvnCommand = `${mvnw()} clean package -Declipse.p2.mirrors=false`; +cp.execSync(mvnCommand, {cwd:server_dir, stdio:[0,1,2], env: env} ); copy(path.join(server_dir, 'com.microsoft.jdtls.ext.core/target'), path.resolve('server'), (file) => { return /^com.microsoft.jdtls.ext.core.*.jar$/.test(file); }); diff --git a/scripts/prepare-nightly-build.js b/scripts/prepare-nightly-build.js index 7e40038b..a41983f3 100644 --- a/scripts/prepare-nightly-build.js +++ b/scripts/prepare-nightly-build.js @@ -2,12 +2,15 @@ const fs = require("fs"); const json = JSON.parse(fs.readFileSync("./package.json").toString()); const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/); +if (!stableVersion) { + throw new Error(`Invalid stable version: ${json.version}`); +} const major = stableVersion[1]; const minor = stableVersion[2]; function prependZero(number) { if (number > 99) { - throw "Unexpected value to prepend with zero"; + throw new Error("Unexpected value to prepend with zero"); } return `${number < 10 ? "0" : ""}${number}`; } @@ -16,10 +19,11 @@ 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 patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`; const insiderPackageJson = Object.assign(json, { version: `${major}.${minor}.${patch}`, + preview: true, }); -fs.writeFileSync("./package.insiders.json", JSON.stringify(insiderPackageJson)); \ No newline at end of file +fs.writeFileSync("./package.insiders.json", `${JSON.stringify(insiderPackageJson, null, 2)}\n`); \ No newline at end of file diff --git a/src/commands.ts b/src/commands.ts index a2564835..50ecc6a9 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -26,6 +26,8 @@ export namespace Commands { export const VIEW_PACKAGE_INTERNAL_REFRESH = "_java.view.package.internal.refresh"; + export const VIEW_PACKAGE_INTERNAL_ADD_PROJECTS = "_java.view.package.internal.addProjects"; + export const VIEW_PACKAGE_OUTLINE = "java.view.package.outline"; export const VIEW_PACKAGE_REVEAL_FILE_OS = "java.view.package.revealFileInOS"; @@ -42,6 +44,8 @@ export namespace Commands { export const VIEW_PACKAGE_NEW_JAVA_CLASS = "java.view.package.newJavaClass"; + export const VIEW_MODERNIZE_JAVA_PROJECT = "_java.view.modernizeJavaProject"; + export const VIEW_PACKAGE_NEW_JAVA_INTERFACE = "java.view.package.newJavaInterface"; export const VIEW_PACKAGE_NEW_JAVA_ENUM = "java.view.package.newJavaEnum"; @@ -94,6 +98,10 @@ export namespace Commands { export const JAVA_PROJECT_BUILD_WORKSPACE = "java.project.build.workspace"; + export const JAVA_PROJECT_REBUILD_WORKSPACE = "java.project.rebuild.workspace"; + + export const JAVA_PROJECT_BUILD_PROJECT = "java.project.build.project"; + export const JAVA_PROJECT_CLEAN_WORKSPACE = "java.project.clean.workspace"; export const JAVA_PROJECT_UPDATE = "java.project.update"; @@ -132,6 +140,14 @@ export namespace Commands { export const JAVA_PROJECT_CHECK_IMPORT_STATUS = "java.project.checkImportStatus"; + export const JAVA_PROJECT_GET_DEPENDENCIES = "java.project.getDependencies"; + + export const JAVA_PROJECT_GET_IMPORT_CLASS_CONTENT = "java.project.getImportClassContent"; + + export const JAVA_PROJECT_GET_FILE_IMPORTS = "java.project.getFileImports"; + + export const JAVA_UPGRADE_WITH_COPILOT = "_java.upgradeWithCopilot"; + /** * Commands from Visual Studio Code */ @@ -156,6 +172,11 @@ export namespace Commands { export const BUILD_PROJECT = "java.project.build"; + /** + * Commands from appmod (Java Upgrade Tool) + */ + export const GOTO_AGENT_MODE = "appmod.javaUpgrade.gotoAgentMode"; + /** * Get the project settings */ diff --git a/src/constants.ts b/src/constants.ts index df01101c..31150834 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -33,6 +33,18 @@ export namespace Explorer { export namespace ExtensionName { export const JAVA_LANGUAGE_SUPPORT: string = "redhat.java"; + export const APP_MODERNIZATION_FOR_JAVA = "vscjava.migrate-java-to-azure"; + // Java upgrade extension is merged into app modernization extension + export const APP_MODERNIZATION_UPGRADE_FOR_JAVA = APP_MODERNIZATION_FOR_JAVA; + export const APP_MODERNIZATION_EXTENSION_NAME = "GitHub Copilot modernization"; +} + +export namespace Upgrade { + export const PACKAGE_ID_FOR_JAVA_RUNTIME = "java:*"; + /** Minimum version of the appmod extension that supports gotoAgentMode command */ + export const MIN_APPMOD_VERSION = "1.15.0"; + export const SOURCE_JAVA_UPGRADE = "vscode-java-dependency.java-upgrade"; + export const SOURCE_CVE = "vscode-java-dependency.cve"; } /** diff --git a/src/controllers/projectController.ts b/src/controllers/projectController.ts index 3f9cbaf5..b630e339 100644 --- a/src/controllers/projectController.ts +++ b/src/controllers/projectController.ts @@ -109,7 +109,7 @@ enum ProjectType { MicroProfile = "MicroProfile", JavaFX = "JavaFX", Micronaut = "Micronaut", - GCN = "GCN", + GDK = "GDK", } async function ensureExtension(typeName: string, metaData: IProjectTypeMetadata): Promise { @@ -275,12 +275,12 @@ const projectTypes: IProjectType[] = [ }, }, { - displayName: "Graal Cloud Native", + displayName: "Graal Development Kit for Micronaut", metadata: { - type: ProjectType.GCN, + type: ProjectType.GDK, extensionId: "oracle-labs-graalvm.gcn", - extensionName: "Graal Cloud Native Launcher", - createCommandId: "gcn.createGcnProject", + extensionName: "Graal Development Kit for Micronaut Launcher", + createCommandId: "gdk.createGdkProject", }, }, ]; diff --git a/src/copilot/contextProvider.ts b/src/copilot/contextProvider.ts new file mode 100644 index 00000000..6640ee13 --- /dev/null +++ b/src/copilot/contextProvider.ts @@ -0,0 +1,179 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { + ResolveRequest, + SupportedContextItem, + type ContextProvider, +} from '@github/copilot-language-server'; +import * as vscode from 'vscode'; +import { CopilotHelper } from './copilotHelper'; +import { sendError, sendInfo } from "vscode-extension-telemetry-wrapper"; +import { + JavaContextProviderUtils, + CancellationError, + InternalCancellationError, + CopilotCancellationError, + ContextResolverFunction, + CopilotApi, + ContextProviderRegistrationError, + ContextProviderResolverError, + sendContextResolutionTelemetry +} from './utils'; + +export async function registerCopilotContextProviders( + context: vscode.ExtensionContext +) { + try { + const apis = await JavaContextProviderUtils.getCopilotApis(); + if (!apis.clientApi || !apis.chatApi) { + return; + } + // Register the Java completion context provider + const provider: ContextProvider = { + id: 'vscjava.vscode-java-dependency', // use extension id as provider id for now + selector: [{ language: "java" }], + resolver: { resolve: createJavaContextResolver() } + }; + const installCount = await JavaContextProviderUtils.installContextProviderOnApis(apis, provider, context, installContextProvider); + if (installCount === 0) { + return; + } + sendInfo("", { + "action": "registerCopilotContextProvider", + "status": "succeeded", + "installCount": installCount + }); + } + catch (error) { + const errorMessage = (error as Error).message || "unknown_error"; + sendError(new ContextProviderRegistrationError( + 'Failed to register Copilot context provider: ' + errorMessage + )); + } +} + +/** + * Create the Java context resolver function + */ +function createJavaContextResolver(): ContextResolverFunction { + return async (request: ResolveRequest, copilotCancel: vscode.CancellationToken): Promise => { + try { + // Check for immediate cancellation + JavaContextProviderUtils.checkCancellation(copilotCancel); + return await resolveJavaContext(request, copilotCancel); + } catch (error: any) { + sendError(new ContextProviderResolverError('Java Context Resolution Failed: ' + ((error as Error).message || "unknown_error"))); + // This should never be reached due to handleError throwing, but TypeScript requires it + return []; + } + }; +} + +async function resolveJavaContext(request: ResolveRequest, copilotCancel: vscode.CancellationToken): Promise { + const items: SupportedContextItem[] = []; + const start = performance.now(); + + let dependenciesResult: CopilotHelper.IResolveResult | undefined; + let importsResult: CopilotHelper.IResolveResult | undefined; + + try { + // Check for cancellation before starting + JavaContextProviderUtils.checkCancellation(copilotCancel); + + // Resolve project dependencies and convert to context items + dependenciesResult = await CopilotHelper.resolveAndConvertProjectDependencies( + vscode.window.activeTextEditor, + copilotCancel, + JavaContextProviderUtils.checkCancellation + ); + JavaContextProviderUtils.checkCancellation(copilotCancel); + items.push(...dependenciesResult.items); + + JavaContextProviderUtils.checkCancellation(copilotCancel); + + // Resolve local imports and convert to context items + importsResult = await CopilotHelper.resolveAndConvertLocalImports( + vscode.window.activeTextEditor, + copilotCancel, + JavaContextProviderUtils.checkCancellation + ); + JavaContextProviderUtils.checkCancellation(copilotCancel); + items.push(...importsResult.items); + } catch (error: any) { + if (error instanceof CopilotCancellationError) { + sendContextResolutionTelemetry( + request, + start, + items, + "cancelled_by_copilot", + undefined, + dependenciesResult?.emptyReason, + importsResult?.emptyReason, + dependenciesResult?.itemCount, + importsResult?.itemCount + ); + throw error; + } + if (error instanceof vscode.CancellationError || error.message === CancellationError.CANCELED) { + sendContextResolutionTelemetry( + request, + start, + items, + "cancelled_internally", + undefined, + dependenciesResult?.emptyReason, + importsResult?.emptyReason, + dependenciesResult?.itemCount, + importsResult?.itemCount + ); + throw new InternalCancellationError(); + } + + // Send telemetry for general errors (but continue with partial results) + sendContextResolutionTelemetry( + request, + start, + items, + "error_partial_results", + error.message || "unknown_error", + dependenciesResult?.emptyReason, + importsResult?.emptyReason, + dependenciesResult?.itemCount, + importsResult?.itemCount + ); + + // Return partial results and log completion for error case + return items; + } + + // Send telemetry data once at the end for success case + sendContextResolutionTelemetry( + request, + start, + items, + "succeeded", + undefined, + dependenciesResult?.emptyReason, + importsResult?.emptyReason, + dependenciesResult?.itemCount, + importsResult?.itemCount + ); + + return items; +} + +export async function installContextProvider( + copilotAPI: CopilotApi, + contextProvider: ContextProvider +): Promise { + const hasGetContextProviderAPI = typeof copilotAPI.getContextProviderAPI === 'function'; + if (hasGetContextProviderAPI) { + const contextAPI = await copilotAPI.getContextProviderAPI('v1'); + if (contextAPI) { + return contextAPI.registerContextProvider(contextProvider); + } + } + return undefined; +} diff --git a/src/copilot/copilotHelper.ts b/src/copilot/copilotHelper.ts new file mode 100644 index 00000000..67bf3196 --- /dev/null +++ b/src/copilot/copilotHelper.ts @@ -0,0 +1,326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { commands, Uri, CancellationToken } from "vscode"; +import { JavaContextProviderUtils } from "./utils"; +import { Commands } from '../commands'; + +/** + * Enum for error messages used in Promise rejection + */ +export enum ErrorMessage { + OperationCancelled = "Operation cancelled", + OperationTimedOut = "Operation timed out" +} + +/** + * Enum for empty reason codes when operations return empty results + */ +export enum EmptyReason { + CopilotCancelled = "CopilotCancelled", + CommandNullResult = "CommandNullResult", + Timeout = "Timeout", + NoWorkspace = "NoWorkspace", + NoDependenciesResults = "NoDependenciesResults", + NoActiveEditor = "NoActiveEditor", + NotJavaFile = "NotJavaFile", + NoImportsResults = "NoImportsResults" +} + +export interface INodeImportClass { + uri: string; + value: string; +} + +export interface IImportClassContentResult { + classInfoList: INodeImportClass[]; + emptyReason?: string; + isEmpty: boolean; +} + +export interface IProjectDependency { + [key: string]: string; +} + +export interface IProjectDependenciesResult { + dependencyInfoList: { key: string; value: string }[]; + emptyReason?: string; + isEmpty: boolean; +} +/** + * Helper class for Copilot integration to analyze Java project dependencies + */ +export namespace CopilotHelper { + /** + * Resolves all local project types imported by the given file with detailed error reporting + * @param fileUri The URI of the Java file to analyze + * @param cancellationToken Optional cancellation token to abort the operation + * @returns Result object containing import class information and error details + */ + export async function resolveLocalImportsWithReason(fileUri: Uri, cancellationToken?: CancellationToken): Promise { + if (cancellationToken?.isCancellationRequested) { + return { + classInfoList: [], + emptyReason: EmptyReason.CopilotCancelled, + isEmpty: true + }; + } + + try { + const normalizedUri = decodeURIComponent(Uri.file(fileUri.fsPath).toString()); + const commandPromise = commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_PROJECT_GET_IMPORT_CLASS_CONTENT, + normalizedUri + ) as Promise; + + // Build promises array for race condition + // Note: Client-side timeout is NECESSARY even if backend has timeout because: + // 1. Network delays may prevent backend response from arriving + // 2. Process hangs won't trigger backend timeout + // 3. Command dispatch failures need to be caught + const promises: Promise[] = [ + commandPromise, + new Promise((_, reject) => { + setTimeout(() => { + reject(new Error(ErrorMessage.OperationTimedOut)); + }, 80); // 80ms client-side timeout (independent of backend timeout) + }) + ]; + + // Add cancellation promise if token provided + if (cancellationToken) { + promises.push( + new Promise((_, reject) => { + cancellationToken.onCancellationRequested(() => { + reject(new Error(ErrorMessage.OperationCancelled)); + }); + }) + ); + } + + const result = await Promise.race(promises); + if (!result) { + return { + classInfoList: [], + emptyReason: EmptyReason.CommandNullResult, + isEmpty: true + }; + } + return result; + } catch (error: any) { + if (error.message === ErrorMessage.OperationCancelled) { + return { + classInfoList: [], + emptyReason: EmptyReason.CopilotCancelled, + isEmpty: true + }; + } + if (error.message === ErrorMessage.OperationTimedOut) { + return { + classInfoList: [], + emptyReason: EmptyReason.Timeout, + isEmpty: true + }; + } + const errorMessage = 'TsException_' + ((error as Error).message || "unknown"); + return { + classInfoList: [], + emptyReason: errorMessage, + isEmpty: true + }; + } + } + + /** + * Resolves project dependencies with detailed error reporting + * @param projectUri The URI of the Java project to analyze + * @param cancellationToken Optional cancellation token to abort the operation + * @returns Result object containing project dependencies and error information + */ + export async function resolveProjectDependenciesWithReason( + fileUri: Uri, + cancellationToken?: CancellationToken + ): Promise { + if (cancellationToken?.isCancellationRequested) { + return { + dependencyInfoList: [], + emptyReason: EmptyReason.CopilotCancelled, + isEmpty: true + }; + } + + try { + const normalizedUri = decodeURIComponent(Uri.file(fileUri.fsPath).toString()); + const commandPromise = commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_PROJECT_GET_DEPENDENCIES, + normalizedUri + ) as Promise; + + // Build promises array for race condition + // Note: Client-side timeout is NECESSARY even if backend has timeout because: + // 1. Network delays may prevent backend response from arriving + // 2. Process hangs won't trigger backend timeout + // 3. Command dispatch failures need to be caught + const promises: Promise[] = [ + commandPromise, + new Promise((_, reject) => { + setTimeout(() => { + reject(new Error(ErrorMessage.OperationTimedOut)); + }, 40); // 40ms client-side timeout (independent of backend timeout) + }) + ]; + + // Add cancellation promise if token provided + if (cancellationToken) { + promises.push( + new Promise((_, reject) => { + cancellationToken.onCancellationRequested(() => { + reject(new Error(ErrorMessage.OperationCancelled)); + }); + }) + ); + } + + const result = await Promise.race(promises); + if (!result) { + return { + dependencyInfoList: [], + emptyReason: EmptyReason.CommandNullResult, + isEmpty: true + }; + } + return result; + } catch (error: any) { + if (error.message === ErrorMessage.OperationCancelled) { + return { + dependencyInfoList: [], + emptyReason: EmptyReason.CopilotCancelled, + isEmpty: true + }; + } + if (error.message === ErrorMessage.OperationTimedOut) { + return { + dependencyInfoList: [], + emptyReason: EmptyReason.Timeout, + isEmpty: true + }; + } + const errorMessage = 'TsException_' + ((error as Error).message || "unknown"); + return { + dependencyInfoList: [], + emptyReason: errorMessage, + isEmpty: true + }; + } + } + + /** + * Result interface for dependency resolution with diagnostic information + */ + export interface IResolveResult { + items: any[]; + emptyReason?: string; + itemCount: number; + } + + /** + * Resolves project dependencies and converts them to context items with cancellation support + * @param activeEditor The active text editor, or undefined if none + * @param copilotCancel Cancellation token from Copilot + * @param checkCancellation Function to check for cancellation + * @returns Result object containing context items and diagnostic information + */ + export async function resolveAndConvertProjectDependencies( + activeEditor: { document: { uri: Uri; languageId: string } } | undefined, + copilotCancel: CancellationToken, + checkCancellation: (token: CancellationToken) => void + ): Promise { + const items: any[] = []; + + // Check if active editor exists + if (!activeEditor) { + return { items: [], emptyReason: EmptyReason.NoActiveEditor, itemCount: 0 }; + } + if (activeEditor.document.languageId !== 'java') { + return { items: [], emptyReason: EmptyReason.NotJavaFile, itemCount: 0 }; + } + const documentUri = activeEditor.document.uri; + + // Resolve project dependencies + const projectDependenciesResult = await resolveProjectDependenciesWithReason(documentUri, copilotCancel); + + // Check for cancellation after dependency resolution + checkCancellation(copilotCancel); + + // Return empty result with reason if no dependencies found + if (projectDependenciesResult.isEmpty && projectDependenciesResult.emptyReason) { + return { items: [], emptyReason: projectDependenciesResult.emptyReason, itemCount: 0 }; + } + + // Check for cancellation after dependency resolution + checkCancellation(copilotCancel); + + // Convert project dependencies to context items + if (projectDependenciesResult.dependencyInfoList && projectDependenciesResult.dependencyInfoList.length > 0) { + const contextItems = JavaContextProviderUtils.createContextItemsFromProjectDependencies(projectDependenciesResult.dependencyInfoList); + + // Check cancellation once after creating all items + checkCancellation(copilotCancel); + items.push(...contextItems); + } + + return { items, itemCount: items.length }; + } + + /** + * Resolves local imports and converts them to context items with cancellation support + * @param activeEditor The active text editor, or undefined if none + * @param copilotCancel Cancellation token from Copilot + * @param checkCancellation Function to check for cancellation + * @returns Result object containing context items and diagnostic information + */ + export async function resolveAndConvertLocalImports( + activeEditor: { document: { uri: Uri; languageId: string } } | undefined, + copilotCancel: CancellationToken, + checkCancellation: (token: CancellationToken) => void + ): Promise { + const items: any[] = []; + + // Check if there's an active editor with a Java document + if (!activeEditor) { + return { items: [], emptyReason: EmptyReason.NoActiveEditor, itemCount: 0 }; + } + if (activeEditor.document.languageId !== 'java') { + return { items: [], emptyReason: EmptyReason.NotJavaFile, itemCount: 0 }; + } + + const documentUri = activeEditor.document.uri; + + // Check for cancellation before resolving imports + checkCancellation(copilotCancel); + // Resolve imports directly without caching + const importClassResult = await resolveLocalImportsWithReason(documentUri, copilotCancel); + + // Check for cancellation after resolution + checkCancellation(copilotCancel); + + // Return empty result with reason if no imports found + if (importClassResult.isEmpty && importClassResult.emptyReason) { + return { items: [], emptyReason: importClassResult.emptyReason, itemCount: 0 }; + } + + // Check for cancellation before processing results + checkCancellation(copilotCancel); + if (importClassResult.classInfoList && importClassResult.classInfoList.length > 0) { + // Process imports in batches to reduce cancellation check overhead + const contextItems = JavaContextProviderUtils.createContextItemsFromImports(importClassResult.classInfoList); + // Check cancellation once after creating all items + checkCancellation(copilotCancel); + items.push(...contextItems); + } + + return { items, itemCount: items.length }; + } +} diff --git a/src/copilot/tools/javaContextTools.ts b/src/copilot/tools/javaContextTools.ts new file mode 100644 index 00000000..22179a3b --- /dev/null +++ b/src/copilot/tools/javaContextTools.ts @@ -0,0 +1,603 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Java Context Tools — First Batch (Zero-Blocking) + * + * These 6 tools are all non-blocking after jdtls is ready: + * 1. lsp_java_getFileStructure — LSP documentSymbol + * 2. lsp_java_findSymbol — LSP workspaceSymbol + * 3. lsp_java_getFileImports — jdtls AST-only command (no type resolution) + * 4. lsp_java_getTypeAtPosition — LSP hover (post-processed) + * 5. lsp_java_getCallHierarchy — LSP call hierarchy + * 6. lsp_java_getTypeHierarchy — LSP type hierarchy + * + * Design principles: + * - Each tool returns < 200 tokens + * - Structured JSON output + * - No classpath resolution, no dependency download + */ + +import * as path from "path"; +import * as vscode from "vscode"; +import { Commands } from "../../commands"; +import { languageServerApiManager } from "../../languageServerApi/languageServerApiManager"; +import { sendInfo } from "vscode-extension-telemetry-wrapper"; + +// Hard caps to keep tool responses within the < 200 token budget. +const MAX_SYMBOL_DEPTH = 3; +const MAX_FILE_STRUCTURE_SYMBOL_NODES = 60; +const DEFAULT_FILE_STRUCTURE_SYMBOL_NODES = 20; +const MAX_CALL_RESULTS = 50; +const MAX_TYPE_RESULTS = 50; +const MAX_IMPORTS = 50; + +function toResult(data: unknown): vscode.LanguageModelToolResult { + const text = typeof data === "string" ? data : JSON.stringify(data, null, 2); + return new vscode.LanguageModelToolResult([ + new vscode.LanguageModelTextPart(text), + ]); +} + +function getResponseCharCount(data: unknown): number { + return typeof data === "string" ? data.length : JSON.stringify(data, null, 2).length; +} + +interface ReadFileInput { + filePath: string; + offset: number; + limit: number; +} + +interface ReadFileRange { + offset: number; + limit: number; +} + +function toInclusiveLineRange(range: vscode.Range): { startLine: number; endLine: number } { + const startLine = range.start.line + 1; + const endLine = Math.max(startLine, range.end.character === 0 && range.end.line > range.start.line + ? range.end.line + : range.end.line + 1); + return { startLine, endLine }; +} + +function toReadFileRange(startLine: number, endLine: number): ReadFileRange { + return { + offset: startLine, + limit: endLine - startLine + 1, + }; +} + +function toReadFileInput(filePath: string, startLine: number, endLine: number): ReadFileInput { + return { + filePath, + ...toReadFileRange(startLine, endLine), + }; +} + +/** + * Normalize a workspace-symbol query for a single fallback retry. + * Strips a fully-qualified package prefix (com.foo.Bar -> Bar), generic parameters + * (List -> List), and method parameter lists (foo() -> foo). jdtls already + * performs camel-hump matching, so the contiguous identifier is preserved. + */ +function normalizeSymbolQuery(query: string): string { + if (!query) { + return ""; + } + let q = query.trim(); + // Drop generic parameters and method parens: List / foo(args) -> List / foo + q = q.replace(/[<(].*$/, ""); + // Drop a fully-qualified package/qualifier prefix: com.foo.Bar / Foo#bar -> Bar / bar + const lastSep = Math.max(q.lastIndexOf("."), q.lastIndexOf("#")); + if (lastSep >= 0 && lastSep < q.length - 1) { + q = q.substring(lastSep + 1); + } + return q.trim(); +} + +function getToolErrorCode(error: unknown): string { + const message = error instanceof Error ? error.message : String(error); + if (message.includes("No workspace folder")) { + return "noWorkspaceFolder"; + } + if (message.includes("Unsupported URI scheme")) { + return "unsupportedUriScheme"; + } + if (message.includes("outside the current workspace")) { + return "outsideWorkspace"; + } + return "unexpectedError"; +} + +/** + * Resolve a file path to a vscode.Uri. + * Accepts: + * - Full file URI: "file:///home/user/project/src/Main.java" + * - Relative path: "src/main/java/Main.java" + * - Absolute path: "/home/user/project/src/Main.java" or "C:\\Users\\...\\Main.java" + * + * Relative paths are resolved against the first workspace folder unless they + * start with a workspace folder name in a multi-root workspace. + * The resolved URI must use the file: scheme and fall under a workspace folder. + */ +function resolveFileUri(input: string): vscode.Uri { + const folders = vscode.workspace.workspaceFolders; + if (!folders || folders.length === 0) { + throw new Error("No workspace folder is open."); + } + + let uri: vscode.Uri; + const normalizedInput = input.trim(); + + if (normalizedInput.includes("://")) { + // URI string (e.g. "file:///home/user/project/src/Main.java") + uri = vscode.Uri.parse(normalizedInput); + if (uri.scheme !== "file") { + throw new Error(`Unsupported URI scheme "${uri.scheme}". Only file: URIs are allowed.`); + } + } else if (path.isAbsolute(normalizedInput)) { + // Absolute filesystem path (Unix or Windows) + uri = vscode.Uri.file(normalizedInput); + } else { + // Relative path — resolve against a matching workspace folder when + // asRelativePath included the folder name, otherwise use the first root. + const normalizedRelativePath = normalizedInput.replace(/\\/g, "/"); + const matchingFolder = folders.find(folder => + normalizedRelativePath === folder.name || normalizedRelativePath.startsWith(`${folder.name}/`)); + if (matchingFolder) { + const pathInFolder = normalizedRelativePath === matchingFolder.name + ? "" + : normalizedRelativePath.substring(matchingFolder.name.length + 1); + uri = vscode.Uri.joinPath(matchingFolder.uri, pathInFolder); + } else { + uri = vscode.Uri.joinPath(folders[0].uri, normalizedRelativePath); + } + } + + // Ensure the resolved path is under a workspace folder + const resolvedPath = uri.fsPath.toLowerCase(); + const isUnderWorkspace = folders.some(folder => { + const folderPath = folder.uri.fsPath.toLowerCase(); + return resolvedPath === folderPath || resolvedPath.startsWith(folderPath + (process.platform === "win32" ? "\\" : "/")); + }); + if (!isUnderWorkspace) { + throw new Error("The resolved path is outside the current workspace."); + } + + return uri; +} + +// ============================================================ +// Tool 1: lsp_java_getFileStructure (LSP — Document Symbol) +// ============================================================ + +interface FileStructureInput { + uri: string; + limit?: number; +} + +const fileStructureTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + const startTime = Date.now(); + const limit = Math.min(Math.max(Math.floor(options.input.limit ?? DEFAULT_FILE_STRUCTURE_SYMBOL_NODES), 1), MAX_FILE_STRUCTURE_SYMBOL_NODES); + let resultCount = 0; + let status = "success"; + let errorCode = ""; + let emptyReason = ""; + let responseCharCount = 0; + let truncated = false; + try { + const uri = resolveFileUri(options.input.uri); + try { + await vscode.workspace.fs.stat(uri); + } catch { + status = "error"; + errorCode = "fileNotFound"; + // Most fileNotFound errors come from the model guessing a path. Return an + // actionable hint instead of a dead end so it can self-correct via findSymbol. + const fileNotFoundPayload = { + error: "File not found.", + hint: "Call lsp_java_findSymbol to obtain the exact workspace path before retrying. Do not guess file paths.", + }; + responseCharCount = getResponseCharCount(fileNotFoundPayload); + return toResult(fileNotFoundPayload); + } + const symbols = await vscode.commands.executeCommand( + "vscode.executeDocumentSymbolProvider", uri, + ); + if (!symbols || symbols.length === 0) { + status = "empty"; + // Separate "index not ready yet" from a genuine no-symbol result so the model + // (and telemetry) can tell a transient state apart from an unrecognized file. + const indexing = !languageServerApiManager.isFullyReady(); + emptyReason = indexing ? "indexingInProgress" : "documentSymbolProviderEmpty"; + const noSymbolsPayload = indexing + ? { error: "Java language server is still indexing. Retry shortly." } + : { error: "No symbols found. The file may not be recognized by the Java language server." }; + responseCharCount = getResponseCharCount(noSymbolsPayload); + return toResult(noSymbolsPayload); + } + const counter = { count: 0, truncated: false }; + const result = symbolsToJson(symbols, 0, counter, limit); + resultCount = counter.count; + truncated = counter.truncated; + const file = vscode.workspace.asRelativePath(uri); + const fileStructurePayload = { file, symbols: result, ...(truncated && { truncated: true }) }; + responseCharCount = getResponseCharCount(fileStructurePayload); + return toResult(fileStructurePayload); + } catch (e) { + status = "error"; + errorCode = errorCode || getToolErrorCode(e); + throw e; + } finally { + sendInfo("", { + operationName: "lmTool.getFileStructure", + status, + ...(errorCode && { errorCode }), + ...(emptyReason && { emptyReason }), + truncated: truncated ? "true" : "false", + limit, + resultCount, + responseCharCount, + durationMs: Date.now() - startTime, + }); + } + }, +}; + +interface SymbolNode { + name: string; + kind: string; + startLine: number; + endLine: number; + readFileRange: ReadFileRange; + range: string; + detail?: string; + children?: SymbolNode[]; +} + +function symbolsToJson(symbols: vscode.DocumentSymbol[], depth: number, counter: { count: number; truncated: boolean }, limit: number): SymbolNode[] { + const result: SymbolNode[] = []; + for (const s of symbols) { + if (counter.count >= limit) { + counter.truncated = true; + break; + } + counter.count++; + const { startLine, endLine } = toInclusiveLineRange(s.range); + const node: SymbolNode = { + name: s.name, + kind: vscode.SymbolKind[s.kind], + startLine, + endLine, + readFileRange: toReadFileRange(startLine, endLine), + range: `L${startLine}-${endLine}`, + }; + if (s.detail) { + node.detail = s.detail; + } + if (s.children?.length && depth < MAX_SYMBOL_DEPTH) { + node.children = symbolsToJson(s.children, depth + 1, counter, limit); + } + result.push(node); + } + return result; +} + +// ============================================================ +// Tool 2: lsp_java_findSymbol (LSP — Workspace Symbol) +// ============================================================ + +interface FindSymbolInput { + query: string; + limit?: number; +} + +const findSymbolTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + const startTime = Date.now(); + let resultCount = 0; + let totalResults = 0; + const limit = Math.min(Math.max(options.input.limit || 20, 1), 50); + let status = "success"; + let errorCode = ""; + let emptyReason = ""; + let responseCharCount = 0; + let retried = false; + try { + const rawQuery = (options.input.query ?? "").trim(); + // Reject blank/whitespace-only queries early: an empty query triggers an + // expensive workspace-wide symbol scan and can return a huge list. + if (!rawQuery) { + status = "error"; + errorCode = "emptyQuery"; + const emptyQueryPayload = { + error: "Query is empty. Provide a class, interface, method, or field name to search for.", + }; + responseCharCount = getResponseCharCount(emptyQueryPayload); + return toResult(emptyQueryPayload); + } + let symbols = await vscode.commands.executeCommand( + "vscode.executeWorkspaceSymbolProvider", rawQuery, + ); + // Server-side fallback: if the verbatim query misses, retry once with a + // normalized identifier (strip package qualifier, generics, and parameter + // lists) so the model does not have to chain repeated findSymbol calls itself. + if (!symbols || symbols.length === 0) { + const normalized = normalizeSymbolQuery(rawQuery); + if (normalized && normalized !== rawQuery) { + retried = true; + symbols = await vscode.commands.executeCommand( + "vscode.executeWorkspaceSymbolProvider", normalized, + ); + } + } + if (!symbols || symbols.length === 0) { + status = "empty"; + // Distinguish a transient "index not ready" state from a real no-match so the + // model can retry later instead of concluding the symbol does not exist. + const indexing = !languageServerApiManager.isFullyReady(); + emptyReason = indexing ? "indexingInProgress" : "workspaceSymbolNoMatch"; + const noMatchesPayload = indexing + ? { results: [], message: "Java language server is still indexing. Retry shortly or use grep_search as a fallback." } + : { results: [], message: "No symbols found." }; + responseCharCount = getResponseCharCount(noMatchesPayload); + return toResult(noMatchesPayload); + } + totalResults = symbols.length; + const results = symbols.slice(0, limit).map(s => { + const file = vscode.workspace.asRelativePath(s.location.uri); + const { startLine, endLine } = toInclusiveLineRange(s.location.range); + return { + name: s.name, + kind: vscode.SymbolKind[s.kind], + container: s.containerName || undefined, + file, + startLine, + endLine, + readFileInput: toReadFileInput(file, startLine, endLine), + range: `L${startLine}-${endLine}`, + }; + }); + resultCount = results.length; + const findSymbolPayload = { results, total: symbols.length }; + responseCharCount = getResponseCharCount(findSymbolPayload); + return toResult(findSymbolPayload); + } catch (e) { + status = "error"; + errorCode = getToolErrorCode(e); + throw e; + } finally { + sendInfo("", { + operationName: "lmTool.findSymbol", + status, + ...(errorCode && { errorCode }), + ...(emptyReason && { emptyReason }), + retried: retried ? "true" : "false", + limit, + resultCount, + totalResults, + responseCharCount, + durationMs: Date.now() - startTime, + }); + } + }, +}; + +// ============================================================ +// Tool 3: lsp_java_getFileImports (jdtls — AST-only, non-blocking) +// ============================================================ + +interface FileImportsInput { + uri: string; +} + +export const _fileImportsTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + sendInfo("", { operationName: "lmTool.getFileImports" }); + const uri = resolveFileUri(options.input.uri); + const result = await vscode.commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_PROJECT_GET_FILE_IMPORTS, + uri.toString(), + ); + if (!result) { + return toResult({ error: "No result from Java language server. It may still be loading." }); + } + if (Array.isArray(result) && result.length > MAX_IMPORTS) { + return toResult({ imports: result.slice(0, MAX_IMPORTS), total: result.length, truncated: true }); + } + return toResult(result); + }, +}; + +// ============================================================ +// Tool 4: lsp_java_getTypeAtPosition (LSP — Hover post-processed) +// ============================================================ + +interface TypeAtPositionInput { + uri: string; + line: number; + character: number; +} + +export const _typeAtPositionTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + sendInfo("", { operationName: "lmTool.getTypeAtPosition" }); + const uri = resolveFileUri(options.input.uri); + const position = new vscode.Position(options.input.line, options.input.character); + const hovers = await vscode.commands.executeCommand( + "vscode.executeHoverProvider", uri, position, + ); + return toResult(extractTypeSignature(hovers)); + }, +}; + +/** + * Extract type signature from jdtls hover result. + * jdtls returns Markdown with ```java code blocks containing the type info. + * We extract just the signature, stripping Javadoc to minimize tokens. + */ +function extractTypeSignature(hovers: vscode.Hover[] | undefined): object { + if (!hovers?.length) { + return { error: "No type information at this position" }; + } + for (const hover of hovers) { + for (const content of hover.contents) { + if (content instanceof vscode.MarkdownString) { + const match = content.value.match(/```java\n([\s\S]*?)```/); + if (match) { + const lines = match[1].trim().split("\n").filter(l => { + const trimmed = l.trim(); + if (trimmed.length === 0) { + return false; + } + // Strip Javadoc and block comment lines + if (trimmed.startsWith("/**") || trimmed.startsWith("*/") || trimmed.startsWith("* ") || trimmed === "*") { + return false; + } + // Strip single-line comments + if (trimmed.startsWith("//")) { + return false; + } + return true; + }); + return { type: lines.join("\n") }; + } + } + } + } + return { error: "Could not extract type from hover result" }; +} + +// ============================================================ +// Tool 5: lsp_java_getCallHierarchy (LSP — Call Hierarchy) +// ============================================================ + +interface CallHierarchyInput { + uri: string; + line: number; + character: number; + direction: "incoming" | "outgoing"; +} + +export const _callHierarchyTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + sendInfo("", { operationName: "lmTool.getCallHierarchy" }); + const uri = resolveFileUri(options.input.uri); + const position = new vscode.Position(options.input.line, options.input.character); + + // Step 1: Prepare call hierarchy item at the given position + const items = await vscode.commands.executeCommand( + "vscode.prepareCallHierarchy", uri, position, + ); + if (!items?.length) { + return toResult({ error: "No callable symbol at this position" }); + } + + // Step 2: Get incoming or outgoing calls + const isIncoming = options.input.direction === "incoming"; + const command = isIncoming ? "vscode.provideIncomingCalls" : "vscode.provideOutgoingCalls"; + const calls = await vscode.commands.executeCommand(command, items[0]); + + if (!calls || calls.length === 0) { + return toResult({ + symbol: items[0].name, + direction: options.input.direction, + calls: [], + message: `No ${options.input.direction} calls found for '${items[0].name}'`, + }); + } + + const truncated = calls.length > MAX_CALL_RESULTS; + const capped = truncated ? calls.slice(0, MAX_CALL_RESULTS) : calls; + const results = capped.map((call: any) => { + const item = isIncoming ? call.from : call.to; + return { + name: item.name, + detail: item.detail || undefined, + location: `${vscode.workspace.asRelativePath(item.uri)}:${item.range.start.line + 1}`, + }; + }); + + return toResult({ + symbol: items[0].name, + direction: options.input.direction, + calls: results, + ...(truncated && { total: calls.length, truncated: true }), + }); + }, +}; + +// ============================================================ +// Tool 6: lsp_java_getTypeHierarchy (LSP — Type Hierarchy) +// ============================================================ + +interface TypeHierarchyInput { + uri: string; + line: number; + character: number; + direction: "supertypes" | "subtypes"; +} + +export const _typeHierarchyTool: vscode.LanguageModelTool = { + async invoke(options, _token) { + sendInfo("", { operationName: "lmTool.getTypeHierarchy" }); + const uri = resolveFileUri(options.input.uri); + const position = new vscode.Position(options.input.line, options.input.character); + + // Step 1: Prepare type hierarchy item at the given position + const items = await vscode.commands.executeCommand( + "vscode.prepareTypeHierarchy", uri, position, + ); + if (!items?.length) { + return toResult({ error: "No type at this position" }); + } + + // Step 2: Get supertypes or subtypes + const isSuper = options.input.direction === "supertypes"; + const command = isSuper ? "vscode.provideSupertypes" : "vscode.provideSubtypes"; + const types = await vscode.commands.executeCommand(command, items[0]); + + if (!types || types.length === 0) { + return toResult({ + symbol: items[0].name, + direction: options.input.direction, + types: [], + message: `No ${options.input.direction} found for '${items[0].name}'`, + }); + } + + const truncated = types.length > MAX_TYPE_RESULTS; + const capped = truncated ? types.slice(0, MAX_TYPE_RESULTS) : types; + const results = capped.map(t => ({ + name: t.name, + kind: vscode.SymbolKind[t.kind], + detail: t.detail || undefined, + location: `${vscode.workspace.asRelativePath(t.uri)}:${t.range.start.line + 1}`, + })); + + return toResult({ + symbol: items[0].name, + direction: options.input.direction, + types: results, + ...(truncated && { total: types.length, truncated: true }), + }); + }, +}; + +// ============================================================ +// Registration +// ============================================================ + +export function registerJavaContextTools(context: vscode.ExtensionContext): void { + sendInfo("", { operationName: "lmTool.register" }); + context.subscriptions.push( + vscode.lm.registerTool("lsp_java_getFileStructure", fileStructureTool), + vscode.lm.registerTool("lsp_java_findSymbol", findSymbolTool), + ); +} diff --git a/src/copilot/utils.ts b/src/copilot/utils.ts new file mode 100644 index 00000000..4a2b424a --- /dev/null +++ b/src/copilot/utils.ts @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. +import * as vscode from 'vscode'; +import { + ContextProviderApiV1, + ResolveRequest, + SupportedContextItem, + type ContextProvider, +} from '@github/copilot-language-server'; +import { sendInfo } from "vscode-extension-telemetry-wrapper"; +/** + * Error classes for Copilot context provider cancellation handling + */ +export class CancellationError extends Error { + static readonly CANCELED = "Canceled"; + constructor() { + super(CancellationError.CANCELED); + this.name = this.message; + } +} + +export class InternalCancellationError extends CancellationError { +} + +export class CopilotCancellationError extends CancellationError { +} + +/** + * Type definitions for common patterns + */ +export type ContextResolverFunction = (request: ResolveRequest, token: vscode.CancellationToken) => Promise; + +export interface CopilotApiWrapper { + clientApi?: CopilotApi; + chatApi?: CopilotApi; +} + +export interface CopilotApi { + getContextProviderAPI(version: string): Promise; +} + +/** + * Utility class for handling common operations in Java Context Provider + */ +export class JavaContextProviderUtils { + /** + * Check if operation should be cancelled and throw appropriate error + */ + static checkCancellation(token: vscode.CancellationToken): void { + if (token.isCancellationRequested) { + throw new CopilotCancellationError(); + } + } + + static createContextItemsFromProjectDependencies(projectDepsResults: { key: string; value: string }[]): SupportedContextItem[] { + return projectDepsResults.map(dep => ({ + name: dep.key, + value: dep.value, + importance: 70 + })); + } + + /** + * Create context items from import classes + */ + static createContextItemsFromImports(importClasses: any[]): SupportedContextItem[] { + return importClasses.map((cls: any) => ({ + uri: cls.uri, + value: cls.value, + importance: 80, + origin: 'request' as const + })); + } + + /** + * Get and validate Copilot APIs + */ + static async getCopilotApis(): Promise { + const copilotClientApi = await getCopilotClientApi(); + const copilotChatApi = await getCopilotChatApi(); + return { clientApi: copilotClientApi, chatApi: copilotChatApi }; + } + + /** + * Install context provider on available APIs + */ + static async installContextProviderOnApis( + apis: CopilotApiWrapper, + provider: ContextProvider, + context: vscode.ExtensionContext, + installFn: (api: CopilotApi, provider: ContextProvider) => Promise + ): Promise { + let installCount = 0; + + if (apis.clientApi) { + const disposable = await installFn(apis.clientApi, provider); + if (disposable) { + context.subscriptions.push(disposable); + installCount++; + } + } + + if (apis.chatApi) { + const disposable = await installFn(apis.chatApi, provider); + if (disposable) { + context.subscriptions.push(disposable); + installCount++; + } + } + + return installCount; + } + + /** + * Calculate approximate token count for context items + * Using a simple heuristic: ~4 characters per token + * Optimized for performance by using reduce and direct property access + */ + static calculateTokenCount(items: SupportedContextItem[]): number { + // Fast path: if no items, return 0 + if (items.length === 0) { + return 0; + } + + // Use reduce for better performance + const totalChars = items.reduce((sum, item) => { + let itemChars = 0; + // Direct property access is faster than 'in' operator + const value = (item as any).value; + const name = (item as any).name; + + if (value && typeof value === 'string') { + itemChars += value.length; + } + if (name && typeof name === 'string') { + itemChars += name.length; + } + + return sum + itemChars; + }, 0); + + // Approximate: 1 token ≈ 4 characters + // Use bitwise shift for faster division by 4 + return Math.ceil(totalChars / 4); + } +} + +/** + * Get Copilot client API + */ +export async function getCopilotClientApi(): Promise { + const extension = vscode.extensions.getExtension('github.copilot'); + if (!extension) { + return undefined; + } + try { + return await extension.activate(); + } catch { + return undefined; + } +} + +/** + * Get Copilot chat API + */ +export async function getCopilotChatApi(): Promise { + type CopilotChatApi = { getAPI?(version: number): CopilotApi | undefined }; + const extension = vscode.extensions.getExtension('github.copilot-chat'); + if (!extension) { + return undefined; + } + + let exports: CopilotChatApi | undefined; + try { + exports = await extension.activate(); + } catch { + return undefined; + } + if (!exports || typeof exports.getAPI !== 'function') { + return undefined; + } + return exports.getAPI(1); +} + +export class ContextProviderRegistrationError extends Error { + constructor(message: string) { + super(message); + this.name = 'ContextProviderRegistrationError'; + } +} + +export class GetImportClassContentError extends Error { + constructor(message: string) { + super(message); + this.name = 'GetImportClassContentError'; + } +} + +export class GetProjectDependenciesError extends Error { + constructor(message: string) { + super(message); + this.name = 'GetProjectDependenciesError'; + } +} + +export class ContextProviderResolverError extends Error { + constructor(message: string) { + super(message); + this.name = 'ContextProviderResolverError'; + } +} + +/** + * Send consolidated telemetry data for Java context resolution + * This is the centralized function for sending context resolution telemetry + * + * @param request The resolve request from Copilot + * @param start Performance timestamp when resolution started + * @param items The resolved context items + * @param status Status of the resolution ("succeeded", "cancelled_by_copilot", "cancelled_internally", "error_partial_results") + * @param sendInfo The sendInfo function from vscode-extension-telemetry-wrapper + * @param error Optional error message + * @param dependenciesEmptyReason Optional reason why dependencies were empty + * @param importsEmptyReason Optional reason why imports were empty + * @param dependenciesCount Number of dependency items resolved + * @param importsCount Number of import items resolved + */ +export function sendContextResolutionTelemetry( + request: ResolveRequest, + start: number, + items: SupportedContextItem[], + status: string, + error?: string, + dependenciesEmptyReason?: string, + importsEmptyReason?: string, + dependenciesCount?: number, + importsCount?: number +): void { + const duration = Math.round(performance.now() - start); + const tokenCount = JavaContextProviderUtils.calculateTokenCount(items); + const telemetryData: any = { + "action": "resolveJavaContext", + "completionId": request.completionId, + "duration": duration, + "itemCount": items.length, + "tokenCount": tokenCount, + "status": status, + "dependenciesCount": dependenciesCount ?? 0, + "importsCount": importsCount ?? 0 + }; + + // Add empty reasons if present + if (dependenciesEmptyReason) { + telemetryData.dependenciesEmptyReason = dependenciesEmptyReason; + } + if (importsEmptyReason) { + telemetryData.importsEmptyReason = importsEmptyReason; + } + if (error) { + telemetryData.error = error; + } + + sendInfo("", telemetryData); +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 531b5ac3..4142bfc8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,8 +2,10 @@ // Licensed under the MIT license. import * as path from "path"; -import { commands, Diagnostic, Extension, ExtensionContext, extensions, languages, - Range, tasks, TextDocument, TextEditor, Uri, window, workspace } from "vscode"; +import { + commands, Diagnostic, Disposable, Extension, ExtensionContext, extensions, languages, + Range, tasks, TextDocument, TextEditor, Uri, window, workspace +} from "vscode"; import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation, instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper"; import { Commands, contextManager } from "../extension.bundle"; import { BuildTaskProvider } from "./tasks/build/buildTaskProvider"; @@ -20,9 +22,13 @@ import { DiagnosticProvider } from "./tasks/buildArtifact/migration/DiagnosticPr import { setContextForDeprecatedTasks, updateExportTaskType } from "./tasks/buildArtifact/migration/utils"; import { CodeActionProvider } from "./tasks/buildArtifact/migration/CodeActionProvider"; import { newJavaFile } from "./explorerCommands/new"; +import upgradeManager from "./upgrade/upgradeManager"; +import { registerJavaContextTools } from "./copilot/tools/javaContextTools"; +import { languageServerApiManager } from "./languageServerApi/languageServerApiManager"; export async function activate(context: ExtensionContext): Promise { contextManager.initialize(context); + upgradeManager.initialize(context); await initializeFromJsonFile(context.asAbsolutePath("./package.json")); await initExpService(context); await instrumentOperation("activation", activateExtension)(context); @@ -34,7 +40,63 @@ export async function activate(context: ExtensionContext): Promise { contextManager.setContextValue(Context.WORKSPACE_CONTAINS_BUILD_FILES, true); } }); - contextManager.setContextValue(Context.EXTENSION_ACTIVATED, true); + await activateJavaProjectExplorerWhenJavaContentExists(context); +} + +/** + * The extension is activated by `workspaceContains:*.gradle*` as well, which fires for any + * Gradle workspace regardless of language (Groovy/Grails/Kotlin/etc.). Showing the + * "Java Projects" view in such workspaces is annoying for non-Java users. To avoid that, + * we only flip the `java:projectManagerActivated` context (which controls the view's + * visibility) when we are confident the workspace actually contains Java content: + * 1. The active editor is a Java file (typical when activated via `onLanguage:java`). + * 2. The workspace contains Maven/Eclipse Java metadata (`pom.xml` / `.classpath`). + * 3. The workspace contains at least one `*.java` source file. + * For Gradle-only workspaces without Java sources we install a watcher so the view will + * appear automatically once a Java file is added later. + */ +async function activateJavaProjectExplorerWhenJavaContentExists(context: ExtensionContext): Promise { + let activated = false; + const setActivated = () => { + if (activated) { + return; + } + activated = true; + contextManager.setContextValue(Context.EXTENSION_ACTIVATED, true); + }; + + // Any already-loaded Java document (active or not) is a strong signal. This also covers + // the case where the extension is activated by `onLanguage:java` but `activeTextEditor` + // has not yet been populated. + if (workspace.textDocuments.some((doc) => doc.languageId === "java") + || window.activeTextEditor?.document.languageId === "java") { + setActivated(); + return; + } + + const [javaProjectMetadata, javaSources] = await Promise.all([ + workspace.findFiles("{**/pom.xml,**/.classpath}", undefined, 1), + workspace.findFiles("**/*.java", undefined, 1), + ]); + if (javaProjectMetadata.length > 0 || javaSources.length > 0) { + setActivated(); + return; + } + + // No Java content detected yet. Listen for it to appear via any of these channels: + // - A `*.java` source file being created in the workspace (FileSystemWatcher). + // - A Java document being opened later (e.g. a single file from outside the workspace). + const javaFileWatcher = workspace.createFileSystemWatcher("**/*.java"); + const disposables: Disposable[] = [ + javaFileWatcher, + javaFileWatcher.onDidCreate(setActivated), + workspace.onDidOpenTextDocument((doc) => { + if (doc.languageId === "java") { + setActivated(); + } + }), + ]; + context.subscriptions.push(...disposables); } async function activateExtension(_operationId: string, context: ExtensionContext): Promise { @@ -81,6 +143,20 @@ async function activateExtension(_operationId: string, context: ExtensionContext } )); setContextForDeprecatedTasks(); + + // Register Copilot context providers after Java Language Server is ready. + languageServerApiManager.ready().then((isReady) => { + const config = workspace.getConfiguration("vscode-java-dependency"); + const isSettingEnabled = config.get("enableLspTools", false); + sendInfo("", { + operationName: "lmTool.registrationCheck", + javaLSReady: isReady ? "true" : "false", + lspToolsEnabled: isSettingEnabled ? "true" : "false", + }); + if (isReady && isSettingEnabled) { + registerJavaContextTools(context); + } + }); } // this method is called when your extension is deactivated diff --git a/src/java/jdtls.ts b/src/java/jdtls.ts index c1388253..84a372a0 100644 --- a/src/java/jdtls.ts +++ b/src/java/jdtls.ts @@ -82,6 +82,10 @@ export namespace Jdtls { return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_CHECK_IMPORT_STATUS) || false; } + export async function getProjectDependencies(projectUri: string): Promise { + return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_GET_DEPENDENCIES, projectUri) || []; + } + export enum CompileWorkspaceStatus { Failed = 0, Succeed = 1, @@ -97,4 +101,9 @@ export namespace Jdtls { interface IPackageDataParam { projectUri: string | undefined; [key: string]: any; +} + +export interface IDependencyInfo { + key: string; + value: string; } \ No newline at end of file diff --git a/src/languageServerApi/languageServerApiManager.ts b/src/languageServerApi/languageServerApiManager.ts index 494c08a4..a89fe4ef 100644 --- a/src/languageServerApi/languageServerApiManager.ts +++ b/src/languageServerApi/languageServerApiManager.ts @@ -13,6 +13,8 @@ class LanguageServerApiManager { private extensionApi: any; private isServerReady: boolean = false; + private isServerRunning: boolean = false; + private serverReadyWaitStarted: boolean = false; public async ready(): Promise { if (this.isServerReady) { @@ -28,11 +30,49 @@ class LanguageServerApiManager { return false; } + // Use serverRunning() if available (API >= 0.14) for progressive loading. + // This resolves when the server process is alive and can handle requests, + // even if project imports haven't completed yet. This enables the tree view + // to show projects incrementally as they are imported. + if (!this.isServerRunning && this.extensionApi.serverRunning) { + await this.extensionApi.serverRunning(); + this.isServerRunning = true; + return true; + } + if (this.isServerRunning) { + return true; + } + + // Fallback for older API versions: wait for full server readiness await this.extensionApi.serverReady(); this.isServerReady = true; return true; } + /** + * Start a background wait for full server readiness (import complete). + * When the server finishes importing, trigger a full refresh to replace + * progressive placeholder items with proper data from the server. + * Guarded so it only starts once regardless of call order. + */ + private startServerReadyWait(): void { + if (this.serverReadyWaitStarted || this.isServerReady) { + return; + } + if (this.extensionApi?.serverReady) { + this.serverReadyWaitStarted = true; + this.extensionApi.serverReady() + .then(() => { + this.isServerReady = true; + commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */false); + }) + .catch((_error: unknown) => { + // Server failed to become ready (e.g., startup failure). + // Leave isServerReady as false; progressive items remain as-is. + }); + } + } + public async initializeJavaLanguageServerApis(): Promise { if (this.isApiInitialized()) { return; @@ -49,18 +89,43 @@ class LanguageServerApiManager { } this.extensionApi = extensionApi; + // Start background wait for full server readiness unconditionally. + // This ensures isServerReady is set and final refresh fires even + // if onDidProjectsImport sets isServerRunning before ready() runs. + this.startServerReadyWait(); + if (extensionApi.onDidClasspathUpdate) { const onDidClasspathUpdate: Event = extensionApi.onDidClasspathUpdate; - contextManager.context.subscriptions.push(onDidClasspathUpdate(() => { - commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true); + contextManager.context.subscriptions.push(onDidClasspathUpdate((uri: Uri) => { + if (this.isServerReady) { + // Server is fully ready — do a normal refresh to get full project data. + commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true); + } else { + // During import, the server is blocked and can't respond to queries. + // Don't clear progressive items. Try to add the project if not + // already present (typically a no-op since ProjectsImported fires first). + commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_ADD_PROJECTS, [uri.toString()]); + } syncHandler.updateFileWatcher(Settings.autoRefresh()); })); } if (extensionApi.onDidProjectsImport) { const onDidProjectsImport: Event = extensionApi.onDidProjectsImport; - contextManager.context.subscriptions.push(onDidProjectsImport(() => { - commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true); + contextManager.context.subscriptions.push(onDidProjectsImport((uris: Uri[]) => { + // Server is sending project data, so it's definitely running. + // Mark as running so ready() returns immediately on subsequent calls. + this.isServerRunning = true; + if (this.isServerReady) { + commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true); + } else { + // During import, the JDTLS server is blocked by Eclipse workspace + // operations and cannot respond to queries. Instead of triggering + // a refresh (which queries the server), directly add projects to + // the tree view from the notification data. + const projectUris = uris.map(u => u.toString()); + commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_ADD_PROJECTS, projectUris); + } syncHandler.updateFileWatcher(Settings.autoRefresh()); })); } @@ -91,6 +156,14 @@ class LanguageServerApiManager { return this.extensionApi !== undefined; } + /** + * Returns true if the server has fully completed initialization (import finished). + * During progressive loading, this returns false even though ready() has resolved. + */ + public isFullyReady(): boolean { + return this.isServerReady; + } + /** * Check if the language server is ready in the given timeout. * @param timeout the timeout in milliseconds to wait diff --git a/src/settings.ts b/src/settings.ts index bea8e7c2..60bde619 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -108,6 +108,10 @@ export class Settings { return workspace.getConfiguration("java.dependency").get("refreshDelay", 2000); } + public static getEnableDependencyCheckup() { + return workspace.getConfiguration("java.dependency").get("enableDependencyCheckup", true); + } + public static getExportJarTargetPath(): string { // tslint:disable-next-line: no-invalid-template-strings return workspace.getConfiguration("java.project.exportJar").get("targetPath", "${workspaceFolder}/${workspaceFolderBasename}.jar"); diff --git a/src/syncHandler.ts b/src/syncHandler.ts index d6d247c0..57dd97f9 100644 --- a/src/syncHandler.ts +++ b/src/syncHandler.ts @@ -13,6 +13,7 @@ import { DataNode } from "./views/dataNode"; import { ExplorerNode } from "./views/explorerNode"; import { explorerNodeCache } from "./views/nodeCache/explorerNodeCache"; import { Jdtls } from "./java/jdtls"; +import upgradeManager from "./upgrade/upgradeManager"; const ENABLE_AUTO_REFRESH: string = "java.view.package.enableAutoRefresh"; const DISABLE_AUTO_REFRESH: string = "java.view.package.disableAutoRefresh"; @@ -46,6 +47,7 @@ class SyncHandler implements Disposable { this.disposables.push(workspace.onDidChangeWorkspaceFolders(() => { this.refresh(); + setImmediate(() => upgradeManager.scan()); // Deferred })); try { @@ -88,7 +90,18 @@ class SyncHandler implements Disposable { })); this.disposables.push(watcher.onDidCreate((uri: Uri) => { - this.refresh(this.getParentNodeInExplorer(uri)); + const node: ExplorerNode | undefined = this.getParentNodeInExplorer(uri); + // When the created resource lands in a package that is not currently + // rendered, getParentNodeInExplorer resolves to the source root. Tell + // that root which path changed so the server can refresh only that + // subtree instead of deeply refreshing the whole source tree. Gate on + // the node kind (not instanceof) to avoid importing PackageRootNode + // here, which would create a module cycle and break activation. + // See https://github.com/microsoft/vscode-java-dependency/issues/914 + if (node instanceof DataNode && node.nodeData?.kind === NodeKind.PackageRoot) { + (node as unknown as { pendingSyncPaths: Set }).pendingSyncPaths.add(uri.toString()); + } + this.refresh(node); })); this.disposables.push(watcher.onDidDelete((uri: Uri) => { diff --git a/src/tasks/build/buildTaskProvider.ts b/src/tasks/build/buildTaskProvider.ts index 6844d68b..ef908fe0 100644 --- a/src/tasks/build/buildTaskProvider.ts +++ b/src/tasks/build/buildTaskProvider.ts @@ -28,7 +28,7 @@ export class BuildTaskProvider implements TaskProvider { const defaultTaskDefinition = { type: BuildTaskProvider.type, paths: [ BuildTaskProvider.workspace ], - isFullBuild: true, + isFullBuild: false, }; const defaultTask = new Task( defaultTaskDefinition, @@ -58,6 +58,9 @@ export class BuildTaskProvider implements TaskProvider { .filter(Boolean); task.definition = taskDefinition; } + if (taskDefinition.isFullBuild === undefined) { + taskDefinition.isFullBuild = false; + } task.execution = new CustomExecution(async (resolvedDefinition: IBuildTaskDefinition): Promise => { return new BuildTaskTerminal(resolvedDefinition, task.scope ?? TaskScope.Workspace); }); diff --git a/src/upgrade/assessmentManager.ts b/src/upgrade/assessmentManager.ts new file mode 100644 index 00000000..3a3c60fb --- /dev/null +++ b/src/upgrade/assessmentManager.ts @@ -0,0 +1,392 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as fs from 'fs'; +import * as semver from 'semver'; +import { globby } from 'globby'; + +import { Uri } from 'vscode'; +import { Jdtls } from "../java/jdtls"; +import { NodeKind, type INodeData } from "../java/nodeData"; +import { type DependencyCheckItem, type UpgradeIssue, type PackageDescription, UpgradeReason } from "./type"; +import { DEPENDENCY_JAVA_RUNTIME } from "./dependency.metadata"; +import { Upgrade } from '../constants'; +import { buildPackageId } from './utility'; +import metadataManager from './metadataManager'; +import { sendInfo } from 'vscode-extension-telemetry-wrapper'; +import { batchGetCVEIssues } from './cve'; +import { ContainerPath } from '../views/containerNode'; + +function packageNodeToDescription(node: INodeData): PackageDescription | null { + const version = node.metaData?.["maven.version"]; + const groupId = node.metaData?.["maven.groupId"]; + const artifactId = node.metaData?.["maven.artifactId"]; + if (!version || !groupId || !artifactId) { + return null; + } + + return { version, groupId, artifactId }; +} + +function getVersionRange(versions: Set) : string { + const versionList = [...versions].sort((a, b) => { + const semverA = semver.coerce(a); + const semverB = semver.coerce(b); + if (!semverA || !semverB) { + return a.localeCompare(b); + } + return semver.compare(semverA, semverB); + }); + if (versionList.length === 1) { + return versionList[0]; + } + return `${versionList[0]}|${versionList[versionList.length - 1]}`; +} + +function collectVersionRange(pkgs: PackageDescription[]): Record { + const versionMap: Record> = {}; + for (const pkg of pkgs) { + const groupId = pkg.groupId; + if (!versionMap[groupId]) { + versionMap[groupId] = new Set(); + } + versionMap[groupId].add(pkg.version); + } + + return Object.fromEntries(Object.entries(versionMap).map(([groupId, versions]) => [groupId, getVersionRange(versions)])); +} + +function getJavaIssues(data: INodeData): UpgradeIssue[] { + const javaVersion = data.metaData?.MaxSourceVersion as number | undefined; + const { name, supportedVersion } = DEPENDENCY_JAVA_RUNTIME; + if (!javaVersion) { + return []; + } + const currentSemVer = semver.coerce(javaVersion); + + const [javaRuntimeGroupId, javaRuntimeArtifactId] = Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME.split(":"); + sendInfo("", { + operationName: "java.dependency.assessmentManager.getJavaVersionRange", + versionRangeByGroupId: JSON.stringify( + collectVersionRange([{ + groupId: javaRuntimeGroupId, + artifactId: javaRuntimeArtifactId, + version: String(javaVersion), + }]), + ), + }); + + if (currentSemVer && !semver.satisfies(currentSemVer, supportedVersion)) { + return [{ + ...DEPENDENCY_JAVA_RUNTIME, + packageId: Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME, + packageDisplayName: name, + currentVersion: String(javaVersion), + }]; + } + + return []; +} + +function getUpgradeForDependency(versionString: string, supportedVersionDefinition: DependencyCheckItem, packageId: string): UpgradeIssue | null { + const reason = supportedVersionDefinition.reason; + switch (reason) { + case UpgradeReason.DEPRECATED: { + return { + ...supportedVersionDefinition, + packageDisplayName: supportedVersionDefinition.name, + reason, + currentVersion: versionString, + packageId, + }; + } + case UpgradeReason.END_OF_LIFE: { + const currentSemVer = semver.coerce(versionString); + if (currentSemVer && !semver.satisfies(currentSemVer, supportedVersionDefinition.supportedVersion)) { + return { + ...supportedVersionDefinition, + packageDisplayName: supportedVersionDefinition.name, + reason, + currentVersion: versionString, + packageId, + }; + } + } + } + + return null; +} + +function getPackageUpgradeMetadata(pkg: PackageDescription): DependencyCheckItem | null { + const { groupId, artifactId } = pkg; + const packageId = buildPackageId(groupId, artifactId); + return metadataManager.getMetadataById(packageId) ?? null; +} + +function getDependencyIssue(pkg: PackageDescription): UpgradeIssue | null { + const supportedVersionDefinition = getPackageUpgradeMetadata(pkg); + const version = pkg.version; + if (!version || !supportedVersionDefinition) { + return null; + } + const { groupId, artifactId } = pkg; + const packageId = buildPackageId(groupId, artifactId); + return getUpgradeForDependency(version, supportedVersionDefinition, packageId); +} + +async function getDependencyIssues(dependencies: PackageDescription[]): Promise { + + const issues = dependencies.map(getDependencyIssue).filter((x): x is UpgradeIssue => Boolean(x)); + const versionRangeByGroupId = collectVersionRange(dependencies.filter(pkg => getPackageUpgradeMetadata(pkg))); + if (Object.keys(versionRangeByGroupId).length > 0) { + sendInfo("", { + operationName: "java.dependency.assessmentManager.getDependencyVersionRange", + versionRangeByGroupId: JSON.stringify(versionRangeByGroupId), + }); + } + + return issues; +} + +async function getWorkspaceIssues(projectDeps: {projectNode: INodeData, dependencies: PackageDescription[]}[]): Promise { + + const issues: UpgradeIssue[] = []; + const dependencyMap: Map = new Map(); + for (const { projectNode, dependencies } of projectDeps) { + issues.push(...getJavaIssues(projectNode)); + for (const dep of dependencies) { + const key = `${dep.groupId}:${dep.artifactId}:${dep.version ?? ""}`; + if (!dependencyMap.has(key)) { + dependencyMap.set(key, dep); + } + } + } + const uniqueDependencies = Array.from(dependencyMap.values()); + issues.push(...await getCVEIssues(uniqueDependencies)); + issues.push(...await getDependencyIssues(uniqueDependencies)); + return issues; +} + +/** + * Find all pom.xml files in a directory using glob + */ +async function findAllPomFiles(dir: string): Promise { + try { + return await globby('**/pom.xml', { + cwd: dir, + absolute: true, + ignore: ['**/node_modules/**', '**/target/**', '**/.git/**', '**/.idea/**', '**/.vscode/**'] + }); + } catch { + return []; + } +} + +/** + * Parse dependencies from a single pom.xml file + */ +function parseDependenciesFromSinglePom(pomPath: string): Set { + // TODO : Use a proper XML parser if needed + const directDeps = new Set(); + try { + const pomContent = fs.readFileSync(pomPath, 'utf-8'); + + // Extract dependencies from section (not inside ) + // First, remove dependencyManagement sections to avoid including managed deps + const withoutDepMgmt = pomContent.replace(/[\s\S]*?<\/dependencyManagement>/g, ''); + + // Match blocks and extract groupId and artifactId + const dependencyRegex = /\s*([^<]+)<\/groupId>\s*([^<]+)<\/artifactId>/g; + let match = dependencyRegex.exec(withoutDepMgmt); + while (match !== null) { + const groupId = match[1].trim(); + const artifactId = match[2].trim(); + // Skip property references like ${project.groupId} + if (!groupId.includes('${') && !artifactId.includes('${')) { + directDeps.add(`${groupId}:${artifactId}`); + } + match = dependencyRegex.exec(withoutDepMgmt); + } + } catch { + // If we can't read the pom, return empty set + } + return directDeps; +} + +/** + * Parse direct dependencies from all pom.xml files in the project. + * Finds all pom.xml files starting from the project root and parses them to collect dependencies. + */ +async function parseDirectDependenciesFromPom(projectPath: string): Promise> { + const directDeps = new Set(); + + // Find all pom.xml files in the project starting from the project root + const allPomFiles = await findAllPomFiles(projectPath); + + // Parse each pom.xml and collect dependencies + for (const pom of allPomFiles) { + const deps = parseDependenciesFromSinglePom(pom); + deps.forEach(dep => directDeps.add(dep)); + } + + return directDeps; +} + +/** + * Find all Gradle build files in a directory using glob + */ +async function findAllGradleFiles(dir: string): Promise { + try { + return await globby('**/{build.gradle,build.gradle.kts}', { + cwd: dir, + absolute: true, + ignore: ['**/node_modules/**', '**/build/**', '**/.git/**', '**/.idea/**', '**/.vscode/**', '**/.gradle/**'] + }); + } catch { + return []; + } +} + +/** + * Parse dependencies from a single Gradle build file + */ +function parseDependenciesFromSingleGradle(gradlePath: string): Set { + const directDeps = new Set(); + try { + const gradleContent = fs.readFileSync(gradlePath, 'utf-8'); + + // Match common dependency configurations: + // implementation 'group:artifact:version' + // implementation "group:artifact:version" + // api 'group:artifact:version' + // compileOnly, runtimeOnly, testImplementation, etc. + const shortFormRegex = /(?:implementation|api|compile|compileOnly|runtimeOnly|testImplementation|testCompileOnly|testRuntimeOnly)\s*\(?['"]([^:'"]+):([^:'"]+)(?::[^'"]*)?['"]\)?/g; + let match = shortFormRegex.exec(gradleContent); + while (match !== null) { + const groupId = match[1].trim(); + const artifactId = match[2].trim(); + if (!groupId.includes('$') && !artifactId.includes('$')) { + directDeps.add(`${groupId}:${artifactId}`); + } + match = shortFormRegex.exec(gradleContent); + } + + // Match map notation: implementation group: 'x', name: 'y', version: 'z' + const mapFormRegex = /(?:implementation|api|compile|compileOnly|runtimeOnly|testImplementation|testCompileOnly|testRuntimeOnly)\s*\(?group:\s*['"]([^'"]+)['"]\s*,\s*name:\s*['"]([^'"]+)['"]/g; + match = mapFormRegex.exec(gradleContent); + while (match !== null) { + const groupId = match[1].trim(); + const artifactId = match[2].trim(); + if (!groupId.includes('$') && !artifactId.includes('$')) { + directDeps.add(`${groupId}:${artifactId}`); + } + match = mapFormRegex.exec(gradleContent); + } + } catch { + // If we can't read the gradle file, return empty set + } + return directDeps; +} + +/** + * Parse direct dependencies from all Gradle build files in the project. + * Finds all build.gradle and build.gradle.kts files and parses them to collect dependencies. + */ +async function parseDirectDependenciesFromGradle(projectPath: string): Promise> { + const directDeps = new Set(); + + // Find all Gradle build files in the project + const allGradleFiles = await findAllGradleFiles(projectPath); + + // Parse each gradle file and collect dependencies + for (const gradleFile of allGradleFiles) { + const deps = parseDependenciesFromSingleGradle(gradleFile); + deps.forEach(dep => directDeps.add(dep)); + } + + return directDeps; +} + +export async function getDirectDependencies(projectNode: INodeData): Promise { + const projectStructureData = await Jdtls.getPackageData({ kind: NodeKind.Project, projectUri: projectNode.uri }); + // Only include Maven or Gradle containers (not JRE or other containers) + const dependencyContainers = projectStructureData.filter(x => + x.kind === NodeKind.Container && + (x.path?.startsWith(ContainerPath.Maven) || x.path?.startsWith(ContainerPath.Gradle)) + ); + + if (dependencyContainers.length === 0) { + return []; + } + + const allPackages = await Promise.allSettled( + dependencyContainers.map(async (packageContainer) => { + const packageNodes = await Jdtls.getPackageData({ + kind: NodeKind.Container, + projectUri: projectNode.uri, + path: packageContainer.path, + }); + return packageNodes + .map(packageNodeToDescription) + .filter((x): x is PackageDescription => Boolean(x)); + }) + ); + + const fulfilled = allPackages.filter((x): x is PromiseFulfilledResult => x.status === "fulfilled"); + const failedPackageCount = allPackages.length - fulfilled.length; + if (failedPackageCount > 0) { + sendInfo("", { + operationName: "java.dependency.assessmentManager.getDirectDependencies.rejected", + failedPackageCount: String(failedPackageCount), + }); + } + + let dependencies = fulfilled.map(x => x.value).flat(); + + if (!dependencies || dependencies.length === 0) { + sendInfo("", { + operationName: "java.dependency.assessmentManager.getDirectDependencies.noDependencyInfo" + }); + return []; + } + + // Determine build type from dependency containers + const isMaven = dependencyContainers.some(x => x.path?.startsWith(ContainerPath.Maven)); + // Get direct dependency identifiers from build files + let directDependencyIds: Set | null = null; + if (projectNode.uri && dependencyContainers.length > 0) { + try { + const projectPath = Uri.parse(projectNode.uri).fsPath; + if (isMaven) { + directDependencyIds = await parseDirectDependenciesFromPom(projectPath); + } else { + directDependencyIds = await parseDirectDependenciesFromGradle(projectPath); + } + } catch { + // Ignore errors + } + } + + if (!directDependencyIds || directDependencyIds.size === 0) { + sendInfo("", { + operationName: "java.dependency.assessmentManager.getDirectDependencies.noDirectDependencyInfo" + }); + // TODO: fallback to return all dependencies if we cannot parse direct dependencies or just return empty? + return dependencies; + } + // Filter to only direct dependencies if we have build file info + dependencies = dependencies.filter(pkg => + directDependencyIds!.has(`${pkg.groupId}:${pkg.artifactId}`) + ); + + return dependencies; +} + +async function getCVEIssues(dependencies: PackageDescription[]): Promise { + const gavCoordinates = dependencies.map(pkg => `${pkg.groupId}:${pkg.artifactId}:${pkg.version}`); + return batchGetCVEIssues(gavCoordinates); +} + +export default { + getWorkspaceIssues, +}; \ No newline at end of file diff --git a/src/upgrade/cve.ts b/src/upgrade/cve.ts new file mode 100644 index 00000000..804afa1a --- /dev/null +++ b/src/upgrade/cve.ts @@ -0,0 +1,192 @@ +import { UpgradeIssue, UpgradeReason } from "./type"; +import { Octokit } from "@octokit/rest"; +import * as semver from "semver"; + +/** + * Severity levels ordered by criticality (higher number = more critical) + * The official doc about the severity levels can be found at: + * https://docs.github.com/en/rest/security-advisories/global-advisories?apiVersion=2022-11-28 + */ +export enum Severity { + unknown = 0, + low = 1, + medium = 2, + high = 3, + critical = 4, +} + +export interface CVE { + id: string; + ghsa_id: string; + severity: keyof typeof Severity; + summary: string; + description: string; + html_url: string; + affectedDeps: { + name?: string | null; + vulVersions?: string | null; + patchedVersion?: string | null; + }[]; +} + +export type CveUpgradeIssue = UpgradeIssue & { + reason: UpgradeReason.CVE; + severity: string; + link: string; +}; + +export async function batchGetCVEIssues( + coordinates: string[] +): Promise { + // Split dependencies into smaller batches to avoid URL length limit + const BATCH_SIZE = 30; + const allCVEUpgradeIssues: CveUpgradeIssue[] = []; + + // Process dependencies in batches + for (let i = 0; i < coordinates.length; i += BATCH_SIZE) { + const batchCoordinates = coordinates.slice(i, i + BATCH_SIZE); + const cveUpgradeIssues = await getCveUpgradeIssues(batchCoordinates); + allCVEUpgradeIssues.push(...cveUpgradeIssues); + } + + return allCVEUpgradeIssues; +} + +async function getCveUpgradeIssues( + coordinates: string[] +): Promise { + if (coordinates.length === 0) { + return []; + } + const deps = coordinates + .map((d) => d.split(":", 3)) + .map((p) => ({ name: `${p[0]}:${p[1]}`, version: p[2] })) + .filter((d) => d.version); + + const depsCves = await fetchCves(deps); + return mapCvesToUpgradeIssues(depsCves); +} + +async function fetchCves(deps: { name: string; version: string }[]) { + if (deps.length === 0) { + return []; + } + try { + const allCves: CVE[] = await retrieveVulnerabilityData(deps); + + if (allCves.length === 0) { + return []; + } + // group the cves by coordinate + const depsCves: { dep: string; version: string; cves: CVE[] }[] = []; + + for (const dep of deps) { + const depCves: CVE[] = allCves.filter((cve) => + isCveAffectingDep(cve, dep.name, dep.version) + ); + + if (depCves.length < 1) { + continue; + } + + depsCves.push({ + dep: dep.name, + version: dep.version, + cves: depCves, + }); + } + + return depsCves; + } catch (error) { + return []; + } +} + +async function retrieveVulnerabilityData( + deps: { name: string; version: string }[] +) { + if (deps.length === 0) { + return []; + } + const octokit = new Octokit(); + + // Use paginate to fetch all pages of results + const allAdvisories = await octokit.paginate( + octokit.securityAdvisories.listGlobalAdvisories, + { + ecosystem: "maven", + affects: deps.map((p) => `${p.name}@${p.version}`), + direction: "asc", + sort: "published", + per_page: 100, + } + ); + + const allCves: CVE[] = allAdvisories + .filter( + (c) => + !c.withdrawn_at?.trim() && + (c.severity === "critical" || c.severity === "high") + ) // only consider critical and high severity CVEs + .map((cve) => ({ + id: cve.cve_id || cve.ghsa_id, + ghsa_id: cve.ghsa_id, + severity: cve.severity, + summary: cve.summary, + description: cve.description || cve.summary, + html_url: cve.html_url, + affectedDeps: (cve.vulnerabilities ?? []).map((v) => ({ + name: v.package?.name, + vulVersions: v.vulnerable_version_range, + patchedVersion: v.first_patched_version, + })), + })); + return allCves; +} + +function mapCvesToUpgradeIssues( + depsCves: { dep: string; version: string; cves: CVE[] }[] +) { + if (depsCves.length === 0) { + return []; + } + const upgradeIssues = depsCves.map((depCve) => { + const mostCriticalCve = [...depCve.cves] + .sort((a, b) => Severity[b.severity] - Severity[a.severity])[0]; + return { + packageId: depCve.dep, + packageDisplayName: depCve.dep, + currentVersion: depCve.version || "unknown", + name: `${mostCriticalCve.id || "CVE"}`, + reason: UpgradeReason.CVE as const, + suggestedVersion: { + name: "", + description: "", + }, + severity: mostCriticalCve.severity, + description: + mostCriticalCve.description || + mostCriticalCve.summary || + "Security vulnerability detected", + link: mostCriticalCve.html_url, + }; + }); + return upgradeIssues; +} + +function isCveAffectingDep( + cve: CVE, + depName: string, + depVersion: string +): boolean { + if (!cve.affectedDeps || cve.affectedDeps.length === 0) { + return false; + } + return cve.affectedDeps.some((d) => { + if (d.name !== depName || !d.vulVersions) { + return false; + } + + return semver.satisfies(depVersion || "0.0.0", d.vulVersions); + }); +} diff --git a/src/upgrade/dependency.metadata.ts b/src/upgrade/dependency.metadata.ts new file mode 100644 index 00000000..df7b3380 --- /dev/null +++ b/src/upgrade/dependency.metadata.ts @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { Upgrade } from "../constants"; +import { UpgradeReason, type DependencyCheckMetadata } from "./type"; + +const MATURE_JAVA_LTS_VERSION = 25; + +export const DEPENDENCY_JAVA_RUNTIME = { + "name": "Java Runtime", + "reason": UpgradeReason.JRE_TOO_OLD, + "supportedVersion": `>=${MATURE_JAVA_LTS_VERSION}`, + "suggestedVersion": { + "name": `Java ${MATURE_JAVA_LTS_VERSION}`, + "description": "LTS version", + }, +} as const; + +const DEPENDENCIES_TO_SCAN: DependencyCheckMetadata = { + "org.springframework.boot:*": { + "reason": UpgradeReason.END_OF_LIFE, + "name": "Spring Boot", + "supportedVersion": "2.7.x || >=3.2.x", + "eolDate": { + "4.0.x": "2027-12", + "3.5.x": "2032-06", + "3.4.x": "2026-12", + "3.3.x": "2026-06", + "3.2.x": "2025-12", + "3.1.x": "2025-06", + "3.0.x": "2024-12", + "2.7.x": "2029-06", + "2.6.x": "2024-02", + "2.5.x": "2023-08", + "2.4.x": "2023-02", + "2.3.x": "2022-08", + "2.2.x": "2022-01", + "2.1.x": "2021-01", + "2.0.x": "2020-06", + "1.5.x": "2020-11", + }, + "suggestedVersion": { + "name": "3.5", + "description": "latest stable release", + }, + }, + "org.springframework:*": { + "reason": UpgradeReason.END_OF_LIFE, + "name": "Spring Framework", + "supportedVersion": "5.3.x || >=6.2.x", + "eolDate": { + "7.0.x": "2028-06", + "6.2.x": "2032-06", + "6.1.x": "2026-06", + "6.0.x": "2025-08", + "5.3.x": "2029-06", + "5.2.x": "2023-12", + "5.1.x": "2022-12", + "5.0.x": "2022-12", + "4.3.x": "2020-12", + }, + "suggestedVersion": { + "name": "6.2", + "description": "latest stable release", + }, + }, + "org.springframework.security:*": { + "reason": UpgradeReason.END_OF_LIFE, + "name": "Spring Security", + "supportedVersion": "5.7.x || 5.8.x || >=6.2.x", + "eolDate": { + "7.0.x": "2027-12", + "6.5.x": "2032-06", + "6.4.x": "2026-12", + "6.3.x": "2026-06", + "6.2.x": "2025-12", + "6.1.x": "2025-06", + "6.0.x": "2024-12", + "5.8.x": "2029-06", + "5.7.x": "2029-06", + "5.6.x": "2024-02", + "5.5.x": "2023-08", + "5.4.x": "2023-02", + "5.3.x": "2022-08", + "5.2.x": "2022-01", + "5.1.x": "2021-01", + "5.0.x": "2020-06", + "4.2.x": "2020-11", + }, + "suggestedVersion": { + "name": "3.5", + "description": "latest stable release", + }, + }, + "javax:*": { + "reason": UpgradeReason.DEPRECATED, + "name": "Java EE", + "suggestedVersion": { + "name": "Jakarta EE 10", + "description": "latest release with wide Java runtime version support", + + }, + }, + [Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME]: DEPENDENCY_JAVA_RUNTIME, +}; + +export default DEPENDENCIES_TO_SCAN; \ No newline at end of file diff --git a/src/upgrade/display/notificationManager.ts b/src/upgrade/display/notificationManager.ts new file mode 100644 index 00000000..29f0f5ca --- /dev/null +++ b/src/upgrade/display/notificationManager.ts @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { commands, ExtensionContext, window } from "vscode"; +import { UpgradeReason, type IUpgradeIssuesRenderer, type UpgradeIssue } from "../type"; +import { buildCVENotificationMessage, buildFixPrompt, buildNotificationMessage, getExtensionState, type ExtensionState } from "../utility"; +import { Commands } from "../../commands"; +import { Settings } from "../../settings"; +import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper"; +import { ExtensionName, Upgrade } from "../../constants"; +import { CveUpgradeIssue } from "../cve"; + +const KEY_PREFIX = 'javaupgrade.notificationManager'; +const NEXT_SHOW_TS_KEY = `${KEY_PREFIX}.nextShowTs`; + +const BUTTON_TEXT_NOT_NOW = "Not Now"; + +// Action button label keyed by the install state of the app modernization extension. +const UPGRADE_BUTTON_TEXT: Record = { + "up-to-date": "Upgrade Now", + "outdated": "Update Extension and Upgrade", + "not-installed": "Install Extension and Upgrade", +}; +const FIX_CVE_BUTTON_TEXT: Record = { + "up-to-date": "Fix Now", + "outdated": "Update Extension and Fix", + "not-installed": "Install Extension and Fix", +}; + +const SECONDS_IN_A_DAY = 24 * 60 * 60; +const SECONDS_COUNT_BEFORE_NOTIFICATION_RESHOW = 10 * SECONDS_IN_A_DAY; + +function getNowTs() { + return Number(new Date()) / 1000; +} + +class NotificationManager implements IUpgradeIssuesRenderer { + private hasShown = false; + private context?: ExtensionContext; + + initialize(context: ExtensionContext) { + this.context = context; + } + + async render(issues: UpgradeIssue[]) { + return (instrumentOperation( + "java.dependency.showUpgradeNotification", + async (operationId: string) => { + if (issues.length === 0) { + return; + } + + if (!this.shouldShow() || this.hasShown) { + return; + } + this.hasShown = true; + + // Prefer Java upgrade recommendations over CVE fixes: only fall back + // to a CVE notification when there is no upgrade issue to recommend. + const cveIssues = issues.filter( + (i): i is CveUpgradeIssue => i.reason === UpgradeReason.CVE + ); + const upgradeIssues = issues.filter( + (i) => i.reason !== UpgradeReason.CVE + ); + const isCVE = upgradeIssues.length === 0; + const issue = isCVE ? cveIssues[0] : upgradeIssues[0]; + + const extensionState = getExtensionState(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA); + const source = isCVE ? Upgrade.SOURCE_CVE : Upgrade.SOURCE_JAVA_UPGRADE; + const notificationMessage = isCVE + ? buildCVENotificationMessage(cveIssues, extensionState) + : buildNotificationMessage(issue, extensionState); + const actionButtonText = isCVE + ? FIX_CVE_BUTTON_TEXT[extensionState] + : UPGRADE_BUTTON_TEXT[extensionState]; + + sendInfo(operationId, { + operationName: "java.dependency.upgradeNotification.show", + extensionState, + source, + }); + + const selection = await window.showInformationMessage( + notificationMessage, + actionButtonText, + BUTTON_TEXT_NOT_NOW + ); + sendInfo(operationId, { + operationName: "java.dependency.upgradeNotification.runUpgrade", + choice: selection ?? "", + }); + + if (selection === actionButtonText) { + commands.executeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, buildFixPrompt(issue), source); + } else if (selection === BUTTON_TEXT_NOT_NOW) { + this.setNextShowTs(getNowTs() + SECONDS_COUNT_BEFORE_NOTIFICATION_RESHOW); + } + } + ))(); + } + + private shouldShow() { + return Settings.getEnableDependencyCheckup() + && ((this.getNextShowTs() ?? 0) <= getNowTs()); + } + + private getNextShowTs() { + return this.context?.globalState.get(NEXT_SHOW_TS_KEY); + } + + private setNextShowTs(num: number) { + return this.context?.globalState.update(NEXT_SHOW_TS_KEY, num); + } +} + +const notificationManager = new NotificationManager(); +export default notificationManager; \ No newline at end of file diff --git a/src/upgrade/metadataManager.ts b/src/upgrade/metadataManager.ts new file mode 100644 index 00000000..f9f79dfd --- /dev/null +++ b/src/upgrade/metadataManager.ts @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { type DependencyCheckMetadata, type DependencyCheckItem } from "./type"; +import { buildPackageId } from "./utility"; +import DEPENDENCIES_TO_SCAN from "./dependency.metadata"; + +class MetadataManager { + private static dependencyCheckMetadata: DependencyCheckMetadata = DEPENDENCIES_TO_SCAN; + + public static getMetadataById(givenPackageId: string): DependencyCheckItem | undefined { + const splits = givenPackageId.split(":", 2); + const groupId = splits[0]; + const artifactId = splits[1] ?? ""; + + const packageId = buildPackageId(groupId, artifactId); + const packageIdWithWildcardArtifactId = buildPackageId(groupId, "*"); + return this.getMetadata(packageId) ?? this.getMetadata(packageIdWithWildcardArtifactId); + } + + private static getMetadata(packageRuleUsed: string) { + return this.dependencyCheckMetadata[packageRuleUsed] ? { + ...this.dependencyCheckMetadata[packageRuleUsed], packageRuleUsed + } : undefined; + } +} + +export default MetadataManager; \ No newline at end of file diff --git a/src/upgrade/type.ts b/src/upgrade/type.ts new file mode 100644 index 00000000..74802b82 --- /dev/null +++ b/src/upgrade/type.ts @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +export type UpgradeTarget = { name: string; description: string }; +export type DependencyCheckItemBase = { name: string, reason: UpgradeReason, suggestedVersion: UpgradeTarget }; +export type DependencyCheckItemEol = DependencyCheckItemBase & { + reason: UpgradeReason.END_OF_LIFE, + supportedVersion: string, + eolDate: Record +}; +export type DependencyCheckItemJreTooOld = DependencyCheckItemBase & { reason: UpgradeReason.JRE_TOO_OLD }; +export type DependencyCheckItemDeprecated = DependencyCheckItemBase & { reason: UpgradeReason.DEPRECATED }; +export type DependencyCheckItemCve = DependencyCheckItemBase & { reason: UpgradeReason.CVE, severity: string, description: string, link: string }; +export type DependencyCheckItem = (DependencyCheckItemEol | DependencyCheckItemJreTooOld | DependencyCheckItemDeprecated | DependencyCheckItemCve); +export type DependencyCheckMetadata = Record; + +export enum UpgradeReason { + END_OF_LIFE, + DEPRECATED, + CVE, + JRE_TOO_OLD, +} + +export type UpgradeIssue = { + packageId: string; + packageDisplayName: string; + currentVersion: string; +} & DependencyCheckItem; + +export interface IUpgradeIssuesRenderer { + render(issues: UpgradeIssue[]): void; +} + +export type PackageDescription = { + groupId: string; + artifactId: string; + version: string; +}; \ No newline at end of file diff --git a/src/upgrade/upgradeManager.ts b/src/upgrade/upgradeManager.ts new file mode 100644 index 00000000..90a60b2a --- /dev/null +++ b/src/upgrade/upgradeManager.ts @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { commands, type ExtensionContext, workspace, type WorkspaceFolder } from "vscode"; + +import { Jdtls } from "../java/jdtls"; +import { languageServerApiManager } from "../languageServerApi/languageServerApiManager"; +import { ExtensionName, Upgrade } from "../constants"; +import { instrumentOperation, instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper"; +import { Commands } from "../commands"; +import notificationManager from "./display/notificationManager"; +import { Settings } from "../settings"; +import assessmentManager, { getDirectDependencies } from "./assessmentManager"; +import { checkOrInstallAppModExtensionForUpgrade, checkOrPopupToInstallAppModExtensionForModernization } from "./utility"; + +const DEFAULT_UPGRADE_PROMPT = "Upgrade Java project dependency to latest version."; + + +function shouldRunCheckup() { + return Settings.getEnableDependencyCheckup(); +} + +class UpgradeManager { + public static initialize(context: ExtensionContext) { + notificationManager.initialize(context); + + // Upgrade project + context.subscriptions.push(instrumentOperationAsVsCodeCommand( + Commands.JAVA_UPGRADE_WITH_COPILOT, async (promptText?: string, source?: string) => { + const canProceed = await checkOrInstallAppModExtensionForUpgrade( + ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA); + if (!canProceed) { + return; + } + const promptToUse = promptText ?? DEFAULT_UPGRADE_PROMPT; + const upgradeSource = source ?? Upgrade.SOURCE_JAVA_UPGRADE; + await commands.executeCommand(Commands.GOTO_AGENT_MODE, { + prompt: promptToUse, useCustomAgent: true, source: upgradeSource, + }); + })); + + // Show modernization view + context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MODERNIZE_JAVA_PROJECT, async () => { + await checkOrPopupToInstallAppModExtensionForModernization( + ExtensionName.APP_MODERNIZATION_FOR_JAVA, + `${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension is required to modernize Java projects. Would you like to install it and modernize this project?`, + "Install Extension and Modernize"); + await commands.executeCommand("workbench.view.extension.azureJavaMigrationExplorer"); + })); + + // Defer the expensive scan operation to not block extension activation + setImmediate(() => UpgradeManager.scan()); + } + + public static scan() { + if (!shouldRunCheckup()) { + return; + } + workspace.workspaceFolders?.forEach((folder) => + UpgradeManager.runDependencyCheckup(folder) + ); + } + + private static async runDependencyCheckup(folder: WorkspaceFolder) { + return instrumentOperation("java.dependency.runDependencyCheckup", async (_operationId: string) => { + if (!(await languageServerApiManager.ready())) { + sendInfo(_operationId, { skipReason: "languageServerNotReady" }); + return; + } + + const hasJavaError: boolean = await Jdtls.checkImportStatus(); + if (hasJavaError) { + sendInfo(_operationId, { skipReason: "hasJavaError" }); + return; + } + + const projects = await Jdtls.getProjects(folder.uri.toString()); + const projectDirectDepsResults = await Promise.allSettled( + projects.map(async (projectNode) => ({ + projectNode, + dependencies: await getDirectDependencies(projectNode), + })) + ); + + const allProjectDirectDeps = projectDirectDepsResults.flatMap(result => + result.status === "fulfilled" ? [result.value] : [] + ); + + if (allProjectDirectDeps.every((x) => x.dependencies.length === 0)) { + sendInfo(_operationId, { skipReason: "notMavenGradleProject" }); + return; + } + + const workspaceIssues = await assessmentManager.getWorkspaceIssues(allProjectDirectDeps); + if (workspaceIssues.length > 0) { + notificationManager.render(workspaceIssues); + } + })(); + } +} + +export default UpgradeManager; \ No newline at end of file diff --git a/src/upgrade/utility.ts b/src/upgrade/utility.ts new file mode 100644 index 00000000..0f364a20 --- /dev/null +++ b/src/upgrade/utility.ts @@ -0,0 +1,258 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { commands, extensions, Uri, window } from "vscode"; +import * as semver from "semver"; +import { UpgradeReason, type UpgradeIssue } from "./type"; +import { ExtensionName, Upgrade } from "../constants"; +import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper"; +import { CveUpgradeIssue } from "./cve"; + + +function findEolDate(currentVersion: string, eolDate: Record): string | null { + const currentVersionSemVer = semver.coerce(currentVersion); + if (!currentVersionSemVer) { + return null; + } + for (const [versionRange, date] of Object.entries(eolDate)) { + if (semver.satisfies(currentVersionSemVer, versionRange)) { + return date; + } + } + return null; +} + +export type ExtensionState = "up-to-date" | "outdated" | "not-installed"; + +export function getExtensionState(extensionId: string): ExtensionState { + const ext = extensions.getExtension(extensionId); + if (!ext) { + return "not-installed"; + } + const version = ext.packageJSON?.version; + if (version && semver.gte(version, Upgrade.MIN_APPMOD_VERSION)) { + return "up-to-date"; + } + // Treat missing version as outdated (conservative) + return "outdated"; +} + +function getActionWord(extensionState: ExtensionState, verb: string): string { + switch (extensionState) { + case "up-to-date": + return verb; + case "outdated": + return `update ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and ${verb}`; + case "not-installed": + return `install ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and ${verb}`; + } +} + +export function buildNotificationMessage(issue: UpgradeIssue, extensionState: ExtensionState): string { + const { + packageId, + currentVersion, + reason, + suggestedVersion: { name: suggestedVersionName, description: suggestedVersionDescription }, + packageDisplayName + } = issue; + + const upgradeWord = getActionWord(extensionState, "upgrade"); + + if (packageId === Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME) { + return `This project is using an older Java runtime (${currentVersion}). Would you like to ${upgradeWord} it to the latest LTS version?`; + } + + switch (reason) { + case UpgradeReason.END_OF_LIFE: { + const { eolDate } = issue; + const versionEolDate = findEolDate(currentVersion, eolDate); + return `This project is using ${packageDisplayName} ${currentVersion}, which has reached end of life${versionEolDate ? ` in ${versionEolDate}` : "" + }. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`; + } + case UpgradeReason.DEPRECATED: + default: { + return `This project is using ${packageDisplayName} ${currentVersion}, which has been deprecated. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`; + } + } +} + +export function buildCVENotificationMessage(issues: CveUpgradeIssue[], extensionState: ExtensionState): string { + + if (issues.length === 0) { + return "No CVE issues found."; + } + const severityCount: Record = issues.reduce>((acc, { reason, severity }) => { + if (reason === UpgradeReason.CVE && (severity === 'critical' || severity === 'high')) { + acc[severity] = (acc[severity] ?? 0) + 1; + } + return acc; + }, {}); + + const criticalCount = severityCount.critical || 0; + const highCount = severityCount.high || 0; + + const parts: string[] = []; + if (criticalCount > 0) { + parts.push(`${criticalCount} critical`); + } + if (highCount > 0) { + parts.push(`${highCount} high-severity`); + } + + const severityText = parts.join(" and "); + + sendInfo("", { + operationName: "java.dependency.upgrade.getCVESeverityDistribution", + CVESeverityDistribution: severityText, + }); + + const fixWord = getActionWord(extensionState, "fix"); + + if (issues.length === 1) { + return `${severityText} CVE vulnerability is detected in this project. Would you like to ${fixWord} it now?`; + } + + return `${severityText} CVE vulnerabilities are detected in this project. Would you like to ${fixWord} them now?`; +} +export function buildFixPrompt(issue: UpgradeIssue): string { + const { packageDisplayName, reason } = issue; + + switch (reason) { + case UpgradeReason.JRE_TOO_OLD: { + return `upgrade java runtime to the latest LTS version`; + } + case UpgradeReason.END_OF_LIFE: + case UpgradeReason.DEPRECATED: { + const { suggestedVersion: { name: suggestedVersionName } } = issue; + return `upgrade ${packageDisplayName} to ${suggestedVersionName}`; + } + case UpgradeReason.CVE: { + return `fix all critical and high-severity CVE vulnerabilities in this project by invoking #appmod-validate-cves-for-java`; + } + } +} + +export function buildPackageId(groupId: string, artifactId: string): string { + return `${groupId}:${artifactId}`; +} + +export function normalizePath(path: string): string { + return Uri.parse(path).toString(); +} + +async function checkOrPromptToEnableAppModExtension(keyword: string) { + if (extensions.getExtension(ExtensionName.APP_MODERNIZATION_FOR_JAVA)) { + return; + } + + // The extension is in a disabled state since we cannot detect the extension after installing it. + await instrumentOperation("java.dependency.extensionDisabled", async () => { + await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA); + const BTN_TEXT = "Show extension in sidebar"; + const choice2 = await window.showInformationMessage( + `${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension is required to ${keyword} Java projects but it seems disabled. Please enable it manually and try again.`, + { modal: true }, + BTN_TEXT + ); + if (choice2 === BTN_TEXT) { + await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA); + } + })(); +} + +export async function checkOrPopupToInstallAppModExtensionForModernization( + extensionIdToCheck: string, + notificationText: string, + buttonText: string): Promise { + if (extensions.getExtension(extensionIdToCheck)) { + return; + } + + const choice = await window.showInformationMessage(notificationText, { modal: true }, buttonText); + if (choice === buttonText) { + await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA); + } else { + return; + } + + await checkOrPromptToEnableAppModExtension("modernize"); +} + +export async function checkOrInstallAppModExtensionForUpgrade( + extensionIdToCheck: string): Promise { + return instrumentOperation("java.dependency.upgradeFlow", async (operationId: string) => { + const state = getExtensionState(extensionIdToCheck); + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.start", + extensionState: state, + }); + + if (state === "up-to-date") { + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.result", + upgradeFlowResult: "proceeded", + }); + return true; + } + + await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA); + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.result", + upgradeFlowStep: "installSucceeded", + installType: state === "outdated" ? "updated" : "installed", + }); + + if (state === "outdated") { + // Extension was updated (not freshly installed) — reload required + const reload = await window.showInformationMessage( + `${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension has been updated. Reload VS Code to start the upgrade experience.`, + "Reload Now" + ); + if (reload === "Reload Now") { + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.result", + upgradeFlowResult: "reload-accepted", + }); + await commands.executeCommand("workbench.action.reloadWindow"); + } else { + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.result", + upgradeFlowResult: "reload-dismissed", + }); + } + return false; + } + + // Wait until the freshly installed extension is registered, returning as + // soon as it is ready, or after a 5s timeout fallback at the latest. + await waitForExtensionReady(extensionIdToCheck, 5000); + + sendInfo(operationId, { + operationName: "java.dependency.upgradeFlow.result", + upgradeFlowResult: "proceeded", + }); + return true; + })(); +} + +function waitForExtensionReady(extensionId: string, timeoutMs: number): Promise { + return new Promise(resolve => { + if (extensions.getExtension(extensionId)) { + resolve(); + return; + } + let timer: NodeJS.Timeout; + const disposable = extensions.onDidChange(() => { + if (extensions.getExtension(extensionId)) { + clearTimeout(timer); + disposable.dispose(); + resolve(); + } + }); + timer = setTimeout(() => { + disposable.dispose(); + resolve(); + }, timeoutMs); + }); +} diff --git a/src/utility.ts b/src/utility.ts index ee647dca..9ea08371 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -88,7 +88,9 @@ export function isKeyword(identifier: string): boolean { return keywords.has(identifier); } -const identifierRegExp: RegExp = /^([a-zA-Z_$][a-zA-Z\d_$]*)$/; +// Java identifier per JLS §3.8: start with a Unicode letter, underscore, or dollar sign; +// continue with Unicode letters, digits, underscore, dollar sign, or combining marks. +const identifierRegExp: RegExp = /^[\p{L}\p{Nl}_$][\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}_$\u200c\u200d]*$/u; export function isJavaIdentifier(identifier: string): boolean { return identifierRegExp.test(identifier); } diff --git a/src/views/PrimaryTypeNode.ts b/src/views/PrimaryTypeNode.ts index 8ee95223..0d80bf8b 100644 --- a/src/views/PrimaryTypeNode.ts +++ b/src/views/PrimaryTypeNode.ts @@ -34,6 +34,10 @@ export class PrimaryTypeNode extends DataNode { return ""; } + public getLabel(): string { + return this._nodeData.displayName ?? this._nodeData.name; + } + protected async loadData(): Promise { if (!this.hasChildren() || !this.nodeData.uri) { return undefined; diff --git a/src/views/containerNode.ts b/src/views/containerNode.ts index 0245514c..8ae3e83b 100644 --- a/src/views/containerNode.ts +++ b/src/views/containerNode.ts @@ -15,23 +15,36 @@ export class ContainerNode extends DataNode { super(nodeData, parent); } + private _containerType: ContainerType; + public get projectBasePath() { return this._project.uri && Uri.parse(this._project.uri).fsPath; } - public getContainerType(): string { + public getContainerType(): ContainerType { + if (this._containerType) { + return this._containerType; + } + const containerPath: string = this._nodeData.path || ""; if (containerPath.startsWith(ContainerPath.JRE)) { - return ContainerType.JRE; + this._containerType = ContainerType.JRE; } else if (containerPath.startsWith(ContainerPath.Maven)) { - return ContainerType.Maven; + this._containerType = ContainerType.Maven; } else if (containerPath.startsWith(ContainerPath.Gradle)) { - return ContainerType.Gradle; + this._containerType = ContainerType.Gradle; } else if (containerPath.startsWith(ContainerPath.ReferencedLibrary) && this._project.isUnmanagedFolder()) { // currently, we only support editing referenced libraries in unmanaged folders - return ContainerType.ReferencedLibrary; + this._containerType = ContainerType.ReferencedLibrary; + } else { + this._containerType = ContainerType.Unknown; } - return ContainerType.Unknown; + + return this._containerType; + } + + public isMavenType(): boolean { + return this._containerType === ContainerType.Maven; } protected async loadData(): Promise { @@ -70,7 +83,7 @@ export enum ContainerType { Unknown = "", } -const enum ContainerPath { +export const enum ContainerPath { JRE = "org.eclipse.jdt.launching.JRE_CONTAINER", Maven = "org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER", Gradle = "org.eclipse.buildship.core.gradleclasspathcontainer", diff --git a/src/views/dataNode.ts b/src/views/dataNode.ts index 21be07a7..200abf13 100644 --- a/src/views/dataNode.ts +++ b/src/views/dataNode.ts @@ -42,6 +42,10 @@ export abstract class DataNode extends ExplorerNode { return item; } + public getDisplayName(): string { + return this._nodeData.displayName || this._nodeData.name; + } + public get nodeData(): INodeData { return this._nodeData; } diff --git a/src/views/dependencyDataProvider.ts b/src/views/dependencyDataProvider.ts index dd0bd05b..a8b192d6 100644 --- a/src/views/dependencyDataProvider.ts +++ b/src/views/dependencyDataProvider.ts @@ -2,12 +2,13 @@ // Licensed under the MIT license. import * as _ from "lodash"; +import * as path from "path"; import { commands, Event, EventEmitter, ExtensionContext, ProviderResult, RelativePattern, TreeDataProvider, TreeItem, Uri, window, workspace, } from "vscode"; import { instrumentOperationAsVsCodeCommand, sendError } from "vscode-extension-telemetry-wrapper"; -import { contextManager } from "../../extension.bundle"; +import { ContainerNode, contextManager } from "../../extension.bundle"; import { Commands } from "../commands"; import { Context } from "../constants"; import { appendOutput, executeExportJarTask } from "../tasks/buildArtifact/BuildArtifactTaskProvider"; @@ -37,11 +38,16 @@ export class DependencyDataProvider implements TreeDataProvider { * `null` means no node is pending. */ private pendingRefreshElement: ExplorerNode | undefined | null; + /** Resolved when the first batch of progressive items arrives. */ + private _progressiveItemsReady: Promise | undefined; + private _resolveProgressiveItems: (() => void) | undefined; constructor(public readonly context: ExtensionContext) { // commands that do not send back telemetry context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, (debounce?: boolean, element?: ExplorerNode) => this.refresh(debounce, element))); + context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_INTERNAL_ADD_PROJECTS, (projectUris: string[]) => + this.addProgressiveProjects(projectUris))); context.subscriptions.push(commands.registerCommand(Commands.EXPORT_JAR_REPORT, (terminalId: string, message: string) => { appendOutput(terminalId, message); })); @@ -55,6 +61,8 @@ export class DependencyDataProvider implements TreeDataProvider { context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_OUTLINE, (uri, range) => window.showTextDocument(Uri.parse(uri), { selection: range }))); context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_BUILD_WORKSPACE, () => + commands.executeCommand(Commands.JAVA_BUILD_WORKSPACE, false /*fullCompile*/))); + context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_REBUILD_WORKSPACE, () => commands.executeCommand(Commands.JAVA_BUILD_WORKSPACE, true /*fullCompile*/))); context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_CLEAN_WORKSPACE, () => commands.executeCommand(Commands.JAVA_CLEAN_WORKSPACE))); @@ -70,13 +78,21 @@ export class DependencyDataProvider implements TreeDataProvider { commands.executeCommand(Commands.JAVA_PROJECT_CONFIGURATION_UPDATE, uris[0]); } })); - context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_REBUILD, async (node: INodeData) => { + context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_BUILD_PROJECT, async (node: INodeData) => { if (!node.uri) { sendError(new Error("Uri not available when building project")); - window.showErrorMessage("The URI of the project is not available, you can try to trigger the command 'Java: Rebuild Projects' from Command Palette."); + window.showErrorMessage("The URI of the project is not available, you can try to trigger the command 'Java: Build Project' from Command Palette."); return; } - commands.executeCommand(Commands.BUILD_PROJECT, Uri.parse(node.uri), true); + return commands.executeCommand(Commands.BUILD_PROJECT, Uri.parse(node.uri), false /*isFullBuild*/); + })); + context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_REBUILD, async (node: INodeData) => { + if (!node.uri) { + sendError(new Error("Uri not available when rebuilding project")); + window.showErrorMessage("The URI of the project is not available, you can try to trigger the command 'Java: Rebuild Project' from Command Palette."); + return; + } + return commands.executeCommand(Commands.BUILD_PROJECT, Uri.parse(node.uri), true /*isFullBuild*/); })); this.setRefreshDebounceFunc(); @@ -117,13 +133,46 @@ export class DependencyDataProvider implements TreeDataProvider { } public async getChildren(element?: ExplorerNode): Promise { + // Fast path: if root items are already populated by progressive loading + // (addProgressiveProjects), return them directly without querying the + // server, which may be blocked during long-running imports. + if (!element && this._rootItems && this._rootItems.length > 0) { + explorerNodeCache.saveNodes(this._rootItems); + return this._rootItems; + } + if (!await languageServerApiManager.ready()) { return []; } + // During progressive loading (server running but not fully ready after + // a clean workspace), don't enter getRootNodes() — its server queries + // will block for the entire import duration. Instead, keep the TreeView + // progress spinner visible by awaiting until the first progressive + // notification delivers items. + if (!element && !languageServerApiManager.isFullyReady()) { + if (!this._rootItems || this._rootItems.length === 0) { + if (!this._progressiveItemsReady) { + this._progressiveItemsReady = new Promise((resolve) => { + this._resolveProgressiveItems = resolve; + }); + } + await this._progressiveItemsReady; + } + return this._rootItems || []; + } + const children = (!this._rootItems || !element) ? await this.getRootNodes() : await element.getChildren(); + if (children && element instanceof ContainerNode) { + if (element.isMavenType()) { + children.sort((a, b) => { + return a.getDisplayName().localeCompare(b.getDisplayName()); + }); + } + } + explorerNodeCache.saveNodes(children || []); return children; } @@ -159,12 +208,74 @@ export class DependencyDataProvider implements TreeDataProvider { private doRefresh(element?: ExplorerNode): void { if (!element) { this._rootItems = undefined; + // Resolve any pending progressive await so getChildren() doesn't hang + if (this._resolveProgressiveItems) { + this._resolveProgressiveItems(); + this._resolveProgressiveItems = undefined; + this._progressiveItemsReady = undefined; + } } explorerNodeCache.removeNodeChildren(element); this._onDidChangeTreeData.fire(element); this.pendingRefreshElement = null; } + /** + * Add projects progressively from ProjectsImported notifications. + * This directly creates ProjectNode items from URIs without querying + * the JDTLS server, which may be blocked during long-running imports. + */ + public addProgressiveProjects(projectUris: string[]): void { + const folders = workspace.workspaceFolders; + // Multi-root workspaces use WorkspaceNode roots. Those roots can remain + // cached briefly after switching to a single folder, so wait for the + // full refresh rather than creating a mixed root structure. + if (!folders || folders.length !== 1 || this._rootItems?.some(root => root instanceof WorkspaceNode)) { + return; + } + + if (!this._rootItems) { + this._rootItems = []; + } + + const existingUris = new Set( + this._rootItems + .filter((n): n is ProjectNode => n instanceof ProjectNode) + .map((n) => n.uri) + .filter((uri): uri is string => Boolean(uri)) + .map(getProjectUriKey) + ); + + let added = false; + for (const uriStr of projectUris) { + const uriKey = getProjectUriKey(uriStr); + if (existingUris.has(uriKey)) { + continue; + } + // Extract project name from URI (last non-empty path segment) + const name = uriStr.replace(/\/+$/, "").split("/").pop() || "unknown"; + const nodeData: INodeData = { + name, + uri: uriStr, + kind: NodeKind.Project, + }; + this._rootItems.push(new ProjectNode(nodeData, undefined)); + existingUris.add(uriKey); + added = true; + } + + if (added) { + // Resolve the pending getChildren() promise so the TreeView + // spinner stops and items appear. + if (this._resolveProgressiveItems) { + this._resolveProgressiveItems(); + this._resolveProgressiveItems = undefined; + this._progressiveItemsReady = undefined; + } + this._onDidChangeTreeData.fire(undefined); + } + } + private async getRootNodes(): Promise { try { await explorerLock.acquireAsync(); @@ -204,3 +315,16 @@ export class DependencyDataProvider implements TreeDataProvider { } } } + +function getProjectUriKey(uriString: string): string { + const uri = Uri.parse(uriString); + if (uri.scheme !== "file") { + return uri.toString(); + } + + let fsPath = path.normalize(uri.fsPath); + if (fsPath !== path.parse(fsPath).root) { + fsPath = fsPath.replace(/[\\\/]+$/, ""); + } + return process.platform === "win32" ? fsPath.toLowerCase() : fsPath; +} diff --git a/src/views/documentSymbolNode.ts b/src/views/documentSymbolNode.ts index a6ead753..7552116e 100644 --- a/src/views/documentSymbolNode.ts +++ b/src/views/documentSymbolNode.ts @@ -28,6 +28,10 @@ export class DocumentSymbolNode extends ExplorerNode { super(parent); } + public getDisplayName(): string { + return this.symbolInfo.name; + } + public getChildren(): ExplorerNode[] | Promise { const res: ExplorerNode[] = []; if (this.symbolInfo?.children?.length) { @@ -39,7 +43,7 @@ export class DocumentSymbolNode extends ExplorerNode { } public getTreeItem(): TreeItem | Promise { - const item = new TreeItem(this.symbolInfo.name, + const item = new TreeItem(this.getDisplayName(), this.symbolInfo?.children?.length ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None); item.iconPath = this.iconPath; diff --git a/src/views/explorerNode.ts b/src/views/explorerNode.ts index c5c29092..1dcac373 100644 --- a/src/views/explorerNode.ts +++ b/src/views/explorerNode.ts @@ -33,4 +33,6 @@ export abstract class ExplorerNode { public abstract getTreeItem(): TreeItem | Promise; public abstract computeContextValue(): string | undefined; + + public abstract getDisplayName(): string; } diff --git a/src/views/packageRootNode.ts b/src/views/packageRootNode.ts index 63de2c65..01327579 100644 --- a/src/views/packageRootNode.ts +++ b/src/views/packageRootNode.ts @@ -16,6 +16,14 @@ import { NodeFactory } from "./nodeFactory"; export class PackageRootNode extends DataNode { + /** + * Resource URIs reported by the file watcher as newly created under this + * source root since the last load. Consumed on the next loadData() so the + * server can scope its filesystem refresh to only the changed subtrees. + * See https://github.com/microsoft/vscode-java-dependency/issues/914 + */ + public pendingSyncPaths: Set = new Set(); + constructor(nodeData: INodeData, parent: DataNode, protected _project: ProjectNode) { super(nodeData, parent); } @@ -25,13 +33,28 @@ export class PackageRootNode extends DataNode { } protected async loadData(): Promise { - return Jdtls.getPackageData({ - kind: NodeKind.PackageRoot, - projectUri: this._project.nodeData.uri, - rootPath: this.nodeData.path, - handlerIdentifier: this.nodeData.handlerIdentifier, - isHierarchicalView: Settings.isHierarchicalView(), - }); + let syncPaths: string[] | undefined; + if (this.pendingSyncPaths.size) { + // Snapshot and clear synchronously before the async server call so + // watcher events arriving during the await are not lost. + syncPaths = Array.from(this.pendingSyncPaths); + this.pendingSyncPaths.clear(); + } + try { + return await Jdtls.getPackageData({ + kind: NodeKind.PackageRoot, + projectUri: this._project.nodeData.uri, + rootPath: this.nodeData.path, + handlerIdentifier: this.nodeData.handlerIdentifier, + isHierarchicalView: Settings.isHierarchicalView(), + syncPaths, + }); + } catch (error) { + // Restore the snapshot so a transient server error does not drop the + // pending paths; the next refresh will retry the targeted sync. + syncPaths?.forEach((path) => this.pendingSyncPaths.add(path)); + throw error; + } } protected createChildNodeList(): ExplorerNode[] { diff --git a/test/e2e-plans/java-dep-autorefresh-targeted.yaml b/test/e2e-plans/java-dep-autorefresh-targeted.yaml new file mode 100644 index 00000000..124c8d77 --- /dev/null +++ b/test/e2e-plans/java-dep-autorefresh-targeted.yaml @@ -0,0 +1,105 @@ +# Validates the targeted (scoped) auto-refresh optimization for issue #914. +# Companion to java-dep-refresh-generated-files.yaml (which tests manual Refresh). +# +# On auto-refresh the extension passes the changed URI to the server +# (PackageParams.syncPaths); the server refreshes only the affected subtree (the +# nearest existing ancestor) instead of the whole source root, then closes the +# package root to rebuild its package-fragment list. This plan does NOT call +# java.view.package.refresh — it relies solely on the FileSystemWatcher, so it +# exercises the syncPaths path. Auto-refresh is on by default. +# +# Tree layout and verify policy are the same as the manual-Refresh plan: compact +# virtualized tree, deterministic verifyTreeItem assertions, no `verify:` on the +# file-write step (no reliable visual signal for the LLM judge). +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-autorefresh-targeted.yaml \ +# --override extensionPath= + +name: "Java Dependency — Auto-refresh surfaces a new package (targeted, #914)" +description: | + Validates the targeted (scoped) auto-refresh optimization for issue #914: a + .java file written by an external generator into a brand-new sub-package must + appear in the Java Projects view via the file-watcher auto-refresh alone (no + manual Refresh), which routes the changed URI through PackageParams.syncPaths. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + explorer.autoReveal: false + +steps: + - id: "ls-ready" + action: "waitForLanguageServer" + timeout: 180 + + # Free vertical space so the Java Projects tree is not virtualized. + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-explorer-folders" + action: "collapseSidebarSection maven" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # The source root must be expanded so a PackageRootNode exists to target. + - id: "expand-project" + action: "expandTreeItem my-app" + verify: "my-app project expanded" + + - id: "expand-source-root" + action: "expandTreeItem src/main/java" + verify: "source root src/main/java expanded" + + - id: "baseline-existing-pkg" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app" + visible: true + + # Negative baseline: the brand-new package must be ABSENT before the file is + # written, so check-new-pkg-autorefresh later observes a genuine appearance + # driven by the watcher, not a pre-existing node. + - id: "baseline-new-pkg-absent" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app.autogen" + visible: false + timeout: 5 + + # Write a file straight to disk into a brand-new sub-package. + - id: "gen-file-new-pkg" + action: "insertLineInFile src/main/java/com/mycompany/app/autogen/Gen914AutoNewPkg.java 1 package com.mycompany.app.autogen;\n\npublic class Gen914AutoNewPkg {\n}\n" + + - id: "dismiss-overlay" + action: "pressKey Escape" + + # Let the file watcher + debounced auto-refresh fire. No manual Refresh. + - id: "wait-for-auto-refresh" + action: "wait 6 seconds" + + - id: "reexpand-source-root" + action: "expandTreeItem src/main/java" + + # The brand-new package appears via auto-refresh alone. + - id: "check-new-pkg-autorefresh" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app.autogen" + visible: true + timeout: 20 diff --git a/test/e2e-plans/java-dep-build-lifecycle.yaml b/test/e2e-plans/java-dep-build-lifecycle.yaml new file mode 100644 index 00000000..b0f6df66 --- /dev/null +++ b/test/e2e-plans/java-dep-build-lifecycle.yaml @@ -0,0 +1,213 @@ +# Test Plan: Java Dependency — Build Lifecycle +# +# Covers the project build / rebuild / reload commands contributed by +# vscode-java-dependency. Each command is invoked through the documented +# entry point (view title-bar action, overflow menu, project context menu, +# or editor title-bar action) and verified by waiting for the Java Language +# Server to return to the Ready state. +# +# Commands exercised: +# - java.project.build.workspace (Build All — title-bar tools icon) +# - java.project.rebuild.workspace (Rebuild All — overflow menu) +# - java.project.build.project (Build Project — project context menu) +# - java.project.rebuild (Rebuild Project — project context menu) +# - java.project.reloadProjectFromActiveFile (Reload Project — pom.xml editor title) +# - java.project.update (Reload Project — Maven submenu on project context menu) +# - java.project.clean.workspace (Clean Workspace — view-title overflow; dialog cancelled to avoid VS Code reload) +# +# Verification strategy +# ───────────────────── +# Build commands have no visible editor side-effect — they trigger a +# background compilation whose progress is reflected only in the status bar +# (and briefly in the Java Language Server progress notifications). For each +# build / rebuild, we run the command and then call `waitForLanguageServer`, +# which polls the status bar until it returns to "Java: Ready" and the +# post-Ready "Building - X%" phase has settled. A non-fatal command is +# enough for the step to pass — the test asserts that the command does not +# leave the LS hung or in an error state. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-build-lifecycle.yaml --vsix + +name: "Java Dependency — Build Lifecycle" +description: | + Tests the build / rebuild / reload commands contributed by the Java + Project Manager. Each command is verified by waiting for the Java + Language Server to return to the Ready state after the command runs. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 240 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup ── + - id: "ls-ready" + action: "waitForLanguageServer" + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + # Collapse the MAVEN workspace-folder pane so JAVA PROJECTS gets the full + # vertical space. OUTLINE and TIMELINE are collapsed by default in fresh + # sessions, so no explicit step is needed. + - id: "collapse-maven-pane" + action: "collapseSidebarSection maven" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Test 1: Build All (incremental) — Java Projects view title-bar button ── + # The "Build All" toolbar action ($(tools) icon) is contributed under + # view/title group navigation@30 in package.json. Clicking it through the + # UI exercises the full button-rendering + when-clause + command-dispatch + # chain — unlike executeVSCodeCommand, which would only hit the command + # bus directly. + - id: "trigger-build-all" + action: 'clickViewTitleAction "Java Projects" "Build All"' + + - id: "wait-build-all" + action: "waitForLanguageServer" + timeout: 120 + + # ── Test 2: Rebuild All (full compile) — Java Projects overflow menu ── + # "Rebuild All" lives in view/title group overflow_20@5, so it is reached + # via the "Views and More Actions..." (...) overflow menu. The + # clickViewTitleAction helper automatically falls through from the direct + # button path to the overflow menu when the action is not present in the + # toolbar's navigation group. + - id: "trigger-rebuild-all" + action: 'clickViewTitleAction "Java Projects" "Rebuild All"' + + - id: "wait-rebuild-all" + action: "waitForLanguageServer" + timeout: 180 + + # ── Test 3: Build Project (per-project, via context menu) ── + # The `java.project.build.project` command requires a project URI, so it + # is gated behind the project context-menu in package.json (8_execution@5 + # when viewItem matches /java:project.*\+java.*\+uri/). Invoke it via the + # project node context menu — the menu surface that real users hit. + - id: "click-project-build" + action: "click my-app tree item" + waitBefore: 1 + + - id: "context-build-project" + action: "contextMenu my-app Build Project" + # No `verify:` — context-menu click has no immediate visible effect + # beyond closing the menu; waitForLanguageServer below is the ground + # truth that the build executed and the LS settled. + + - id: "wait-build-project" + action: "waitForLanguageServer" + timeout: 120 + + # ── Test 4: Rebuild Project (per-project, via context menu) ── + - id: "click-project-rebuild" + action: "click my-app tree item" + waitBefore: 1 + + - id: "context-rebuild-project" + action: "contextMenu my-app Rebuild Project" + + - id: "wait-rebuild-project" + action: "waitForLanguageServer" + timeout: 180 + + # ── Test 5: Reload Project (editor title-bar action on pom.xml) ── + # `java.project.reloadProjectFromActiveFile` is contributed in editor/title + # group navigation when both `java:reloadProjectActive` and `javaLSReady` + # are true. The `java:reloadProjectActive` key is only set after the + # project file (pom.xml / build.gradle) has been modified — opening an + # unchanged pom.xml is NOT enough to make the $(sync) button appear. + # + # To exercise the real UI flow: + # 1. Open pom.xml. + # 2. Type a space at the cursor → file becomes dirty. + # 3. Save → JDT.LS detects the build file change and sets + # `java:reloadProjectActive`, which renders the $(sync) "Reload + # Java Project" button in the editor title bar. + # 4. Click the title-bar button → reload kicks off. + # 5. waitForLanguageServer confirms the reload completed. + # 6. Undo + save restores pom.xml to its original content so the + # fixture is left clean for subsequent runs. + # ── Test 5: Reload Project From Active File ── + # `java.project.reloadProjectFromActiveFile` is contributed to editor/title + # group navigation only when `java:reloadProjectActive && javaLSReady` are + # both true. The `java:reloadProjectActive` key is set by redhat.java when + # JDT.LS detects an out-of-date project descriptor — but that signal is + # racy and inconsistent for synthetic changes (trivial whitespace edits + # often get absorbed without flipping the key, and a substantive edit + # would risk corrupting the fixture pom.xml). For deterministic CI + # behaviour this step therefore invokes the command id directly through + # the keybinding-bridge path. The fact that the command exists and runs + # without breaking the language server is still meaningful coverage, + # complementing the UI-driven tests above. + - id: "open-pom" + action: "open file pom.xml" + waitBefore: 3 + + - id: "trigger-reload-project" + action: "executeVSCodeCommand java.project.reloadProjectFromActiveFile" + + - id: "wait-reload-project" + action: "waitForLanguageServer" + timeout: 180 + + # ── Test 6: Reload Project (Maven submenu on project context menu) ── + # `java.project.update` lives in the `javaProject.maven` submenu under the + # project context menu's `9_configuration@10` group. Real users right-click + # the Maven project node → hover the "Maven" submenu → click "Reload + # Project". This is the only UI surface for this command (no command + # palette entry, no toolbar button). + - id: "close-pom-editors" + action: "run command View: Close All Editors" + + - id: "focus-java-projects-reload" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + - id: "click-project-update" + action: "click my-app tree item" + waitBefore: 1 + + - id: "context-update-maven" + action: 'contextMenuSubmenu my-app Maven "Reload Project"' + + - id: "wait-update-project" + action: "waitForLanguageServer" + timeout: 180 + + # ── Test 7: Clean Workspace (overflow menu, dialog cancelled if shown) ── + # `java.project.clean.workspace` is contributed to the Java Projects view + # title-bar `overflow_20@10` group. When clicked it forwards to JDT.LS's + # `java.clean.workspace`. Depending on the redhat.java / JDT.LS version + # this may or may not raise a modal warning dialog ("…delete workspace + # cache and restart?") before doing the work. We use a *tolerant* dialog + # cancel (`tryClickDialogButton`) so the step passes whether or not the + # dialog appears — when it does appear we cancel to avoid the destructive + # VS Code reload; when it does not we proceed straight to the LS settle + # check. The primary coverage signal is the overflow-menu mount + click, + # which `trigger-clean-workspace` already exercises with a deterministic + # `clickViewTitleAction`. + - id: "trigger-clean-workspace" + action: 'clickViewTitleAction "Java Projects" "Clean Workspace"' + + - id: "cancel-clean-dialog" + action: "tryClickDialogButton Cancel" + # No `verify:` — tolerant action: clicks Cancel if dialog appears, else + # silently no-ops. `trigger-clean-workspace` is the deterministic signal. + + - id: "wait-clean-settle" + action: "waitForLanguageServer" + timeout: 60 diff --git a/test/e2e-plans/java-dep-classpath.yaml b/test/e2e-plans/java-dep-classpath.yaml new file mode 100644 index 00000000..cd3e7d4a --- /dev/null +++ b/test/e2e-plans/java-dep-classpath.yaml @@ -0,0 +1,290 @@ +# Test Plan: Java Dependency — Classpath / Referenced Libraries +# +# Covers the referenced-library management commands contributed by +# vscode-java-dependency. These commands are only active for invisible +# (unmanaged-folder) projects — Maven / Gradle projects manage their +# classpath through pom.xml / build.gradle and do NOT expose the +# Referenced Libraries container's inline actions. +# +# Commands exercised: +# - java.project.refreshLibraries (Refresh — inline title icon on Referenced Libraries) +# - java.project.addLibraries (Add Jar Libraries… — inline `+` icon) +# - java.project.removeLibrary (Remove from Project Classpath — invoked +# by command id in both `include`-removal +# and `exclude`-addition modes) +# - java.project.addLibraryFolders (Add Library Folders… — Alt-variant of `+` icon; +# no plain-click UI affordance, invoked via command path) +# +# Verification strategy +# ───────────────────── +# `referencedLibraries` is a workspace setting (`java.project.referencedLibraries`) +# whose include/exclude globs are reflected live in the JAVA PROJECTS tree under +# the "Referenced Libraries" container. Each command we exercise either inserts +# a new include glob (addLibraries / addLibraryFolders), removes/excludes one +# (removeLibrary), or re-reads the setting from disk (refreshLibraries). We +# therefore assert state by name-matching jar leaves in the tree with the +# deterministic `verifyTreeItem` block — both presence (`visible: true`, the +# default) and absence (`visible: false`). +# +# Substring matching for jar leaves +# ───────────────────────────────── +# Each jar leaf is rendered as ".jar ", +# so the accessible name carries the full resolved path. We deliberately omit +# `exact: true` on jar `verifyTreeItem` blocks — the driver falls back to +# substring matching, which is exactly what we need to locate a leaf by its +# basename. The project root (`invisible`) keeps `exact: true` because no +# description is appended to project-level rows. +# +# Fixture layout (test/invisible) +# ─────────────────────────────── +# .vscode/settings.json java.project.referencedLibraries = ["lib/**/*.jar"] +# lib/simple.jar already attached at startup via the include glob +# libSource/simple.jar existing companion file (unrelated to this plan) +# extraJars/extra-a.jar added/removed via the UI in cycles 2 + 3 +# extraJars/extra-b.jar surfaced by cycle 4's folder-add (extra-a stays excluded) +# +# Native file/folder pickers are intercepted by `setup.mockOpenDialog` — the +# first entry is consumed by `addLibraries`, the second by `addLibraryFolders`. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-classpath.yaml --vsix + +name: "Java Dependency — Classpath / Referenced Libraries" +description: | + Tests the four referenced-library commands on an invisible (unmanaged) + Java project: refreshLibraries, addLibraries, removeLibrary, and + addLibraryFolders. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../invisible" + timeout: 240 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + # Native file/folder pickers are mocked at the Electron `dialog.showOpenDialog` + # layer, but VS Code's smoke-test driver suppresses the native dialog and + # falls back to its internal quick-pick `simpleFileDialog`. The mock therefore + # never fires — instead we drive the simple dialog with `fillQuickInput`, + # typing the resolved jar / folder path and pressing Enter. The mockOpenDialog + # block below is kept as a behavioural reference (and harmless no-op). + mockOpenDialog: + - ["~/extraJars/extra-a.jar"] + - ["~/extraJars"] + +steps: + # ── Setup: activate the Java extension, wait for LS, clear sidebar ── + # Invisible projects do not auto-activate redhat.java the way Maven / + # Gradle workspaces do (those activate via the pom.xml / build.gradle + # workspaceContains contributions). Open `src/App.java` first so the + # Language Server actually starts — otherwise `waitForLanguageServer` + # times out and the Java Projects view never registers. + - id: "open-bootstrap-file" + action: "open file src/App.java" + + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + # Single-folder workspaces don't have a collapsible aria-level=1 workspace + # root inside `.explorer-folders-view`, so `collapseWorkspaceRoot` is a + # no-op here. Instead collapse the whole `invisible` pane in the EXPLORER + # view container — otherwise its top-level entries (.vscode/extraJars/ + # lib/libSource/src) push the JAVA PROJECTS pane down so far that the + # virtualised list does not render the jar leaves and `verifyTreeItem` + # times out hunting an off-screen node. + - id: "collapse-explorer-pane" + action: "collapseSidebarSection invisible" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 5 seconds" + + # Invisible-project root takes the worktree folder name (`invisible`). + - id: "verify-project-node" + action: "wait 1 seconds" + # No `verify:` — state-check step; `verifyTreeItem` is authoritative. + verifyTreeItem: + name: "invisible" + exact: true + timeout: 15 + + - id: "expand-project" + action: "expandTreeItem invisible" + waitBefore: 2 + + - id: "expand-referenced-libraries" + action: "expandTreeItem Referenced Libraries" + waitBefore: 2 + + # Baseline: lib/simple.jar matches the default include glob `lib/**/*.jar`. + # No `exact:` — the jar row's accessible name includes a description with the + # resolved jar path; substring match on the basename is sufficient and stable. + - id: "verify-baseline-simple-jar" + action: "wait 1 seconds" + verifyTreeItem: + name: "simple.jar" + timeout: 15 + + # ── Cycle 1: java.project.refreshLibraries ── + # Click the inline `$(refresh)` icon on the Referenced Libraries container. + # The aria-label is the localised command title — here "Refresh". The action + # is idempotent: nothing on disk changed, so simple.jar must remain attached. + - id: "click-refresh-libraries" + action: 'clickTreeItemAction "Referenced Libraries" "Refresh"' + + - id: "wait-after-refresh" + action: "wait 3 seconds" + + - id: "verify-refresh-stable" + action: "wait 1 seconds" + verifyTreeItem: + name: "simple.jar" + timeout: 15 + + # ── Cycle 2: java.project.addLibraries ── + # Click the inline `$(add)` icon on the Referenced Libraries container. + # aria-label = "Add Jar Libraries to Project Classpath...". Partial match + # on "Add Jar Libraries" is enough — the driver does `aria-label.includes()`. + # In smoke-test mode VS Code substitutes its quick-pick `simpleFileDialog` + # for the native picker, so we type the resolved jar path into the input + # bar and press Enter via `fillQuickInput`. The command then appends the + # new path to `java.project.referencedLibraries.include`. + - id: "click-add-libraries" + action: 'clickTreeItemAction "Referenced Libraries" "Add Jar Libraries"' + + - id: "type-add-libraries-path" + action: "fillQuickInput ${workspaceFolder}/extraJars/extra-a.jar" + + - id: "wait-after-add" + action: "wait 5 seconds" + + - id: "verify-extra-a-added" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-a.jar" + timeout: 20 + + # ── Cycle 3: java.project.removeLibrary ── + # Invoke the command directly. The inline `$(remove)` icon on the jar leaf + # is rendered only on row hover and its `` hit-target + # is narrower than the wrapping `
  • `, so the centre-of- + # actionItem click that `clickTreeItemAction` performs lands consistently on + # extension-contributed view-title icons (`+`, `$(refresh)`) but not on the + # jar-leaf `–`. Driving the command by id sidesteps the hit-target gap and + # exercises the same handler — `removeLibrary(Uri.parse(node.uri).fsPath)`. + # + # We pass a `{uri}` payload as JSON. JSON.parse runs before + # resolveWorkspacePlaceholders, so `${workspaceFolderUri}` here is a literal + # substring inside a valid JSON string. autotest substitutes it with a + # correctly-formed `file:///...` URI for the current OS (drive-letter form + # on Windows, plain absolute path on POSIX), so the same template round-trips + # through `Uri.parse(...).fsPath` and `workspace.asRelativePath(...)` to + # match the include entry that `java.project.addLibraries` wrote in cycle 2. + - id: "invoke-remove-extra-a" + action: 'executeVSCodeCommand java.project.removeLibrary {"uri":"${workspaceFolderUri}/extraJars/extra-a.jar"}' + + - id: "wait-after-remove" + action: "wait 5 seconds" + + - id: "verify-extra-a-gone" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-a.jar" + visible: false + timeout: 20 + + - id: "verify-simple-still-present" + action: "wait 1 seconds" + verifyTreeItem: + name: "simple.jar" + timeout: 15 + + # ── Cycle 4: java.project.addLibraryFolders ── + # The `addLibraryFolders` command has no plain-click affordance — it is + # only bound as the `alt:` variant of the `+` icon (Alt-click). autotest + # 0.7.x has no Alt-modifier tree-item action, so we invoke the command + # directly. The same simpleFileDialog appears in folder-pick mode; we + # type the resolved folder path and press Enter. The command appends + # `extraJars/**/*.jar` (the folder glob) to the include list. + # + # Because extra-a.jar is now in the exclude list, only extra-b.jar + # surfaces from the folder-add — making this a sharp differentiation + # test against cycle 3's removeLibrary outcome. + - id: "invoke-add-library-folders" + action: "executeVSCodeCommand java.project.addLibraryFolders" + + # In folder-pick mode the simpleFileDialog treats Enter on a folder as + # "navigate into", so `fillQuickInput` types the path AND opens the folder. + # The "Select Library Folders" button is the explicit confirmation + # affordance; clicking it is what actually returns the URI to the command. + - id: "type-add-folder-path" + action: "fillQuickInput ${workspaceFolder}/extraJars" + + - id: "confirm-folder-select" + action: "tryClickButton Select Library Folders" + + - id: "wait-after-add-folder" + action: "wait 5 seconds" + + - id: "verify-extra-b-via-folder" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-b.jar" + timeout: 20 + + # Sanity-check that extra-a.jar is back too — `removeLibrary` in cycle 3 + # only stripped the explicit `extraJars/extra-a.jar` include entry; it did + # NOT add an exclude. The folder glob `extraJars/**/*.jar` therefore + # re-attaches both jars. This is the exact behavioural contract documented + # in libraryController.ts (the `if (removedPaths.length === 0)` branch + # only fires for glob-matched jars). + - id: "verify-extra-a-reattached-via-glob" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-a.jar" + timeout: 15 + + # ── Cycle 5: java.project.removeLibrary (exclude code path) ── + # extra-a.jar is now attached via the folder glob, NOT an explicit include. + # Removing it now exercises the second branch of removeLibrary: the include + # list has no exact match for the relative path, so the handler appends + # `extraJars/extra-a.jar` to `referencedLibraries.exclude`. The folder + # glob still attaches extra-b.jar, so it must stay visible while extra-a + # disappears — proving the exclude path works independently of the include + # removal already covered in cycle 3. + - id: "invoke-remove-extra-a-glob" + action: 'executeVSCodeCommand java.project.removeLibrary {"uri":"${workspaceFolderUri}/extraJars/extra-a.jar"}' + + - id: "wait-after-glob-remove" + action: "wait 5 seconds" + + - id: "verify-extra-a-excluded" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-a.jar" + visible: false + timeout: 20 + + - id: "verify-extra-b-still-via-glob" + action: "wait 1 seconds" + verifyTreeItem: + name: "extra-b.jar" + timeout: 15 diff --git a/test/e2e-plans/java-dep-copy-paths.yaml b/test/e2e-plans/java-dep-copy-paths.yaml new file mode 100644 index 00000000..7fd7c3cd --- /dev/null +++ b/test/e2e-plans/java-dep-copy-paths.yaml @@ -0,0 +1,195 @@ +# Test Plan: Java Dependency — Copy File / Relative Paths +# +# Covers two clipboard commands contributed against the Java Projects view: +# - java.view.package.copyFilePath (Copy Path) +# - java.view.package.copyRelativeFilePath (Copy Relative Path) +# +# Why a dedicated plan +# ──────────────────── +# These two commands have **no on-screen side effect at all** — they don't +# open a dialog, write a file, change the tree, or post a notification. +# The only observable consequence is what ends up on the OS clipboard. +# Verifying them therefore requires an autotest clipboard primitive +# (writeClipboard / readClipboard / verifyClipboard) added in 0.7.15. +# +# Both handlers (dependencyExplorer.ts:159 and :165) are thin wrappers +# around VS Code's built-in `copyFilePath` / `copyRelativeFilePath`: +# +# instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH, +# (node?: DataNode) => { +# const cmdNode = getCmdNode(this._dependencyViewer.selection, node); +# if (cmdNode?.uri) { +# commands.executeCommand("copyFilePath", Uri.parse(cmdNode.uri)); +# } +# }) +# +# So the values landing on the clipboard are whatever VS Code's built-ins +# write — i.e. the URI's fsPath (absolute, OS-native separators) and the +# workspace-relative path (no leading slash). +# +# Invocation pattern (same as delete-permanent.yaml) +# ────────────────────────────────────────────────── +# Both commands accept a `node?: DataNode` parameter and fall back to +# the current tree selection via getCmdNode (explorerCommands/utility.ts:38). +# DataNode is a class instance, not a POJO, so passing a synthetic node +# from YAML would crash. Selection fallback is the only viable smoke-test +# path: open a file via link-with-editor (auto-selects in the tree) → +# click the tree row to re-assert selection after focus changes → +# invoke the command by id. +# +# Cross-OS path separator handling +# ──────────────────────────────── +# Windows fsPaths use `\` and POSIX uses `/`. The assertions therefore +# combine three orthogonal checks per command: +# - `contains: "App.java"` — leaf filename, identical on every OS +# - `matches: regex` — accepts both separators between segments +# - `notContains: ` — proves the clipboard was overwritten +# (we seed a sentinel before each command) +# +# A pure `exact:` match would force a per-OS conditional plan; the regex +# approach keeps a single plan that's portable Linux ↔ Windows ↔ macOS. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-copy-paths.yaml --vsix + +name: "Java Dependency — Copy File / Relative Paths" +description: | + Exercises java.view.package.copyFilePath and java.view.package.copyRelativeFilePath + on a Maven-project source file. Seeds a clipboard sentinel before each command, + invokes the command by id (using the current tree selection), and verifies the + resulting clipboard text via path-shape regex + filename containment + + sentinel-overwritten check. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup: wait for LS, free sidebar space, focus Java Projects ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Reveal & select App.java via link-with-editor ── + # Same pattern as java-dep-delete-permanent.yaml: opening the file + # makes link-with-editor reveal+select the tree node deterministically, + # which is more reliable than chained expandTreeItem on the virtualised + # tree on 1024x768 CI displays. + - id: "open-target-file" + action: "open file App.java" + waitBefore: 2 + + - id: "collapse-workspace-root-2" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-2" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 2 + + # Click the App tree row to assert it as the active selection. The Java + # Projects view labels source files by class name (no `.java` suffix — + # the leaf row reads "App"), and a default substring `click App tree + # item` would also match the project node "my-app" first (case-insensitive + # substring), silently selecting the project — whose URI is the workspace + # root, not the file. We use the `exact` modifier (autotest ≥ 0.7.16) so + # only the leaf row labeled exactly "App" matches. + - id: "select-app" + action: "click App tree item exact" + waitBefore: 1 + + # ── Cycle 1: java.view.package.copyFilePath (absolute path) ── + # Sentinel proves the clipboard was actually written — without it, a + # silently-no-op command would pass if the OS clipboard happened to + # already contain "App.java" from any earlier action on the host. + - id: "seed-clipboard-absolute" + action: "writeClipboard __SENTINEL_BEFORE_COPY_FILE_PATH__" + + - id: "invoke-copy-file-path" + action: "executeVSCodeCommand java.view.package.copyFilePath" + waitBefore: 1 + + # Verify the clipboard contents post-action. + # + # • `contains: "App.java"` — the leaf filename is identical on every OS + # • `matches: ...` — accepts either `\` (Windows) or `/` (POSIX) between + # path segments, and asserts the URL-decoded fsPath structure + # `maven/src/main/java/com/mycompany/app/App.java`. The `[\\\\/]` + # escapes to a literal `[\/]` character class in the compiled regex. + # • `notContains: ` — proves the seed was overwritten and the + # command isn't silently no-op'ing into a stale clipboard. + - id: "verify-absolute-path" + action: "wait 1 seconds" + verifyClipboard: + contains: "App.java" + matches: "maven[\\\\/]src[\\\\/]main[\\\\/]java[\\\\/]com[\\\\/]mycompany[\\\\/]app[\\\\/]App\\.java$" + notContains: "__SENTINEL_BEFORE_COPY_FILE_PATH__" + timeout: 10 + + # ── Cycle 2: java.view.package.copyRelativeFilePath ── + # The selection persists across the previous command, so no re-click. + # A fresh sentinel is still needed — the cycle-1 clipboard now contains + # the absolute path, which would trivially satisfy any leaf-only check. + # + # Cross-platform note: VS Code's built-in `copyRelativeFilePath` computes + # `path.relative(workspaceFolderUri, fileUri)` and falls back to the + # absolute fsPath when the file URI isn't a member of any workspace + # folder. On Windows the URI we pass — `Uri.parse(cmdNode.uri)` from + # JDT.LS — can differ from VS Code's registered workspace folder URI + # in drive-letter case or percent-encoding, so the membership test + # fails and we get the absolute path back. On POSIX the URIs match and + # the relative form is produced. The assertions below tolerate both: + # they prove the command fired and overwrote the sentinel with a + # well-formed path ending in the expected package + class layout, but + # do not require the leading-`src` shape that only POSIX produces. + - id: "seed-clipboard-relative" + action: "writeClipboard __SENTINEL_BEFORE_COPY_RELATIVE_FILE_PATH__" + + - id: "invoke-copy-relative-file-path" + action: "executeVSCodeCommand java.view.package.copyRelativeFilePath" + waitBefore: 1 + + # Verify the clipboard after copyRelativeFilePath. + # + # • `contains: "App.java"` — leaf filename appears (OS-independent) + # • `matches: ...` — same path-suffix shape as the absolute assertion + # above. Anchored to `$` so it matches whether the path is the + # POSIX relative form `src/main/java/.../App.java` (single match + # of the suffix) or the Windows absolute fallback + # `C:\...\maven\src\main\java\.../App.java` (suffix at end). + # • `notContains: ` — proves the seed was overwritten, + # which is the strongest signal that the wrapper command actually + # forwarded to the built-in (rather than silently no-op'ing on a + # missing selection). + - id: "verify-relative-path" + action: "wait 1 seconds" + verifyClipboard: + contains: "App.java" + matches: "src[\\\\/]main[\\\\/]java[\\\\/]com[\\\\/]mycompany[\\\\/]app[\\\\/]App\\.java$" + notContains: "__SENTINEL_BEFORE_COPY_RELATIVE_FILE_PATH__" + timeout: 10 diff --git a/test/e2e-plans/java-dep-delete-permanent.yaml b/test/e2e-plans/java-dep-delete-permanent.yaml new file mode 100644 index 00000000..8089ede7 --- /dev/null +++ b/test/e2e-plans/java-dep-delete-permanent.yaml @@ -0,0 +1,144 @@ +# Test Plan: Java Dependency — Permanent Delete +# +# Covers java.view.package.deleteFilePermanently (the "shift+delete" / +# non-trash branch of file removal). The companion command +# java.view.package.moveFileToTrash is already covered by +# java-dep-file-operations.yaml. +# +# Why this is a separate plan +# ─────────────────────────── +# The permanent-delete command has no plain-click UI affordance on regular +# local files: the JAVA PROJECTS context-menu entry (package.json:812-820) +# and the `delete` keybinding (package.json:485-490) are both gated on +# `!explorerResourceMoveableToTrash`, so files in `test/maven` only ever +# see "Delete" (move-to-trash). We therefore invoke the command directly +# via id and rely on tree selection to supply the target node — the same +# pattern the classpath plan uses for `removeLibrary`. +# +# The confirmation dialog also differs from moveFileToTrash: the prompt +# says "permanently delete" instead of "delete", and the action button is +# labelled "Delete" instead of "Move to Recycle Bin" (see +# src/explorerCommands/delete.ts line 17 + getInformationMessage). +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-delete-permanent.yaml --vsix + +name: "Java Dependency — Permanent Delete" +description: | + Tests the java.view.package.deleteFilePermanently command on a regular + Maven-project file. Invokes the command by id (no UI affordance on local + files), confirms the "permanently delete" dialog, and verifies the file + is gone from disk and from the Java Projects tree. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup: wait for LS, free sidebar space, focus Java Projects ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Reveal App1.java via link-with-editor, then select it ── + # Opening the file makes link-with-editor expand the tree path and + # reveal+select App1 deterministically — much more reliable than + # manual expandTreeItem chains on the virtualised tree. + - id: "open-target-file" + action: "open file App1.java" + waitBefore: 2 + + - id: "collapse-workspace-root-2" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-2" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 2 + + # Click the tree item to guarantee it's the active selection — getCmdNode + # (explorerCommands/utility.ts:38) falls back to `selectedNodes[0]` when + # the command is invoked without a node argument. Linking-with-editor + # already auto-selected App1 when the file was opened, but clicking + # re-asserts the selection deterministically after the focus-java-projects + # round trip. + # + # We intentionally do NOT verify the App1 tree row here. On 1024x768 CI + # displays the row gets virtualised out of view in the brief window + # between `open file` and the click, and an inView:"Java Projects" + # verifyTreeItem then times out — even though the underlying selection + # is set correctly (proven by the subsequent delete succeeding). The + # post-delete `verify-file-gone` + `verify-tree-item-gone` block is the + # authoritative ground truth for whether the right node was targeted. + - id: "select-app1" + action: "click App1 tree item" + waitBefore: 1 + + # ── Invoke java.view.package.deleteFilePermanently ── + # The handler at views/dependencyExplorer.ts:177 takes `node?: DataNode`. + # With no node arg, getCmdNode uses the current selection (set by the + # `click App1 tree item` step above). DataNode is a class instance with + # methods (.getChildren()) so passing a POJO would crash — selection + # fallback is the only viable path from a smoke-test. + - id: "invoke-delete-permanently" + action: "executeVSCodeCommand java.view.package.deleteFilePermanently" + + # `expectConfirmDialog` waits for the dialog and clicks the first + # recognized confirm button (autotest knows "Delete" is one of them, see + # dialogOperations.ts:16). It's the strict variant — throws if no dialog + # appears, surfacing a silently-failed command invocation immediately + # instead of 15s later when verifyFile times out. + - id: "confirm-delete" + action: "expectConfirmDialog" + + - id: "wait-after-delete" + action: "wait 5 seconds" + + # ── Verify deletion on disk AND in the tree ── + # The disk check is the strongest signal: useTrash=false routes through + # workspace.fs.delete with the OS-level unlink, so a passing verifyFile + # exists:false proves the permanent-delete path actually fired (rather + # than silently downgrading to a no-op or moving to trash). + - id: "verify-file-gone" + action: "wait 1 seconds" + verifyFile: + path: "${workspaceFolder}/src/main/java/com/mycompany/app1/App1.java" + exists: false + timeout: 15 + + - id: "verify-tree-item-gone" + action: "wait 1 seconds" + # No `verify:` — verifyTreeItem is authoritative. + verifyTreeItem: + name: "App1" + exact: true + visible: false + inView: "Java Projects" + timeout: 15 diff --git a/test/e2e-plans/java-dep-export-jar.yaml b/test/e2e-plans/java-dep-export-jar.yaml new file mode 100644 index 00000000..713eb926 --- /dev/null +++ b/test/e2e-plans/java-dep-export-jar.yaml @@ -0,0 +1,164 @@ +# Test Plan: Java Dependency — Export Jar +# +# Covers java.view.package.exportJar — the multi-step wizard that builds a +# runnable jar from a Java project. The command is contributed both as the +# title-bar `$(export)` icon on the JAVA PROJECTS workspace-root node +# (package.json:858-861, group=inline) and as a context-menu entry, but we +# invoke it directly by id: the inline icon is rendered against the +# `java:workspace` viewItem (not the Maven project node `my-app`), which +# is fragile to locate by name, and ResolveJavaProject auto-resolves when +# there's exactly one project in the workspace — so direct invocation +# bypasses one wizard step that's not the command's responsibility. +# +# Wizard step machine (BuildArtifactTaskProvider.ts:284 `createJarFile`): +# 1. ResolveJavaProject → auto when single-project; quick-pick otherwise +# 2. ResolveMainClass → quick-pick of main classes + "" +# 3. GenerateJar +# a. generateClasspaths → multi-select quick-pick if >1 dependency item +# b. showSaveDialog → only if outputPath === "" (skipped when +# java.project.exportJar.targetPath is set +# to a non-empty value; we set it via a +# user-level `settings:` block to keep the +# output filename deterministic — see the +# setup section below for why user-level +# and not workspaceSettings) +# c. Jdtls.exportJar → writes the jar file +# +# Verification strategy +# ───────────────────── +# The jar is written to a known absolute path inside the workspace +# (`output.jar`). We assert with `verifyFile exists: true` — the strongest +# possible signal that the full wizard completed end-to-end, not just that +# the command was dispatched. The Jdtls export runs in a hidden Pseudoterminal +# (BuildArtifactTaskProvider line 91: `presentationOptions.reveal = Never`), +# so there is no terminal text to inspect; the file on disk is the only +# unambiguous post-condition. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-export-jar.yaml --vsix + +name: "Java Dependency — Export Jar" +description: | + Exercises the multi-step Export Jar wizard end-to-end on the maven + fixture: triggers the command, picks the main class, accepts the default + classpath element selection, and verifies that the resulting jar file + exists at the configured target path. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + # Bumped above the standard 180s — the wizard runs a full workspace build + # (await buildWorkspace() in executeExportJarTask) before the first + # quick-pick appears, which on a cold JDT-LS warmup commonly takes 60-90s. + timeout: 360 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + # Pinning java.project.exportJar.targetPath to an absolute deterministic + # path bypasses the showSaveDialog branch in GenerateJarExecutor + # (BuildArtifactTaskProvider lines 240-244 short-circuit only when + # outputPath === ""), and lets the verifyFile assertion target a stable + # location regardless of how the fixture's worktree is named. + # + # We use user-level `settings:` (not `workspaceSettings:`) because + # autotest's workspaceSettings merge uses JSON.parse on the existing + # `.vscode/settings.json`, and the maven fixture's settings.json + # contains JSONC `//` comments which fail JSON.parse. User settings + # are written fresh each run (user-data-dir is wiped on launch) so + # there is no JSONC merge hazard. The Settings.getExportJarTargetPath + # config read is unscoped, so user-level setting takes effect identically. + java.project.exportJar.targetPath: "${workspaceFolder}/output.jar" + +steps: + # ── Setup: wait for LS, free sidebar space, focus Java Projects ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Trigger the Export Jar wizard ── + # Direct command invocation avoids the brittle inline-icon-on-workspace- + # node click path (the `$(export)` icon is contributed against viewItem + # `java:workspace`, not against the Maven project node `my-app`, and + # locating workspace-level inline icons in autotest is fragile). + # ResolveJavaProject auto-resolves for single-project workspaces. + - id: "invoke-export-jar" + action: "executeVSCodeCommand java.view.package.exportJar" + + # The wizard first triggers a full workspace build (await buildWorkspace() + # in executeExportJarTask) before any UI appears. On a cold JDT-LS this + # typically takes 30-60s; the Jdtls.getMainClasses fetch then needs + # another 2-5s before the first quick-pick is shown. Wait generously. + - id: "wait-build-complete" + action: "wait 60 seconds" + + # ── Step 2: pick the main class ── + # The maven fixture has a single class with a `public static void main` + # entry point: com.mycompany.app.App. App1 has no main, so the only + # quick-pick options are "App" and "". We pick "App" + # explicitly so the resulting jar is runnable. + - id: "pick-main-class" + action: "select App option" + # No `verify:` — selectPaletteOption is the action and verification in + # one. The quick-pick closes on selection; the AFTER screenshot may + # already show the next quick-pick (classpath elements), which a + # strict LLM could mis-read as "App selection was lost". + + - id: "wait-after-main-class" + action: "wait 5 seconds" + + # ── Step 3a: accept the pre-selected classpath elements ── + # GenerateJarExecutor.generateClasspaths builds a list of runtime / test + # output folders + dependency artifacts, pre-selects everything tagged + # `runtime`, and shows a multi-select QuickPick. For the maven fixture + # this includes target/classes plus any resolved JUnit jars under test + # scope. The pre-selection is the sane default — accepting it gives a + # runnable jar without needing to compute which items to check. + # + # `confirmQuickInput` presses Enter on the open quick-pick widget without + # typing anything, which leaves selections untouched and submits. + - id: "accept-classpath-elements" + action: "confirmQuickInput" + + # ── Step 3c: wait for Jdtls to generate the jar ── + # Jdtls.exportJar writes the jar via a JDT LSP request. The custom + # pseudoterminal stays hidden (presentationOptions.reveal=Never), so + # there is no terminal-text signal — we just wait long enough for the + # filesystem write to settle. + - id: "wait-jar-generated" + action: "wait 30 seconds" + + # ── Verification: jar file exists at the configured target path ── + # This is the strongest possible end-to-end check: the file appearing + # on disk proves ResolveJavaProject + ResolveMainClass + generateClasspaths + # + Jdtls.exportJar all completed in order. A failure here pinpoints + # the wizard breaking; a pass means the full happy path worked. + - id: "verify-jar-created" + action: "wait 1 seconds" + verifyFile: + path: "${workspaceFolder}/output.jar" + exists: true + timeout: 60 diff --git a/test/e2e-plans/java-dep-file-operations.yaml b/test/e2e-plans/java-dep-file-operations.yaml new file mode 100644 index 00000000..45deefe4 --- /dev/null +++ b/test/e2e-plans/java-dep-file-operations.yaml @@ -0,0 +1,254 @@ +# Test Plan: Java Dependency — File Operations +# +# Covers fileOperations.test.ts scenarios: +# - create new Java class +# - create new package +# - rename Java file +# - delete Java file +# +# Note: The workspace is auto-copied to a temp directory by autotest, +# so rename/delete operations don't pollute the source test fixtures. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-file-operations.yaml --vsix + +name: "Java Dependency — File Operations" +description: | + Tests file/resource operations in the Java Projects view: + create class, create package, rename file, delete file. + Replaces test/e2e/tests/fileOperations.test.ts. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup: wait for LS, free Explorer space, focus Java Projects ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check (it returns only when the Java Language Server status + # changes to "Ready"). The post-action screenshot frequently captures + # the very next state — "Java: Building - 0%" once Maven import begins — + # which a strict LLM mis-reads as "not ready", even though Ready was + # observed milliseconds earlier. + timeout: 180 + + # Free horizontal space (Chat panel can take ~210px on right side) + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + # Free vertical space inside Explorer so JAVA PROJECTS gets room. + # Without this the Java Projects pane-header overlaps tree rows on + # 1024x768 CI displays and click events get intercepted by the sticky header. + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Test 1: create new Java class ── + - id: "click-project-node" + action: "click my-app tree item" + + - id: "trigger-new-resource" + action: "clickTreeItemAction my-app New..." + verify: "New resource quick pick opened" + + - id: "select-java-class" + action: "selectOptionByIndex 0" + verify: "Java Class selected" + + - id: "select-source-folder" + action: "select src/main/java option" + verify: "Source folder selected" + + - id: "enter-class-name" + action: "fillQuickInput App2" + # NOTE: no `verify:` — `fillQuickInput` submits and closes the quick input. + # The before/after screenshots only show the input disappearing, which the + # screenshot-comparing LLM frequently mis-reads as "wrong UI element + # targeted". The deterministic `verifyEditorTab` on the next step is the + # ground truth for whether App2.java was created. + + - id: "verify-new-class-tab" + action: "wait 2 seconds" + # No `verify:` — state-check step. The deterministic `verifyEditorTab` + # below is authoritative. BEFORE and AFTER screenshots are nearly + # identical at steady state (App2.java tab present in both), which a + # strict LLM can mis-read as "no change". + verifyEditorTab: + title: "App2.java" + timeout: 15 + + # ── Test 2: create new package ── + # Close the editor opened by the previous step. With link-with-editor on, + # an open editor causes the JAVA PROJECTS tree to auto-expand, pushing + # my-app right under the sticky pane-header where clicks get intercepted. + # + # App2.java is opened in a dirty editor by the New Class flow (the extension + # writes initial class boilerplate via the buffer), so we must save first + # — otherwise `Close All Editors` raises a "Save changes?" modal dialog + # that blocks every subsequent click for the rest of the run. + - id: "save-all-before-close" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-before-pkg" + action: "run command View: Close All Editors" + + - id: "collapse-workspace-root-2" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-2" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # Test 1 expanded my-app → src/main/java → com.mycompany.app to reveal the + # newly-created App2.java. Reset the JAVA PROJECTS tree so my-app is back + # at row 0 and not occluded by the sticky pane-header on the next click. + - id: "collapse-java-projects-tree-2" + action: "executeVSCodeCommand workbench.actions.treeView.javaProjectExplorer.collapseAll" + waitBefore: 1 + + - id: "click-project-node-2" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-resource-2" + action: "clickTreeItemAction my-app New..." + + - id: "select-package" + action: "select Package option" + verify: "Package selected" + + - id: "select-source-folder-2" + action: "select src/main/java option" + + - id: "enter-package-name" + action: "fillQuickInput com.mycompany.newpkg" + # No `verify:` — quick input closes after submit and the new package is + # under a still-collapsed tree, so LLM can't see the change and downgrades + # the step. Package creation is a side-effect of the wizard finishing. + + - id: "wait-package-creation" + action: "wait 3 seconds" + # No `verify:` — tree is collapsed at this point so the new package isn't + # rendered; LLM screenshot comparison would erroneously downgrade. + + # ── Test 3: rename Java file ── + # Open the target file, let link-with-editor reveal it in the tree, + # then click to select it and trigger rename via context menu. + - id: "open-rename-target" + action: "open file AppToRename.java" + waitBefore: 3 + + - id: "collapse-workspace-root-3" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-3" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 3 + + # Click the tree item first to select it + - id: "select-rename-target" + action: "click AppToRename tree item" + waitBefore: 2 + + # Use context menu to trigger extension's rename (shows showInputBox) + - id: "rename-context-menu" + action: "contextMenu AppToRename Rename" + verify: "Rename input box opened" + + - id: "enter-new-name" + action: "fillAnyInput AppRenamed" + # No `verify:` — rename is async (status bar shows "Computing rename + # updates..." for several seconds) so the AFTER screenshot still shows + # the old name and LLM downgrades. `verify-renamed-tab` below uses + # deterministic `verifyEditorTab` against the new name as ground truth. + waitBefore: 2 + + # Handle optional rename confirmation dialog — may not appear on all platforms + # (Electron native dialog is auto-dismissed by monkey-patch). + # No `verify:` — confirmDialog is best-effort (dialog may not appear). + - id: "handle-rename-dialog" + action: "confirmDialog" + + # Handle optional Refactor Preview panel. + # No `verify:` — tryClickButton is best-effort; if the Apply button does not + # appear because the refactor finished without preview, the before/after + # screenshots are identical and LLM downgrades. The deterministic + # `verify-renamed-tab` covers the real outcome. + - id: "handle-refactor-preview" + action: "tryClickButton Apply" + + - id: "wait-rename" + action: "wait 3 seconds" + + - id: "verify-renamed-tab" + action: "wait 1 seconds" + # No `verify:` — state-check step. `verifyEditorTab` is authoritative. + # By the time this runs, the rename has typically already completed + # (after wait-rename's 3s), so both BEFORE and AFTER show AppRenamed. + # A strict LLM mis-reads identical screenshots as "no transition". + verifyEditorTab: + title: "AppRenamed" + timeout: 15 + + # ── Test 4: delete Java file ── + # Instead of manually expanding the tree (which requires viewport space), + # open the file and let link-with-editor reveal it in the tree. + - id: "open-delete-target" + action: "open file AppToDelete.java" + waitBefore: 5 + + - id: "collapse-workspace-root-4" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-4" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 2 + + - id: "delete-context-menu" + action: "contextMenu AppToDelete Delete" + verify: "Delete confirmation triggered" + + # VSCode shows a platform-specific confirmation dialog for delete. + # Use the strict variant: throw if the dialog is not present, so a + # silently-failed delete-context-menu surfaces here rather than 30s later + # at verify-deleted. Requires @vscjava/vscode-autotest >= 0.6.7. + - id: "confirm-delete" + action: "expectConfirmDialog" + + # Combined wait + verify in a single step: the deterministic verifyTreeItem + # with visible:false polls up to 15s for the tree to refresh, so a short + # explicit `wait 3` is enough to give the tree time to render before the + # AFTER screenshot is captured. + - id: "wait-delete" + action: "wait 6 seconds" + + - id: "verify-deleted" + action: "wait 1 seconds" + # No `verify:` — AFTER screenshot is captured immediately after the wait, + # but the tree's removal of AppToDelete may not yet be visually reflected + # on slower CI runners. The deterministic verifyTreeItem (visible:false) + # below polls for up to 15s and is authoritative. + verifyTreeItem: + name: "AppToDelete" + visible: false + timeout: 15 diff --git a/test/e2e-plans/java-dep-new-types.yaml b/test/e2e-plans/java-dep-new-types.yaml new file mode 100644 index 00000000..eb35283d --- /dev/null +++ b/test/e2e-plans/java-dep-new-types.yaml @@ -0,0 +1,339 @@ +# Test Plan: Java Dependency — New File Types +# +# Covers the "New..." quick-pick options from the Java Projects view that are +# NOT already covered by java-dep-file-operations.yaml (which only tests +# `New Class` and `New Package`). +# +# Commands exercised (each invoked through the New... quick-pick on a node): +# - java.view.package.newJavaInterface (Interface) +# - java.view.package.newJavaEnum (Enum) +# - java.view.package.newJavaRecord (Record — requires Java 16+) +# - java.view.package.newJavaAnnotation (Annotation) +# - java.view.package.newJavaAbstractClass (Abstract Class) +# - java.view.package.newFile ("File" option) +# - java.view.package.newFolder ("Folder" option) +# +# Pattern for each type (same as the existing New Class flow): +# 1. click `my-app` in the JAVA PROJECTS view +# 2. clickTreeItemAction my-app New... (triggers java.view.package.new) +# 3. select option in the quick pick +# 4. select src/main/java source-folder option (where applicable) +# 5. fillQuickInput +# 6. verifyEditorTab — confirms the new file was created and opened +# +# Between each cycle the previously-created file is saved + all editors are +# closed and the JAVA PROJECTS tree is collapsed, mirroring the technique +# used in java-dep-file-operations.yaml. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-new-types.yaml --vsix + +name: "Java Dependency — New File Types" +description: | + Tests all the "New ..." quick-pick options in the Java Projects view that + are not already covered by java-dep-file-operations.yaml: + Interface / Enum / Record / Annotation / Abstract Class / File / Folder. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 240 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — waitForLanguageServer is itself the deterministic + # readiness check; see java-dep-file-operations.yaml for rationale. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + # Collapse the MAVEN workspace-folder pane so JAVA PROJECTS gets the full + # vertical space. OUTLINE and TIMELINE are collapsed by default in fresh + # sessions, so no explicit step is needed. + - id: "collapse-maven-pane" + action: "collapseSidebarSection maven" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Test 1: New Interface ── + - id: "click-project-1" + action: "click my-app tree item" + + - id: "trigger-new-1" + action: "clickTreeItemAction my-app New..." + verify: "New resource quick pick opened" + + - id: "select-interface" + action: "select Interface option" + # No `verify:` — LLM screenshot check is flaky when the quick-pick + # advances immediately after selection (LLM sees the next page and + # mistakes the advance for "selection not visible"). The downstream + # fillQuickInput / file creation provides authoritative verification. + + - id: "select-source-folder-1" + action: "select src/main/java option" + + - id: "enter-interface-name" + action: "fillQuickInput MyInterface" + # No `verify:` — fillQuickInput submits and closes the quick input. The + # deterministic `verifyEditorTab` below is the ground truth. + + - id: "verify-interface-tab" + action: "wait 2 seconds" + # No `verify:` — BEFORE/AFTER screenshots are identical once the editor + # tab is open; verifyEditorTab is authoritative. + verifyEditorTab: + title: "MyInterface.java" + timeout: 20 + + # Reset between cycles: save the dirty buffer, close editors, refocus. + - id: "save-1" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-1" + action: "run command View: Close All Editors" + + - id: "collapse-tree-1" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-2" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-2" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 2: New Enum ── + - id: "click-project-2" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-2" + action: "clickTreeItemAction my-app New..." + + - id: "select-enum" + action: "select Enum option" + + - id: "select-source-folder-2" + action: "select src/main/java option" + + - id: "enter-enum-name" + action: "fillQuickInput MyEnum" + + - id: "verify-enum-tab" + action: "wait 2 seconds" + verifyEditorTab: + title: "MyEnum.java" + timeout: 20 + + - id: "save-2" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-2" + action: "run command View: Close All Editors" + + - id: "collapse-tree-2" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-3" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-3" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 3: New Annotation ── + - id: "click-project-3" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-3" + action: "clickTreeItemAction my-app New..." + + - id: "select-annotation" + action: "select Annotation option" + + - id: "select-source-folder-3" + action: "select src/main/java option" + + - id: "enter-annotation-name" + action: "fillQuickInput MyAnnotation" + + - id: "verify-annotation-tab" + action: "wait 2 seconds" + verifyEditorTab: + title: "MyAnnotation.java" + timeout: 20 + + - id: "save-3" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-3" + action: "run command View: Close All Editors" + + - id: "collapse-tree-3" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-4" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-4" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 4: New Record (Java 16+; fixture pom uses Java 17) ── + # The Record option is only shown when the project source level is >= 16, + # see JavaType.getDisplayNames(..., includeRecord) in src/explorerCommands/new.ts. + - id: "click-project-4" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-4" + action: "clickTreeItemAction my-app New..." + + - id: "select-record" + action: "select Record option" + + - id: "select-source-folder-4" + action: "select src/main/java option" + + - id: "enter-record-name" + action: "fillQuickInput MyRecord" + + - id: "verify-record-tab" + action: "wait 2 seconds" + verifyEditorTab: + title: "MyRecord.java" + timeout: 20 + + - id: "save-4" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-4" + action: "run command View: Close All Editors" + + - id: "collapse-tree-4" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-5" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-5" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 5: New Abstract Class ── + - id: "click-project-5" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-5" + action: "clickTreeItemAction my-app New..." + + - id: "select-abstract-class" + action: "select Abstract Class option" + + - id: "select-source-folder-5" + action: "select src/main/java option" + + - id: "enter-abstract-name" + action: "fillQuickInput MyAbstract" + + - id: "verify-abstract-tab" + action: "wait 2 seconds" + verifyEditorTab: + title: "MyAbstract.java" + timeout: 20 + + - id: "save-5" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-5" + action: "run command View: Close All Editors" + + - id: "collapse-tree-5" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-6" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-6" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 6: New File (plain non-Java file via "File" option) ── + # The "File" entry routes to `java.view.package.newFile` and writes the + # file under the project root (the node we triggered from). + - id: "click-project-6" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-6" + action: "clickTreeItemAction my-app New..." + + - id: "select-file" + action: "select File option" + + - id: "enter-file-name" + action: "fillQuickInput notes.txt" + + - id: "verify-file-tab" + action: "wait 2 seconds" + verifyEditorTab: + title: "notes.txt" + timeout: 20 + + - id: "save-6" + action: "executeVSCodeCommand workbench.action.files.saveAll" + + - id: "close-editors-6" + action: "run command View: Close All Editors" + + - id: "collapse-tree-6" + action: 'clickViewTitleAction "Java Projects" "Collapse All"' + + - id: "collapse-workspace-root-7" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects-7" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 1 + + # ── Test 7: New Folder ── + # Folder creation has no editor side-effect — verify by checking the new + # folder exists on disk under the workspace root. + - id: "click-project-7" + action: "click my-app tree item" + waitBefore: 1 + + - id: "trigger-new-7" + action: "clickTreeItemAction my-app New..." + + - id: "select-folder" + action: "select Folder option" + + - id: "enter-folder-name" + action: "fillQuickInput my-new-folder" + + - id: "wait-folder-create" + action: "wait 2 seconds" + # No `verify:` — folder creation has no editor side-effect, so the + # BEFORE/AFTER screenshots are nearly identical and a screenshot LLM + # would downgrade. The deterministic verifyFile below is authoritative. + verifyFile: + path: "~/my-new-folder" + exists: true + timeout: 15 diff --git a/test/e2e-plans/java-dep-project-creation.yaml b/test/e2e-plans/java-dep-project-creation.yaml new file mode 100644 index 00000000..946188c0 --- /dev/null +++ b/test/e2e-plans/java-dep-project-creation.yaml @@ -0,0 +1,169 @@ +# Test Plan: Java Dependency — Create Project +# +# Covers java.project.create — the flagship "Java: Create Java Project..." +# wizard. We exercise the "No build tools" branch (a.k.a. invisible / +# unmanaged-folder project) because it is the only project type whose +# scaffolding lives entirely inside this extension (`templates/invisible- +# project/`) — every other type (Maven, Gradle, Spring Boot, Quarkus, ...) +# delegates to a third-party extension's create-command, which is out of +# scope for this repo's E2E coverage. +# +# Wizard flow (controllers/projectController.ts — `createJavaProject` → +# `scaffoldSimpleProject`): +# 1. `window.showQuickPick` → user picks a project type +# 2. `window.showOpenDialog` (folder mode, `openLabel: "Select the project location"`) +# → user picks parent directory +# 3. `window.showInputBox` → user types the project name +# 4. `fse.copy(templates/invisible-project, /)` → scaffold +# 5. `commands.executeCommand("vscode.openFolder", Uri.file(...), openInNewWindow)` +# where openInNewWindow = workspace && !_.isEmpty(workspace.workspaceFolders) +# +# Why a new window does NOT break this test +# ───────────────────────────────────────── +# Because the test runs with a workspace open (`workspace: "../maven"`), +# step 5 opens the new project in a SEPARATE Electron window. The Playwright +# driver is attached via CDP to the original window's renderer process; the +# new window is a separate process the driver never sees. After step 4 +# (the fse.copy) the scaffolded files are already on disk regardless of +# whether step 5 succeeds in opening the new window — so the deterministic +# verifyFile assertions still pass. We deliberately put no UI steps after +# the project creation completes, to avoid any race with the second-window +# spawn momentarily stealing OS focus. +# +# Verification strategy +# ───────────────────── +# `templates/invisible-project/` ships exactly three files: +# - README.md +# - .vscode/settings.json +# - src/App.java +# In addition, `scaffoldSimpleProject` (projectController.ts:185) creates +# an empty `lib/` directory at runtime via `fse.ensureDir`, so a freshly +# scaffolded project on disk has the three template files plus `lib/`. +# We assert two of the template files (the .vscode settings file and +# App.java) on disk. Notably absent: `.classpath` / `.project` — invisible +# projects rely on `java.import.generatesMetadataFilesAtProjectRoot` (off +# by default in the template), so testing for .classpath would yield a +# false negative. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-project-creation.yaml --vsix + +name: "Java Dependency — Create Project" +description: | + Exercises the java.project.create wizard end-to-end on the "No build + tools" path: triggers the command, picks the project type, drives the + folder picker, names the project, and verifies the scaffolded template + files appear on disk. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 240 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Setup: wait for LS, free sidebar space, focus Java Projects ── + # We open the maven workspace to satisfy step 5's openInNewWindow=true + # branch (see header comment). LS readiness isn't strictly required for + # project creation, but the wait gives the workbench time to settle + # before we drive multiple chained quick-picks / input-boxes. + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. + timeout: 180 + + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # ── Step 1: trigger the wizard and pick the project type ── + # Direct command invocation is more reliable than navigating the title- + # bar `$(add)` icon on the Java Projects view, which routes through the + # `_java.project.create.from.javaprojectexplorer` proxy command — same + # underlying handler but extra menu-binding indirection. + - id: "invoke-create-project" + action: "executeVSCodeCommand java.project.create" + + # The project-type quick-pick lists 9 items (controllers/projectController.ts + # `projectTypes`). "No build tools" is index 0. We pick by exact label + # rather than index to keep the plan resilient if the list is re-ordered. + - id: "pick-no-build-tools" + action: "select No build tools option" + + # ── Step 2: drive the folder picker ── + # `window.showOpenDialog` (canSelectFolders: true) is intercepted by + # VS Code's smoke-test driver and re-surfaced as the internal + # simpleFileDialog quick-pick — the same mechanism the classpath plan + # uses for addLibraryFolders. In folder-pick mode, typing a path and + # pressing Enter NAVIGATES INTO the folder; the explicit confirmation + # button (labelled with the dialog's `openLabel`, here "Select the + # project location") is what actually returns the URI to the caller. + # + # We type the workspace root path so the scaffolded project lands + # directly inside the auto-copied worktree — that keeps the verifyFile + # paths simple and the worktree gets cleaned up by autotest at teardown. + - id: "type-project-location" + action: "fillQuickInput ${workspaceFolder}" + + - id: "confirm-project-location" + action: "tryClickButton Select the project location" + + # ── Step 3: name the project ── + # `window.showInputBox` surfaces as the quick-input widget too; + # `fillAnyInput` covers both quick-input and inline-rename widgets so + # it's slightly more robust if VS Code ever changes which surface the + # InputBox API targets. + - id: "type-project-name" + action: "fillAnyInput AutotestNewProject" + + # ── Step 4 + 5: wait for scaffold + new-window spawn ── + # `fse.copy(templates/invisible-project, ...)` is a few-KB synchronous- + # style copy that completes in <500ms, but `vscode.openFolder` triggers + # a second Electron window launch which can briefly steal focus and + # delay file flushing on slower disks. 8s is a comfortable margin. + - id: "wait-scaffold-and-open" + action: "wait 8 seconds" + + # ── Verification: scaffolded template files exist on disk ── + # These two assertions together prove: + # - the wizard reached step 4 (file copy) + # - the basePath (workspace root) and projectName (AutotestNewProject) + # were correctly threaded through showOpenDialog / showInputBox + # + # Verifying directly on disk is the strongest signal we can get: it + # decouples the test from whatever happens with the new-window spawn, + # which Playwright can't observe anyway (different Electron process). + - id: "verify-app-java" + action: "wait 1 seconds" + verifyFile: + path: "${workspaceFolder}/AutotestNewProject/src/App.java" + exists: true + timeout: 15 + + - id: "verify-vscode-settings" + action: "wait 1 seconds" + verifyFile: + path: "${workspaceFolder}/AutotestNewProject/.vscode/settings.json" + exists: true + timeout: 15 diff --git a/test/e2e-plans/java-dep-project-explorer.yaml b/test/e2e-plans/java-dep-project-explorer.yaml new file mode 100644 index 00000000..73854cf6 --- /dev/null +++ b/test/e2e-plans/java-dep-project-explorer.yaml @@ -0,0 +1,230 @@ +# Test Plan: Java Dependency — Project Explorer +# +# Covers scenarios: +# - javaProjectExplorer.focus shows Java Projects section +# - linkWithFolderExplorer reveals active file in tree +# - unlinkWithFolderExplorer stops auto-reveal +# - revealInProjectExplorer reveals file from File Explorer context menu +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-project-explorer.yaml --vsix + +name: "Java Dependency — Project Explorer" +description: | + Tests the Java Projects explorer view: focus, link/unlink with editor, + reveal in project explorer. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Wait for LS ready ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — `waitForLanguageServer` is itself the deterministic + # readiness check. The AFTER screenshot may transiently show + # "Java: Building - 0%" (Maven import starts immediately after Ready), + # which a strict LLM mis-reads as a failure. + timeout: 180 + + # Free horizontal & vertical space so JAVA PROJECTS gets enough room. + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-workspace-root" + action: "collapseWorkspaceRoot" + + # ── Test 1: javaProjectExplorer.focus ── + # The view is contributed to the Explorer container, so the palette title is + # "Explorer: Focus on Java Projects View". Invoking the command id directly + # via executeVSCodeCommand is locale-independent and slightly faster. + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + - id: "verify-project-node" + action: "wait 1 seconds" + # No `verify:` — state-check step; `verifyTreeItem` is authoritative. + verifyTreeItem: + name: "my-app" + timeout: 15 + + # ── Test 2: linkWithFolderExplorer ── + # NOTE: action resolver only matches "expandTreeItem " — strings like + # "expand my-app tree item" silently fall back to command palette and no-op. + - id: "expand-project" + action: "expandTreeItem my-app" + + - id: "expand-src" + action: "expandTreeItem src/main/java" + waitBefore: 2 + + - id: "verify-package" + action: "wait 1 seconds" + # No `verify:` — state-check step; `verifyTreeItem` is authoritative. + verifyTreeItem: + name: "com.mycompany.app" + timeout: 15 + + - id: "expand-package" + action: "expandTreeItem com.mycompany.app" + waitBefore: 2 + + - id: "verify-app-class" + action: "wait 1 seconds" + # No `verify:` — state-check step; `verifyTreeItem` is authoritative. + verifyTreeItem: + name: "App" + exact: true + timeout: 15 + + # ── Test 3: unlinkWithFolderExplorer ── + # Click the title-bar action ("Unlink with Editor") in the JAVA PROJECTS pane. + # When `config.java.dependency.syncWithFolderExplorer == true` (the default), + # the package contributes the Unlink button to overflow_10@20 — clickViewTitleAction + # locates it directly or via the "Views and More Actions..." overflow menu. + - id: "unlink-editor" + action: 'clickViewTitleAction "Java Projects" "Unlink with Editor"' + # No `verify:` — toggling the link-with-editor setting produces no visible + # change in the screenshot (tree selection persists from the prior reveal). + # The behavior is verified deterministically by `wait-after-open` below: + # after opening AppToRename.java, the tree must NOT auto-reveal it. + + - id: "open-rename-file" + action: "open file AppToRename.java" + + - id: "wait-after-open" + action: "wait 3 seconds" + # Stability check: with link-with-editor disabled, opening + # AppToRename.java must NOT change the Java Projects tree state. The + # BEFORE and AFTER screenshots are expected to look identical (tree + # state preserved), which is exactly what a comparison-only LLM + # verification can confirm reliably. We cannot use verifyTreeItem + # visible:false here because AppToRename is already visible (its + # parent package was expanded by earlier setup steps); the check is + # about tree-state stability, not item visibility. + verify: "Java Projects tree state is unchanged; opening AppToRename.java did not auto-reveal or auto-select anything new." + + - id: "relink-editor" + action: 'clickViewTitleAction "Java Projects" "Link with Editor"' + # No `verify:` — same reason as `unlink-editor`. The behavior is verified + # deterministically downstream when revealInProjectExplorer locates App. + + # ── Test 4: revealInProjectExplorer ── + # Collapse all tree nodes, then reveal App.java by invoking the contributed + # `java.view.package.revealInProjectExplorer` command. autotest 0.7.x has no + # contextMenuOnEditorTab action, so we drive the command directly via + # executeVSCodeCommand with a Uri-shaped POJO arg (the command reads + # `uri.fsPath` and reconstructs a proper Uri before use, so a plain object + # with `fsPath` is sufficient). + - id: "collapse-all" + action: "executeVSCodeCommand workbench.actions.treeView.javaProjectExplorer.collapseAll" + verify: "Collapse tree to reset state" + + - id: "open-app-file" + action: "open file App.java" + waitBefore: 2 + + - id: "reveal-in-project-explorer" + action: 'executeVSCodeCommand java.view.package.revealInProjectExplorer {"fsPath":"${workspaceFolder}/src/main/java/com/mycompany/app/App.java","scheme":"file"}' + waitBefore: 2 + + - id: "verify-revealed" + action: "wait 2 seconds" + # No `verify:` — state-check step; `verifyTreeItem` is authoritative. + verifyTreeItem: + name: "App" + exact: true + timeout: 15 + + # ── Test 5: mixed multi-root project attribution (#1060) ── + # First establish a mixed workspace and refresh it into WorkspaceNode roots. + # The smoke-test driver renders folder pickers as an internal quick input: + # entering an absolute folder path opens it, then the Add button confirms it. + - id: "invoke-add-non-java-root" + action: "executeVSCodeCommand workbench.action.addRootFolder" + + - id: "type-non-java-root" + action: "fillQuickInput ${workspaceParent}/non-java" + + - id: "confirm-non-java-root" + action: "tryClickButton Add" + + - id: "wait-non-java-root-ready" + action: "waitForLanguageServer" + timeout: 120 + skipLlmVerify: true + + - id: "refresh-mixed-workspace" + action: "executeVSCodeCommand java.view.package.refresh" + waitBefore: 2 + + - id: "collapse-multi-root-explorer" + action: "collapseSidebarSection UNTITLED (WORKSPACE)" + + - id: "focus-mixed-workspace" + action: "executeVSCodeCommand javaProjectExplorer.focus" + waitBefore: 2 + + - id: "verify-non-java-workspace-root" + action: "wait 1 seconds" + verifyTreeItem: + name: "non-java" + timeout: 15 + + # Add a Java folder after the mixed multi-root structure already exists and + # refresh it into the expected WorkspaceNode -> ProjectNode hierarchy. + - id: "invoke-add-java-root" + action: "executeVSCodeCommand workbench.action.addRootFolder" + + - id: "type-java-root" + action: "fillQuickInput ${workspaceParent}/simple" + + - id: "confirm-java-root" + action: "tryClickButton Add" + + - id: "wait-java-root-ready" + action: "waitForLanguageServer" + timeout: 120 + skipLlmVerify: true + + - id: "refresh-added-java-root" + action: "executeVSCodeCommand java.view.package.refresh" + + - id: "verify-java-workspace-root" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verifyTreeItem: + name: "simple" + exact: true + count: 1 + level: 1 + timeout: 15 + + # Deterministically simulate the onDidProjectsImport path. Before #1060 this + # command appended a second top-level ProjectNode named "simple" beside the + # existing WorkspaceNode. The fixed provider ignores progressive insertion + # in multi-root workspaces, so exactly one level-1 row remains. + - id: "simulate-progressive-project-import" + action: 'executeVSCodeCommand _java.view.package.internal.addProjects ["${workspaceParentUri}/simple"]' + verifyTreeItem: + name: "simple" + exact: true + count: 1 + level: 1 + timeout: 15 diff --git a/test/e2e-plans/java-dep-refresh-generated-files.yaml b/test/e2e-plans/java-dep-refresh-generated-files.yaml new file mode 100644 index 00000000..3f55cb2b --- /dev/null +++ b/test/e2e-plans/java-dep-refresh-generated-files.yaml @@ -0,0 +1,127 @@ +# Regression test for issue #914: manual Refresh must surface externally written +# .java files (a brand-new sub-package and a class in an existing package). +# Pre-fix the shallow DEPTH_ONE refresh never discovered the new package folder. +# +# Tree layout: the Java Projects tree is virtualized, so off-screen rows are not +# in the DOM. The Explorer file tree is collapsed and explorer.autoReveal is off +# so assertions run while the tree is compact and every package node collapsed. +# +# insertLineInFile uses fs.writeFileSync, bypassing VS Code's file service — i.e. +# exactly an external generator. Assertions use the deterministic verifyTreeItem +# DOM check; file-write and refresh steps carry no `verify:` because the LLM +# screenshot judge has no reliable visual signal for them. +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-refresh-generated-files.yaml \ +# --override extensionPath= + +name: "Java Dependency — Refresh surfaces externally generated files (#914)" +description: | + Regression for issue #914. Externally written .java files — one in a brand-new + sub-package, one in an existing package — must both appear in the Java Projects + view after an explicit Refresh. + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + explorer.autoReveal: false + +steps: + - id: "ls-ready" + action: "waitForLanguageServer" + timeout: 180 + + # Free vertical space so the Java Projects tree is not virtualized. + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + + - id: "collapse-outline" + action: "collapseSidebarSection OUTLINE" + + - id: "collapse-timeline" + action: "collapseSidebarSection TIMELINE" + + - id: "collapse-explorer-folders" + action: "collapseSidebarSection maven" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # NOTE: no `verify:` on expand steps — the LLM screenshot check is flaky + # ("LLM downgraded pass -> fail" on already-expanded trees). The next + # verifyTreeItem (or the chained expand below) provides authoritative + # ground truth: if the expand didn't happen the child won't be visible. + - id: "expand-project" + action: "expandTreeItem my-app" + + - id: "expand-source-root" + action: "expandTreeItem src/main/java" + + - id: "baseline-existing-pkg" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app" + visible: true + + # Negative baseline: the brand-new package must be ABSENT before any file is + # written. This is the "before" half of the regression's before/after check — + # it proves check-new-pkg later observes a genuine appearance, not a leftover. + - id: "baseline-new-pkg-absent" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app.gen" + visible: false + timeout: 5 + + # Write files straight to disk: one in a brand-new sub-package, one in an + # existing package. + - id: "gen-file-new-pkg" + action: "insertLineInFile src/main/java/com/mycompany/app/gen/Gen914InNewPkg.java 1 package com.mycompany.app.gen;\n\npublic class Gen914InNewPkg {\n}\n" + + - id: "gen-file-existing-pkg" + action: "insertLineInFile src/main/java/com/mycompany/app/Gen914InExisting.java 1 package com.mycompany.app;\n\npublic class Gen914InExisting {\n}\n" + + - id: "dismiss-overlay" + action: "pressKey Escape" + + - id: "settle" + action: "wait 3 seconds" + + # The behaviour under test: an explicit manual Refresh. + - id: "manual-refresh" + action: "executeVSCodeCommand java.view.package.refresh" + + - id: "wait-after-refresh" + action: "wait 4 seconds" + + - id: "reexpand-source-root" + action: "expandTreeItem src/main/java" + + # Core regression: the brand-new package appears after Refresh. + - id: "check-new-pkg" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app.gen" + visible: true + timeout: 15 + + # Sanity: a new class in an existing package also appears. No `verify:` here + # for the same reason as the expand steps above — check-existing-pkg-class + # below is the deterministic assertion. + - id: "expand-existing-pkg" + action: "expandTreeItem com.mycompany.app" + + - id: "check-existing-pkg-class" + action: "wait 1 seconds" + verifyTreeItem: + name: "Gen914InExisting" + visible: true + timeout: 15 diff --git a/test/e2e-plans/java-dep-view-modes.yaml b/test/e2e-plans/java-dep-view-modes.yaml new file mode 100644 index 00000000..85ff1ee5 --- /dev/null +++ b/test/e2e-plans/java-dep-view-modes.yaml @@ -0,0 +1,265 @@ +# Test Plan: Java Dependency — View Modes & Refresh +# +# Covers Java Projects view title-bar / overflow commands: +# - java.view.package.changeToHierarchicalPackageView (Hierarchical View) +# - java.view.package.changeToFlatPackageView (Flat View) +# - java.view.package.refresh (Refresh) +# - java.project.explorer.hideNonJavaResources (Hide Non-Java Resources) +# - java.project.explorer.showNonJavaResources (Show Non-Java Resources) +# +# Usage: +# npx autotest run test/e2e-plans/java-dep-view-modes.yaml --vsix + +name: "Java Dependency — View Modes & Refresh" +description: | + Tests Java Projects explorer title-bar commands: switching between flat / + hierarchical package presentation, refreshing the tree, and toggling + visibility of non-Java resources (pom.xml, .vscode, .classpath, .project). + +setup: + extension: "redhat.java" + vscodeVersion: "stable" + workspace: "../maven" + timeout: 180 + settings: + java.configuration.checkProjectSettingsExclusions: false + workbench.startupEditor: "none" + +steps: + # ── Wait for LS ── + - id: "ls-ready" + action: "waitForLanguageServer" + # No `verify:` — waitForLanguageServer is the deterministic readiness + # check. The AFTER screenshot may transiently show "Java: Building - 0%" + # right after Ready, which a strict LLM mis-reads as a failure. + timeout: 180 + + # Free horizontal & vertical space so JAVA PROJECTS gets enough room. + - id: "close-aux-bar" + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" + verify: "Auxiliary bar (Chat) closed" + + # Collapse the entire MAVEN workspace-folder pane so JAVA PROJECTS gets the + # full vertical space — its tree is virtualized and rows below the viewport + # are not rendered, which masks items like pom.xml that live below + # src/main/java in a Maven project. OUTLINE and TIMELINE panes are + # collapsed by default in a fresh session, so no explicit step needed. + - id: "collapse-maven-pane" + action: "collapseSidebarSection maven" + + - id: "focus-java-projects" + action: "executeVSCodeCommand javaProjectExplorer.focus" + verify: "Java Projects view is focused" + + - id: "wait-tree-load" + action: "wait 3 seconds" + + # Expand my-app → src/main/java so subsequent verifyTreeItem can observe + # package nodes at this layer. + - id: "expand-project" + action: "expandTreeItem my-app" + + - id: "expand-src-main" + action: "expandTreeItem src/main/java" + waitBefore: 2 + + # ── Baseline: flat mode shows "com.mycompany.app" as a single node ── + - id: "verify-flat-baseline" + action: "wait 1 seconds" + # No `verify:` — verifyTreeItem is authoritative. + verifyTreeItem: + name: "com.mycompany.app" + exact: true + inView: "Java Projects" + timeout: 15 + + # ── Test 1: switch to hierarchical view ── + # In hierarchical (compressed) mode the JLS collapses single-child chains, + # so "com.mycompany.app" is split into a parent "com.mycompany" node with + # children "app" and "app1". This is the same behavior covered by + # test/maven-suite/projectView.test.ts ("primarySubPackage.name should be + # 'com.mycompany'"). Verify deterministically through the appearance of + # the "com.mycompany" node. + - id: "switch-to-hierarchical" + action: 'clickViewTitleAction "Java Projects" "Hierarchical View"' + # Real UI path: opens the Java Projects view overflow menu and clicks + # "Hierarchical View". sub-screenshots capture overflow-open (button + # tooltip visible) and menuitem (Hierarchical View highlighted) so + # the LLM/human reviewer can verify the click landed correctly. + # deterministic verifyTreeItem below is still authoritative. + + - id: "wait-hierarchical" + action: "wait 4 seconds" + + - id: "verify-hierarchical-node" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany" + exact: true + inView: "Java Projects" + timeout: 15 + + # ── Test 2: switch back to flat view ── + - id: "switch-to-flat" + action: 'clickViewTitleAction "Java Projects" "Flat View"' + # Real UI path through view-title overflow menu — see + # switch-to-hierarchical. verifyTreeItem below is authoritative. + + - id: "wait-flat" + action: "wait 4 seconds" + + - id: "verify-flat-restored" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app" + exact: true + inView: "Java Projects" + timeout: 15 + + - id: "verify-hierarchical-gone" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany" + exact: true + visible: false + inView: "Java Projects" + timeout: 15 + + # ── Test 3: refresh ── + # Smoke check: the command runs without throwing and the tree remains stable. + - id: "refresh-tree" + action: "executeVSCodeCommand java.view.package.refresh" + # No `verify:` — refresh has no visible effect at steady state, so the + # BEFORE/AFTER screenshots are identical and a strict LLM downgrades. + # The deterministic verifyTreeItem on verify-refresh-stable confirms the + # tree did not get corrupted by the refresh. + + - id: "wait-after-refresh" + action: "wait 3 seconds" + + - id: "verify-refresh-stable" + action: "wait 1 seconds" + verifyTreeItem: + name: "com.mycompany.app" + exact: true + inView: "Java Projects" + timeout: 15 + + # ── Test 4: hide non-Java resources ── + # In flat mode the project shows non-Java resources such as pom.xml, + # .vscode, .classpath, .project. Hide should remove them from the tree. + # `inView: "Java Projects"` scopes the search to the Java Projects pane + # only — without it the EXPLORER pane (which also shows pom.xml at the + # workspace root) would mask any Java-Projects-side change. + # + # The virtualized Java Projects tree only renders rows in the viewport, + # so we first collapse src/main/java to bring pom.xml (a sibling) into + # view. Click selects the node, then ArrowLeft collapses it. + - id: "select-src-main" + action: "click src/main/java" + + - id: "collapse-src-main" + action: "pressKey ArrowLeft" + + # After collapsing src/main/java, press End to scroll the (virtualized) + # JAVA PROJECTS tree to its last row, which makes pom.xml — a child of + # my-app rendered below other source folders / libraries — render in + # the DOM. Playwright's `waitFor("visible")` does not auto-scroll + # virtualized lists, so this is necessary. + - id: "scroll-tree-end" + action: "pressKey End" + + - id: "wait-collapse" + action: "wait 1 seconds" + + - id: "verify-pom-visible-baseline" + action: "wait 1 seconds" + verifyTreeItem: + name: "pom.xml" + exact: true + inView: "Java Projects" + timeout: 15 + + - id: "hide-non-java" + action: 'clickViewTitleAction "Java Projects" "Hide Non-Java Resources"' + # Real UI path through view-title overflow menu. The menu item label + # toggles based on `config.java.project.explorer.showNonJavaResources` + # (Show vs Hide), and the current state at this point is "showing" + # so the menu surfaces "Hide Non-Java Resources". verifyTreeItem + # checks below are authoritative. + + - id: "wait-hide" + action: "wait 5 seconds" + + - id: "verify-pom-hidden" + action: "wait 1 seconds" + verifyTreeItem: + name: "pom.xml" + exact: true + visible: false + inView: "Java Projects" + timeout: 30 + + # ── Test 5: show non-Java resources ── + - id: "show-non-java" + action: 'clickViewTitleAction "Java Projects" "Show Non-Java Resources"' + # Real UI path through view-title overflow menu. After hide-non-java + # the toggle now surfaces "Show Non-Java Resources". verifyTreeItem + # below is authoritative. + + - id: "wait-show" + action: "wait 5 seconds" + + # After the tree refresh, the scroll position may have reset to the top + # of the JAVA PROJECTS pane, so scroll back to the end to render pom.xml. + - id: "scroll-tree-end-2" + action: "pressKey End" + + - id: "verify-pom-restored" + action: "wait 1 seconds" + verifyTreeItem: + name: "pom.xml" + exact: true + inView: "Java Projects" + timeout: 30 + + # ── Test 6: do not show empty physical ancestors of package roots (#1062) ── + # src/main/java and src/main/resources are represented as Java package roots. + # The physical src → main hierarchy must not also appear as an empty normal + # folder tree when non-Java resources are shown. + - id: "reset-tree-for-non-java-ancestor-check" + action: "executeVSCodeCommand workbench.actions.treeView.javaProjectExplorer.collapseAll" + + - id: "expand-project-for-non-java-ancestor-check" + action: "expandTreeItem my-app" + waitBefore: 2 + + - id: "verify-resources-root-visible" + action: "wait 1 seconds" + verifyTreeItem: + name: "src/main/resources" + exact: true + level: 2 + inView: "Java Projects" + timeout: 15 + + - id: "expand-resources-root" + action: "expandTreeItem src/main/resources" + + - id: "verify-resource-file-visible" + action: "wait 1 seconds" + verifyTreeItem: + name: "application.yml" + exact: true + inView: "Java Projects" + timeout: 15 + + - id: "verify-empty-physical-src-hidden" + action: "wait 1 seconds" + verifyTreeItem: + name: "src" + exact: true + level: 2 + visible: false + inView: "Java Projects" + timeout: 15 diff --git a/test/gradle-suite/projectView.test.ts b/test/gradle-suite/projectView.test.ts index ec5a045d..6e23a088 100644 --- a/test/gradle-suite/projectView.test.ts +++ b/test/gradle-suite/projectView.test.ts @@ -3,15 +3,20 @@ import * as assert from "assert"; import { ContainerNode, contextManager, DataNode, DependencyExplorer, + languageServerApiManager, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; import { fsPath, setupTestEnv, Uris } from "../shared"; // tslint:disable: only-arrow-functions suite("Gradle Project View Tests", () => { - suiteSetup(setupTestEnv); + suiteSetup(async () => { + await setupTestEnv(); + await languageServerApiManager.ready(); + }); test("Can node render correctly", async function() { + this.timeout(120000); const explorer = DependencyExplorer.getInstance(contextManager.context); // validate root nodes @@ -24,13 +29,13 @@ suite("Gradle Project View Tests", () => { const projectChildren = await projectNode.getChildren(); assert.ok(!!projectChildren.find((c: DataNode) => c.name === "build.gradle")); assert.ok(!!projectChildren.find((c: DataNode) => c.name === ".vscode")); - const mainPackage = projectChildren[0] as PackageRootNode; - assert.equal(mainPackage.name, "src/main/java", "Package name should be \"src/main/java\""); - const systemLibrary = projectChildren[1] as ContainerNode; - const gradleDependency = projectChildren[2] as ContainerNode; + const mainPackage = projectChildren.find((c: DataNode) => c.name === "src/main/java") as PackageRootNode; + assert.ok(mainPackage, "Should have src/main/java package root"); + const systemLibrary = projectChildren.find((c: DataNode) => c.name.startsWith("JRE System Library")) as ContainerNode; + const gradleDependency = projectChildren.find((c: DataNode) => c.name === "Project and External Dependencies") as ContainerNode; // only match prefix of system library since JDK version may differ - assert.ok(systemLibrary.name.startsWith("JRE System Library"), "Container name should start with JRE System Library"); - assert.equal(gradleDependency.name, "Project and External Dependencies", "Container name should be \"Project and External Dependencies\""); + assert.ok(systemLibrary, "Should have JRE System Library container"); + assert.ok(gradleDependency, "Should have Project and External Dependencies container"); // validate innermost layer nodes const mainClasses = await mainPackage.getChildren(); @@ -43,7 +48,9 @@ suite("Gradle Project View Tests", () => { const explorer = DependencyExplorer.getInstance(contextManager.context); const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; - const mainPackage = (await projectNode.getChildren())[0] as PackageRootNode; + const projectChildren = await projectNode.getChildren(); + const mainPackage = projectChildren.find((c: DataNode) => c.name === "src/main/java") as PackageRootNode; + assert.ok(mainPackage, "Should have src/main/java"); const mainClass = (await mainPackage.getChildren())[0] as PrimaryTypeNode; assert.equal(fsPath(projectNode), Uris.GRADLE_PROJECT_NODE, "Project uri incorrect"); diff --git a/test/index.ts b/test/index.ts index 66d0b20a..a08d7358 100644 --- a/test/index.ts +++ b/test/index.ts @@ -16,10 +16,14 @@ async function main(): Promise { // Resolve redhat.java dependency const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - cp.spawnSync(cli, [...args, '--install-extension', 'redhat.java'], { + const options: cp.SpawnSyncOptionsWithStringEncoding = { encoding: 'utf-8', - stdio: 'inherit' - }); + stdio: 'inherit', + }; + if (process.platform === 'win32') { + options.shell = true; + } + cp.spawnSync(cli, [...args, '--install-extension', 'redhat.java'], options); // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` @@ -94,6 +98,28 @@ async function main(): Promise { ], }); + // Run multi-root workspace test + await runTests({ + vscodeExecutablePath, + extensionDevelopmentPath, + extensionTestsPath: path.resolve(__dirname, "./multiple-suite"), + launchArgs: [ + path.join(__dirname, "..", "..", "test", "multiple", "multiple-project.code-workspace"), + `--user-data-dir=${userDir}`, + ], + }); + + // Run test for non-Java Gradle project (regression test for #921) + await runTests({ + vscodeExecutablePath, + extensionDevelopmentPath, + extensionTestsPath: path.resolve(__dirname, "./non-java-gradle-suite"), + launchArgs: [ + path.join(__dirname, "..", "..", "test", "non-java-gradle"), + `--user-data-dir=${userDir}`, + ], + }); + process.exit(0); } catch (err) { diff --git a/test/invisible-suite/projectView.test.ts b/test/invisible-suite/projectView.test.ts index c1488ce7..61e91d01 100644 --- a/test/invisible-suite/projectView.test.ts +++ b/test/invisible-suite/projectView.test.ts @@ -3,22 +3,21 @@ import * as assert from "assert"; import * as fse from "fs-extra"; -import { platform } from "os"; import * as path from "path"; import * as vscode from "vscode"; -import { Commands, contextManager, DependencyExplorer, PackageNode, PackageRootNode, ProjectNode } from "../../extension.bundle"; +import { Commands, contextManager, DependencyExplorer, languageServerApiManager, PackageNode, PackageRootNode, ProjectNode } from "../../extension.bundle"; import { setupTestEnv } from "../shared"; import { sleep } from "../util"; // tslint:disable: only-arrow-functions suite("Invisible Project View Tests", () => { - suiteSetup(setupTestEnv); + suiteSetup(async () => { + await setupTestEnv(); + await languageServerApiManager.ready(); + }); test("Can execute command java.project.refreshLibraries correctly", async function() { - if (platform() === "darwin") { - this.skip(); - } const explorer = DependencyExplorer.getInstance(contextManager.context); let projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; @@ -37,9 +36,6 @@ suite("Invisible Project View Tests", () => { }); test("Can execute command java.project.removeLibrary correctly", async function() { - if (platform() === "darwin") { - this.skip(); - } const explorer = DependencyExplorer.getInstance(contextManager.context); let projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; diff --git a/test/invisible/extraJars/extra-a.jar b/test/invisible/extraJars/extra-a.jar new file mode 100644 index 00000000..d8cc4e6f Binary files /dev/null and b/test/invisible/extraJars/extra-a.jar differ diff --git a/test/invisible/extraJars/extra-b.jar b/test/invisible/extraJars/extra-b.jar new file mode 100644 index 00000000..d8cc4e6f Binary files /dev/null and b/test/invisible/extraJars/extra-b.jar differ diff --git a/test/invisible/lib/simple.jar b/test/invisible/lib/simple.jar new file mode 100644 index 00000000..d8cc4e6f Binary files /dev/null and b/test/invisible/lib/simple.jar differ diff --git a/test/maven-suite/projectView.test.ts b/test/maven-suite/projectView.test.ts index f6863758..ff3c5db5 100644 --- a/test/maven-suite/projectView.test.ts +++ b/test/maven-suite/projectView.test.ts @@ -3,14 +3,17 @@ import * as assert from "assert"; import * as vscode from "vscode"; -import { Commands, ContainerNode, contextManager, DataNode, DependencyExplorer, FileNode, - INodeData, Jdtls, NodeKind, PackageNode, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; +import { Commands, ContainerNode, contextManager, DataNode, DependencyExplorer, FileNode, FolderNode, + INodeData, Jdtls, languageServerApiManager, NodeKind, PackageNode, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; import { fsPath, printNodes, setupTestEnv, Uris } from "../shared"; // tslint:disable: only-arrow-functions suite("Maven Project View Tests", () => { - suiteSetup(setupTestEnv); + suiteSetup(async () => { + await setupTestEnv(); + await languageServerApiManager.ready(); + }); test("Can node render correctly in hierarchical view", async function() { await vscode.workspace.getConfiguration("java.dependency").update("packagePresentation", "hierarchical"); @@ -26,8 +29,9 @@ suite("Maven Project View Tests", () => { const projectChildren = await projectNode.getChildren(); assert.ok(!!projectChildren.find((c: DataNode) => c.name === "pom.xml")); assert.ok(!!projectChildren.find((c: DataNode) => c.name === ".vscode")); - assert.equal(projectChildren.length, 8, `Number of children should be 8, but was ${projectChildren.length}.\n${printNodes(projectChildren)}`); - const mainPackage = projectChildren[0] as PackageRootNode; + assert.ok(projectChildren.length >= 8, `Number of children should be at least 8, but was ${projectChildren.length}.\n${printNodes(projectChildren)}`); + const mainPackage = projectChildren.find((c: DataNode) => c.name === "src/main/java") as PackageRootNode; + assert.ok(mainPackage, "Should have src/main/java package root"); assert.equal(mainPackage.name, "src/main/java", "Package name should be \"src/main/java\""); const mainSourceSetChildren = await mainPackage.getChildren(); @@ -75,15 +79,15 @@ suite("Maven Project View Tests", () => { const projectChildren = await projectNode.getChildren(); assert.ok(!!projectChildren.find((c: DataNode) => c.name === "pom.xml")); assert.ok(!!projectChildren.find((c: DataNode) => c.name === ".vscode")); - const mainPackage = projectChildren[0] as PackageRootNode; - const testPackage = projectChildren[1] as PackageRootNode; - assert.equal(mainPackage.name, "src/main/java", "Package name should be \"src/main/java\""); - assert.equal(testPackage.name, "src/test/java", "Package name should be \"src/test/java\""); - const systemLibrary = projectChildren[2] as ContainerNode; - const mavenDependency = projectChildren[3] as ContainerNode; + const mainPackage = projectChildren.find((c: DataNode) => c.name === "src/main/java") as PackageRootNode; + const testPackage = projectChildren.find((c: DataNode) => c.name === "src/test/java") as PackageRootNode; + assert.ok(mainPackage, "Should have src/main/java package root"); + assert.ok(testPackage, "Should have src/test/java package root"); + const systemLibrary = projectChildren.find((c: DataNode) => c.name.startsWith("JRE System Library")) as ContainerNode; + const mavenDependency = projectChildren.find((c: DataNode) => c.name === "Maven Dependencies") as ContainerNode; // only match prefix of system library since JDK version may differ - assert.ok(systemLibrary.name.startsWith("JRE System Library"), "Container name should start with JRE System Library"); - assert.equal(mavenDependency.name, "Maven Dependencies", "Container name should be \"Maven Dependencies\""); + assert.ok(systemLibrary, "Should have JRE System Library container"); + assert.ok(mavenDependency, "Should have Maven Dependencies container"); // validate package nodes const mainSourceSetChildren = await mainPackage.getChildren(); @@ -126,8 +130,10 @@ suite("Maven Project View Tests", () => { const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; const packageRoots = await projectNode.getChildren(); - const mainPackage = packageRoots[0] as PackageRootNode; - const testPackage = packageRoots[1] as PackageRootNode; + const mainPackage = packageRoots.find((c: DataNode) => c.name === "src/main/java") as PackageRootNode; + const testPackage = packageRoots.find((c: DataNode) => c.name === "src/test/java") as PackageRootNode; + assert.ok(mainPackage, "Should have src/main/java"); + assert.ok(testPackage, "Should have src/test/java"); const mainSubPackage = (await mainPackage.getChildren())[0] as PackageNode; const testSubPackage = (await testPackage.getChildren())[0] as PackageNode; const mainClass = (await mainSubPackage.getChildren())[0] as PrimaryTypeNode; @@ -241,6 +247,61 @@ suite("Maven Project View Tests", () => { assert.ok(!projectChildren.find((node: DataNode) => node.nodeData.name === ".hidden")); }); + test("Does not display empty physical ancestors of Java package roots", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; + const projectChildren = await projectNode.getChildren(); + + assert.ok(!projectChildren.find((node: DataNode) => node.nodeData.name === "src"), + "The physical src folder should not duplicate Java package roots"); + + const resourcesRoot = projectChildren.find((node: DataNode) => + node.nodeData.name === "src/main/resources") as PackageRootNode; + assert.ok(resourcesRoot, "The Maven resources root should remain visible"); + const resourceChildren = await resourcesRoot.getChildren(); + assert.ok(resourceChildren.find((node: DataNode) => node.nodeData.name === "application.yml"), + "Non-Java files under the resources root should remain visible"); + }); + + test("Displays empty non-Java folders next to Java package roots", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; + const initialChildren = await projectNode.getChildren(); + const mainSourceRoot = initialChildren.find((node: DataNode) => + node.nodeData.name === "src/main/java") as PackageRootNode; + const srcPath = mainSourceRoot.nodeData.path!.replace(/\/main\/java$/, ""); + const docsUri = vscode.Uri.joinPath(vscode.Uri.file(Uris.MAVEN_PROJECT_NODE), "src", "docs"); + await vscode.workspace.fs.createDirectory(docsUri); + + try { + await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_GETPACKAGEDATA, { + kind: NodeKind.Folder, + projectUri: projectNode.uri, + path: srcPath, + }); + await vscode.commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH); + const refreshedProjectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; + const projectChildren = await refreshedProjectNode.getChildren(); + const srcFolder = projectChildren.find((node: DataNode) => + node.nodeData.name === "src") as FolderNode; + + assert.ok(srcFolder, "The physical src folder should remain visible when it contains an empty non-Java folder"); + const srcChildren = await srcFolder.getChildren(); + assert.ok(srcChildren.find((node: DataNode) => node.nodeData.name === "docs"), + "The empty non-Java folder should remain visible"); + } finally { + await vscode.workspace.fs.delete(docsUri, { recursive: true }); + await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_GETPACKAGEDATA, { + kind: NodeKind.Folder, + projectUri: projectNode.uri, + path: srcPath, + }); + await vscode.commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH); + } + }); + test("Can apply 'java.project.explorer.showNonJavaResources'", async function() { await vscode.workspace.getConfiguration("java.project.explorer").update( "showNonJavaResources", @@ -250,7 +311,43 @@ suite("Maven Project View Tests", () => { const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode; const projectChildren = await projectNode.getChildren(); - assert.equal(projectChildren.length, 4); + // When showNonJavaResources is false, non-Java resource nodes (pom.xml, .vscode, .settings, etc.) should be hidden + assert.ok(!projectChildren.find((c: DataNode) => c.name === "pom.xml"), "pom.xml should be hidden"); + assert.ok(!projectChildren.find((c: DataNode) => c.name === ".vscode"), ".vscode should be hidden"); + assert.ok(!projectChildren.find((c: DataNode) => c.name === ".classpath"), ".classpath should be hidden"); + assert.ok(!projectChildren.find((c: DataNode) => c.name === ".project"), ".project should be hidden"); + }); + + test("Can maven dependency nodes display in correct groupId:artifactId:version format", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + + const roots = await explorer.dataProvider.getChildren(); + const projectNode = roots![0] as ProjectNode; + const projectChildren = await projectNode.getChildren(); + const mavenDependency = projectChildren.find((c: DataNode) => c.name === "Maven Dependencies") as ContainerNode; + assert.ok(mavenDependency, "Should have Maven Dependencies container"); + const mavenChildren = await mavenDependency.getChildren(); + + assert.equal(mavenChildren[0].getDisplayName(), "org.hamcrest:hamcrest-core:1.3"); + assert.equal(mavenChildren[1].getDisplayName(), "junit:junit:4.13.1"); + }); + + test("Does not add duplicate progressive projects for equivalent URIs", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + await vscode.commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH); + + const roots = await explorer.dataProvider.getChildren(); + assert.equal(roots?.length, 1, "Number of root nodes should be 1"); + const projectNode = roots![0] as ProjectNode; + assert.ok(projectNode.uri, "Project node should have a URI"); + + const equivalentUri = projectNode.uri!.endsWith("/") + ? projectNode.uri!.replace(/\/+$/, "") + : `${projectNode.uri}/`; + explorer.dataProvider.addProgressiveProjects([equivalentUri]); + + const updatedRoots = await explorer.dataProvider.getChildren(); + assert.equal(updatedRoots?.length, 1, "Equivalent project URIs should be deduplicated"); }); teardown(async () => { diff --git a/test/maven/src/main/resources/application.yml b/test/maven/src/main/resources/application.yml new file mode 100644 index 00000000..b6c6235b --- /dev/null +++ b/test/maven/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + application: + name: my-app diff --git a/test/multi-module-suite/projectView.test.ts b/test/multi-module-suite/projectView.test.ts index e54e9336..5776ae80 100644 --- a/test/multi-module-suite/projectView.test.ts +++ b/test/multi-module-suite/projectView.test.ts @@ -4,21 +4,32 @@ import * as assert from "assert"; import { contextManager, DependencyExplorer, FileNode, + languageServerApiManager, ProjectNode } from "../../extension.bundle"; import { printNodes, setupTestEnv } from "../shared"; // tslint:disable: only-arrow-functions suite("Multi Module Tests", () => { - suiteSetup(setupTestEnv); + suiteSetup(async () => { + await setupTestEnv(); + await languageServerApiManager.ready(); + }); test("Can open module with name equal or longer than folder name correctly", async function() { + this.timeout(120000); const explorer = DependencyExplorer.getInstance(contextManager.context); const roots = await explorer.dataProvider.getChildren(); + // Find the level1 submodule - LS may use .project name or folder name const nestedProjectNode = roots?.find(project => - project instanceof ProjectNode && project.name === 'de.myorg.myservice.level1') as ProjectNode; + project instanceof ProjectNode && ( + project.name === 'de.myorg.myservice.level1' || + project.name === 'fvclaus-de.myorg.myservice.level1' || + project.name === 'level1' + )) as ProjectNode; + assert.ok(nestedProjectNode, `Expected to find level1 project in roots:\n${roots?.map(r => (r as ProjectNode).name).join(', ')}`); const projectChildren = await nestedProjectNode.getChildren(); assert.ok(!!projectChildren.find(child => child instanceof FileNode && child.path?.endsWith('level1/pom.xml'), `Expected to find FileNode with level1 pom.xml in:\n${printNodes(projectChildren)}`)); }); diff --git a/test/multiple-suite/index.ts b/test/multiple-suite/index.ts new file mode 100644 index 00000000..cfc957e9 --- /dev/null +++ b/test/multiple-suite/index.ts @@ -0,0 +1,38 @@ +// 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 { + const mocha = new Mocha({ + ui: "tdd", + color: true, + timeout: 1 * 60 * 1000, + }); + + const testsRoot = __dirname; + + return new Promise((c, e) => { + glob("**/**.test.js", { cwd: testsRoot }, (err, files) => { + if (err) { + return e(err); + } + + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); + + try { + mocha.run((failures) => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + e(err); + } + }); + }); +} diff --git a/test/multiple-suite/projectView.test.ts b/test/multiple-suite/projectView.test.ts new file mode 100644 index 00000000..2e10c3db --- /dev/null +++ b/test/multiple-suite/projectView.test.ts @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as assert from "assert"; +import * as vscode from "vscode"; +import { + Commands, contextManager, DependencyExplorer, ProjectNode, WorkspaceNode, +} from "../../extension.bundle"; +import { setupTestEnv } from "../shared"; + +// tslint:disable: only-arrow-functions +suite("Multiple Project View Tests", () => { + + suiteSetup(async () => { + await setupTestEnv(); + const javaExtension = vscode.extensions.getExtension("redhat.java"); + assert.ok(javaExtension, "Language Support for Java should be installed"); + const javaApi = await javaExtension!.activate(); + await javaApi.serverReady(); + await vscode.commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH); + }); + + test("Does not add project roots progressively in a multi-root workspace", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + const roots = await explorer.dataProvider.getChildren(); + const expectedRootCount = vscode.workspace.workspaceFolders?.length || 0; + + assert.equal(roots?.length, expectedRootCount, "Each workspace folder should have one root node"); + assert.ok(roots?.every(root => root instanceof WorkspaceNode), "All roots should be workspace nodes"); + const nonJavaRoot = roots?.find(root => + root instanceof WorkspaceNode && root.name === "non-java") as WorkspaceNode | undefined; + assert.ok(nonJavaRoot, "The non-Java workspace folder should have a root node"); + assert.equal((await nonJavaRoot!.getChildren()).length, 0, "The non-Java root should not contain Java projects"); + + const projects = await explorer.dataProvider.getRootProjects(); + const project = projects.find((node): node is ProjectNode => + node instanceof ProjectNode && Boolean(node.uri)); + assert.ok(project?.uri, "At least one Java project should be available"); + + explorer.dataProvider.addProgressiveProjects([project!.uri!]); + + const updatedRoots = await explorer.dataProvider.getChildren(); + assert.equal(updatedRoots?.length, expectedRootCount, "Progressive updates should not add project roots"); + assert.ok(updatedRoots?.every(root => root instanceof WorkspaceNode), "All roots should remain workspace nodes"); + }); + + test("Does not add project roots while cached multi-root roots are stale", async function() { + const explorer = DependencyExplorer.getInstance(contextManager.context); + const roots = await explorer.dataProvider.getChildren(); + const folders = vscode.workspace.workspaceFolders; + assert.ok(folders && folders.length > 1, "The test requires a multi-root workspace"); + assert.ok(roots?.every(root => root instanceof WorkspaceNode), "All cached roots should be workspace nodes"); + + const projects = await explorer.dataProvider.getRootProjects(); + const project = projects.find((node): node is ProjectNode => + node instanceof ProjectNode && Boolean(node.uri)); + assert.ok(project?.uri, "At least one Java project should be available"); + + const removedFolders = folders!.slice(1); + const workspaceFoldersChanged = updateWorkspaceFoldersAndWait(1, removedFolders.length, [], + "The workspace should switch to a single folder"); + + try { + assert.equal(vscode.workspace.workspaceFolders?.length, 1, "The workspace should have one folder"); + explorer.dataProvider.addProgressiveProjects([project!.uri!]); + + const updatedRoots = await explorer.dataProvider.getChildren(); + assert.equal(updatedRoots?.length, roots?.length, "Stale cached roots should not be mixed with project roots"); + assert.ok(updatedRoots?.every(root => root instanceof WorkspaceNode), + "Cached workspace roots should remain unchanged until refresh"); + } finally { + await workspaceFoldersChanged; + await updateWorkspaceFoldersAndWait(1, 0, + removedFolders.map(folder => ({ uri: folder.uri })), + "The removed workspace folders should be restored"); + } + }); +}); + +async function updateWorkspaceFoldersAndWait( + start: number, + deleteCount: number, + foldersToAdd: { uri: vscode.Uri; name?: string }[], + failureMessage: string, +): Promise { + let resolveChange: () => void; + const changed = new Promise((resolve) => resolveChange = resolve); + const listener = vscode.workspace.onDidChangeWorkspaceFolders(() => { + listener.dispose(); + resolveChange(); + }); + + if (!vscode.workspace.updateWorkspaceFolders(start, deleteCount, ...foldersToAdd)) { + listener.dispose(); + assert.fail(failureMessage); + } + + await changed; +} diff --git a/test/multiple/multiple-project.code-workspace b/test/multiple/multiple-project.code-workspace index 19610b08..6189dcb6 100644 --- a/test/multiple/multiple-project.code-workspace +++ b/test/multiple/multiple-project.code-workspace @@ -1,13 +1,16 @@ { "folders": [ { - "path": "..\\simple" + "path": "../simple" }, { - "path": "..\\maven" + "path": "../maven" }, { - "path": "..\\gradle" + "path": "../gradle" + }, + { + "path": "../non-java" } ], "settings": {} diff --git a/test/non-java-gradle-suite/index.ts b/test/non-java-gradle-suite/index.ts new file mode 100644 index 00000000..3e503ad8 --- /dev/null +++ b/test/non-java-gradle-suite/index.ts @@ -0,0 +1,41 @@ +// 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", + color: true, + timeout: 1 * 60 * 1000, + }); + + const testsRoot = __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/test/non-java-gradle-suite/projectExplorerActivation.test.ts b/test/non-java-gradle-suite/projectExplorerActivation.test.ts new file mode 100644 index 00000000..6161fc0e --- /dev/null +++ b/test/non-java-gradle-suite/projectExplorerActivation.test.ts @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as assert from "assert"; +import * as fse from "fs-extra"; +import * as path from "path"; +import { extensions, Uri, workspace } from "vscode"; +import { contextManager } from "../../extension.bundle"; +import { sleep } from "../util"; + +const PROJECT_MANAGER_ACTIVATED = "java:projectManagerActivated"; + +// tslint:disable: only-arrow-functions +/** + * Regression tests for https://github.com/microsoft/vscode-java-dependency/issues/921 + * + * The "Java Projects" explorer view's visibility is gated by the `java:projectManagerActivated` + * context. For non-Java Gradle workspaces (e.g. Groovy/Grails) the view used to appear + * unconditionally, which annoyed users that never write Java. The activation logic now + * defers setting that context until actual Java content is detected, and reacts when a + * Java file is added later. + */ +suite("Non-Java Gradle Workspace Activation Tests", () => { + + const workspaceRoot = workspace.workspaceFolders![0].uri.fsPath; + const generatedJavaFile = path.join(workspaceRoot, "Generated.java"); + + suiteSetup(async () => { + // Make sure no leftover from a previous failed run pollutes the workspace. + await fse.remove(generatedJavaFile); + // Activation is auto-triggered by `workspaceContains:build.gradle`, but await it + // explicitly so the test does not race with the activation function. + await extensions.getExtension("vscjava.vscode-java-dependency")!.activate(); + }); + + suiteTeardown(async () => { + await fse.remove(generatedJavaFile); + }); + + test("Should not flip projectManagerActivated when the workspace has no Java content", function() { + const activated = contextManager.getContextValue(PROJECT_MANAGER_ACTIVATED); + assert.notStrictEqual( + activated, + true, + "Java Projects view should stay hidden in a non-Java Gradle workspace (issue #921)", + ); + }); + + test("Should flip projectManagerActivated when a Java source file appears later", async function() { + this.timeout(20 * 1000); + + // Sanity check: still inactive before the file is created. + assert.notStrictEqual( + contextManager.getContextValue(PROJECT_MANAGER_ACTIVATED), + true, + ); + + await fse.outputFile( + generatedJavaFile, + "public class Generated { public static void main(String[] args) {} }\n", + ); + + // Wait for the FileSystemWatcher's onDidCreate event to propagate. + const deadline = Date.now() + 10 * 1000; + while (contextManager.getContextValue(PROJECT_MANAGER_ACTIVATED) !== true + && Date.now() < deadline) { + await sleep(200); + } + + assert.strictEqual( + contextManager.getContextValue(PROJECT_MANAGER_ACTIVATED), + true, + "Java Projects view should become visible after a *.java file is created", + ); + + // Sanity: file actually lives where we expect, in case the watcher is reacting to + // some other event source. + assert.ok(await fse.pathExists(Uri.file(generatedJavaFile).fsPath)); + }); +}); diff --git a/test/non-java-gradle/build.gradle b/test/non-java-gradle/build.gradle new file mode 100644 index 00000000..4311cf43 --- /dev/null +++ b/test/non-java-gradle/build.gradle @@ -0,0 +1,10 @@ +// A Gradle build file used to simulate a non-Java workspace (e.g. Groovy/Grails) +// that should NOT trigger the "Java Projects" explorer view. +// See: https://github.com/microsoft/vscode-java-dependency/issues/921 +plugins { + id 'groovy' +} + +repositories { + mavenCentral() +} diff --git a/test/non-java-gradle/src/main/groovy/Hello.groovy b/test/non-java-gradle/src/main/groovy/Hello.groovy new file mode 100644 index 00000000..4b6bebec --- /dev/null +++ b/test/non-java-gradle/src/main/groovy/Hello.groovy @@ -0,0 +1,5 @@ +class Hello { + static void main(String[] args) { + println 'Hello from Groovy!' + } +} diff --git a/test/non-java/package.json b/test/non-java/package.json new file mode 100644 index 00000000..030de1b7 --- /dev/null +++ b/test/non-java/package.json @@ -0,0 +1,4 @@ +{ + "name": "non-java", + "private": true +} diff --git a/test/simple-suite/projectView.test.ts b/test/simple-suite/projectView.test.ts index 862b28d4..eef03ce9 100644 --- a/test/simple-suite/projectView.test.ts +++ b/test/simple-suite/projectView.test.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import * as assert from "assert"; -import { ContainerNode, contextManager, DependencyExplorer, +import { ContainerNode, contextManager, DataNode, DependencyExplorer, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; import { fsPath, setupTestEnv, Uris } from "../shared"; @@ -18,11 +18,14 @@ suite("Simple Project View Tests", () => { const roots = await explorer.dataProvider.getChildren(); assert.equal(roots?.length, 1, "Number of root node should be 1"); const projectNode = roots![0] as ProjectNode; - assert.equal(projectNode.name, "1.helloworld", "Project name should be \"1.helloworld\""); + assert.equal(projectNode.name, "simple", "Project name should be \"simple\""); // validate package root/dependency nodes const projectChildren = await projectNode.getChildren(); - assert.equal(projectChildren.length, 6, "Number of children nodes should be 6"); + assert.equal(projectChildren.length, 5, + `Number of children nodes should be 5: ${projectChildren.map((node: DataNode) => node.name).join(", ")}`); + assert.ok(!projectChildren.find((node: DataNode) => node.name === "src"), + "The empty physical source folder should not be visible"); const mainPackage = projectChildren[0] as PackageRootNode; assert.equal(mainPackage.name, "src/main/java", "Package name should be \"src/main/java\""); const systemLibrary = projectChildren[1] as ContainerNode; diff --git a/test/simple/.project b/test/simple/.project index e86159b9..ac7b1767 100644 --- a/test/simple/.project +++ b/test/simple/.project @@ -1,17 +1,28 @@ - 1.helloworld - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - + simple + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + + + 1774876132513 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/test/suite/buildTask.test.ts b/test/suite/buildTask.test.ts index a861f73a..d8596356 100644 --- a/test/suite/buildTask.test.ts +++ b/test/suite/buildTask.test.ts @@ -22,6 +22,19 @@ suite("Build Task Tests", () => { && t.source === BuildTaskProvider.type; }); assert.ok(exportJarTask !== undefined); + assert.strictEqual(exportJarTask.definition.isFullBuild, false); + }); + + test("test resolving build task defaults to incremental build", async function() { + const task: Task = new Task({ + type: BuildTaskProvider.type, + paths: [ BuildTaskProvider.workspace ], + }, TaskScope.Workspace, BuildTaskProvider.defaultTaskName, BuildTaskProvider.type); + + const resolvedTask: Task | undefined = await new BuildTaskProvider().resolveTask(task); + + assert.ok(resolvedTask !== undefined); + assert.strictEqual(resolvedTask.definition.isFullBuild, false); }); test("test categorizePaths()", async function() { diff --git a/test/suite/extension.test.ts b/test/suite/extension.test.ts index 8b6e2864..625b9957 100644 --- a/test/suite/extension.test.ts +++ b/test/suite/extension.test.ts @@ -3,6 +3,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; +import { contextManager } from "../../extension.bundle"; // tslint:disable: only-arrow-functions // Defines a Mocha test suite to group tests of similar kind together @@ -16,4 +17,15 @@ suite("Extension Tests", () => { await vscode.extensions.getExtension("vscjava.vscode-java-dependency")!.activate(); assert.ok(true); }); + + test("Should flip projectManagerActivated when the workspace contains Java content", async function() { + await vscode.extensions.getExtension("vscjava.vscode-java-dependency")!.activate(); + // The general suite runs against `test/java9`, which contains *.java sources, so the + // explorer-visibility context must be set. Guards against regressions of issue #921 in + // the opposite direction (i.e. the view erroneously hidden for real Java workspaces). + assert.strictEqual( + contextManager.getContextValue("java:projectManagerActivated"), + true, + ); + }); }); diff --git a/test/ui/command.test.ts b/test/ui/command.test.ts deleted file mode 100644 index d9f28cd0..00000000 --- a/test/ui/command.test.ts +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -import * as assert from "assert"; -import * as fse from "fs-extra"; -import { platform, tmpdir } from "os"; -import * as path from "path"; -import * as seleniumWebdriver from "selenium-webdriver"; -import { ActivityBar, By, InputBox, ModalDialog, SideBarView, StatusBar, TextEditor, TreeItem, VSBrowser, ViewSection, Workbench } from "vscode-extension-tester"; -import { sleep } from "../util"; - -// tslint:disable: only-arrow-functions -const newProjectName = "helloworld"; -const testFolder = path.join(__dirname, "..", "..", "..", "test"); -const mavenProjectPath = path.join(testFolder, "maven"); -const mavenJavaFilePath = path.join("src", "main", "java", "com", "mycompany", "app", "App.java"); -const invisibleProjectPath = path.join(testFolder, "invisible"); -const invisibleJavaFilePath = path.join("src", "App.java"); - -// async function pauseInPipeline(timeInMs: number): Promise { -// if (process.env.GITHUB_ACTIONS) { -// return sleep(timeInMs); -// } else { -// return Promise.resolve(); -// } -// } - -describe("Command Tests", function() { - - this.timeout(2 * 60 * 1000 /*ms*/); - const mavenProjectTmpFolders: string[] = []; - let currentProjectPath: string | undefined; - let statusBar: StatusBar; - - function createTmpProjectFolder(projectName: string) { - const tmpFolder = fse.mkdtempSync(path.join(tmpdir(), 'vscode-java-dependency-ui-test')); - // Keep the folder name. - const projectFolder = path.join(tmpFolder, projectName); - fse.mkdirSync(projectFolder); - mavenProjectTmpFolders.push(tmpFolder); - return projectFolder; - } - - async function openProject(projectPath: string) { - const projectFolder = createTmpProjectFolder(path.basename(projectPath)); - // Copy to avoid restoring after each test run to revert changes done during the test. - fse.copySync(projectPath, projectFolder); - await VSBrowser.instance.openResources(projectFolder); - currentProjectPath = projectFolder; - await ensureExplorerIsOpen(); - } - - async function openFile(filePath: string) { - statusBar = new StatusBar(); - if (path.isAbsolute(filePath)) { - await VSBrowser.instance.openResources(filePath); - } else { - await VSBrowser.instance.openResources(path.join(currentProjectPath!, filePath)); - } - } - - async function waitForLanguageServerReady() { - while (true) { - const language = await statusBar.getCurrentLanguage(); - if (language === 'Java') { - break; - } - } - while (true) { - try { - const languageStatus = await statusBar.findElement(By.xpath('//*[@id="status.languageStatus"]')); - await languageStatus.click(); - await languageStatus.findElement(By.xpath(`//div[contains(@class, 'context-view')]//div[contains(@class, 'hover-language-status')]//span[contains(@class, 'codicon-thumbsup')]`)); - break; - } catch (e) { - await sleep(100); - } - } - } - - before(async function() { - await openProject(mavenProjectPath); - await openFile(mavenJavaFilePath); - await waitForLanguageServerReady(); - }); - - after(async function() { - mavenProjectTmpFolders.forEach(mavenProjectTmpFolder => { - fse.rmSync(mavenProjectTmpFolder, {force: true, recursive: true}); - }); - }); - - - it("Test javaProjectExplorer.focus", async function() { - await new Workbench().executeCommand("javaProjectExplorer.focus"); - const section = await new SideBarView().getContent().getSection("Java Projects"); - assert.ok(section.isExpanded(), `Section "Java Projects" should be expanded`); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.linkWithFolderExplorer", async function() { - await openFile(mavenJavaFilePath); - await sleep(1000); - const [, section] = await expandInJavaProjects('my-app'); - const packageNode = await section.findItem("com.mycompany.app") as TreeItem; - assert.ok(await packageNode.isExpanded(), `Package node "com.mycompany.app" should be expanded`); - const classNode = await section.findItem("App") as TreeItem; - assert.ok(await classNode.isDisplayed(), `Class node "App" should be revealed`); - await packageNode.collapse(); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.unLinkWithFolderExplorer", async function() { - const [, section] = await expandInJavaProjects('my-app'); - await section.click(); - let moreActions = await section.moreActions(); - const desynchronize = await moreActions!.getItem("Unlink with Editor"); - await desynchronize!.click(); - await openFile(mavenJavaFilePath); - await sleep(1000); - const packageNode = await section.findItem("com.mycompany.app") as TreeItem; - assert.ok(!await packageNode.isExpanded(), `Package "com.mycompany.app" should not be expanded`); - moreActions = await section.moreActions(); - const link = await moreActions!.getItem("Link with Editor"); - await link!.click(); - }); - - it("Test java.view.package.newJavaClass", async function() { - let inputBox = await createJavaResource(); - const javaClassQuickPick = await inputBox.findQuickPick(0); - await javaClassQuickPick!.click(); - assert.ok(await inputBox.getPlaceHolder() === "Choose a source folder", `InputBox "Choose a source folder" should appear`); - const quickPick = await inputBox.findQuickPick("src/main/java"); - assert.ok(quickPick, `Quickpick item "src/main/java" should be found`); - await quickPick!.click(); - inputBox = await InputBox.create(); - assert.ok(await inputBox.getPlaceHolder() === "Input the class name", `InputBox "Input the class name" should appear`); - await inputBox.setText("App2"); - await inputBox.confirm(); - await sleep(1000); - const editor = new TextEditor(); - await editor.save(); - assert.ok(await editor.getTitle() === "App2.java", `Editor's title should be "App2.java"`); - assert.ok(await fse.pathExists(path.join(currentProjectPath!, "src", "main", "java", "App2.java")), `"App2.java" should be created in correct path`); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.newPackage", async function() { - // The current UI test framework doesn't support mac title bar and context menus. - // See: https://github.com/redhat-developer/vscode-extension-tester#requirements - // So we dismiss some UI tests on mac. - let inputBox = await createJavaResource(); - const packageQuickPick = await inputBox.findQuickPick('Package'); - await packageQuickPick!.click(); - const quickPick = await inputBox.findQuickPick("src/main/java"); - assert.ok(quickPick, `"src/main/java" should be found in quickpick items`); - await quickPick!.click(); - inputBox = await InputBox.create(); - await inputBox.setText("com.mycompany.app2"); - await inputBox.confirm(); - await sleep(1000); - assert.ok(await fse.pathExists(path.join(currentProjectPath!, "src", "main", "java", "com", "mycompany", "app2")), `New package should be created in correct path`); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.revealInProjectExplorer", async function() { - // Make sure App.java is not currently revealed in Java Projects - const section = await new SideBarView().getContent().getSection("Java Projects"); - const item = await section.findItem("my-app") as TreeItem; - await item.collapse(); - const [fileSection, fileNode] = await openAppJavaSourceCode(); - await fileNode.openContextMenu(); - // menu.getItem(label) does not work. I did not investigate this further. - // This is a global selector on purpose. The context-menu is located near the root node. - const revealItem = await fileNode.findElement(By.xpath(`//div[contains(@class, 'context-view')]//a[@role='menuitem' and span[contains(text(), 'Reveal in Java Project Explorer')]]`)); - // const revealItem = await menu.getItem("Reveal in Java Project Explorer"); - assert.ok(revealItem, `Item "Reveal in Java Project Explorer" should be found in context menu`); - await revealItem!.click(); - const classNode = await section.findItem("App") as TreeItem; - assert.ok(await classNode.isDisplayed(), `Class Node "App" should be revealed`); - await fileSection.collapse(); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.renameFile", async function() { - // Collapse file section to make sure that the AppToRename tree item fits in the current viewport. - // .findItem will only find tree items in the current viewport. - await collapseFileSection(); - const section = await expandMainCodeInJavaProjects(); - const classNode = await section.findItem("AppToRename") as TreeItem; - assert.ok(classNode, `AppToRename.java should be found`); - await classNode.click(); - const menu = await classNode.openContextMenu(); - const renameItem = await menu.getItem("Rename"); - assert.ok(renameItem, `"Rename" item should be found`); - await renameItem!.click(); - const inputBox = await InputBox.create(); - await inputBox.setText("AppRenamed"); - await inputBox.confirm(); - await sleep(1000); - const dialog = new ModalDialog(); - const buttons = await dialog.getButtons(); - for (const button of buttons) { - if (await button.getText() === "OK") { - await button.click(); - break; - } - } - await sleep(5000); - const editor = new TextEditor(); - await editor.save(); - assert.ok(await editor.getTitle() === "AppRenamed.java", `Editor's title should be "AppRenamed.java"`); - assert.ok(await section.findItem("AppRenamed"), `Item in Java Project section should be "AppRenamed"`); - }); - - (platform() === "darwin" ? it.skip : it)("Test java.view.package.moveFileToTrash", async function() { - // Collapse file section to make sure that the AppToRename tree item fits in the current viewport. - // .findItem will only find tree items in the current viewport. - await collapseFileSection(); - const section = await expandMainCodeInJavaProjects(); - const classNode = await section.findItem("AppToDelete") as TreeItem; - await classNode.click(); - const menu = await classNode.openContextMenu(); - let deleteItem = await menu.getItem("Delete"); - // Not sure why sometimes one is visible and other times the other. - if (deleteItem === undefined) { - deleteItem = await menu.getItem("Delete Permanently"); - } - assert.ok(deleteItem, `"Delete" item should be found`); - await deleteItem!.click(); - const dialog = new ModalDialog(); - const buttons = await dialog.getButtons(); - for (const button of buttons) { - if (await button.getText() === "Move to Recycle Bin") { - await button.click(); - break; - } - } - await sleep(1000); - assert.ok(!await fse.pathExists(path.join(currentProjectPath!, "src", "main", "java", "AppToDelete.java")), `The source file "AppToDelete.java" should be deleted`); - }); - - it("Test change to invisible project", async function() { - await openProject(invisibleProjectPath); - await openFile(invisibleJavaFilePath); - await waitForLanguageServerReady(); - const fileSections = await new SideBarView().getContent().getSections(); - await fileSections[0].collapse(); - await new Workbench().executeCommand("javaProjectExplorer.focus"); - }); - - it("Test java.project.addLibraries", async function() { - // tslint:disable-next-line:prefer-const - let [referencedItem, section] = await expandInJavaProjects('invisible', 'Referenced Libraries'); - await referencedItem.click(); - await clickActionButton(referencedItem, `Add Jar Libraries to Project Classpath...`); - const input = await InputBox.create(); - await input.setText(path.join(invisibleProjectPath, "libSource", "simple.jar")); - await input.confirm(); - await sleep(5000); - referencedItem = await section.findItem("Referenced Libraries") as TreeItem; - await referencedItem.expand(); - let simpleItem = await section.findItem("simple.jar") as TreeItem; - assert.ok(simpleItem, `Library "simple.jar" should be found`); - await simpleItem.click(); - await clickActionButton(simpleItem, 'Remove from Project Classpath'); - await sleep(5000); - simpleItem = await section.findItem("simple.jar") as TreeItem; - assert.ok(!simpleItem, `Library "simple.jar" should not be found`); - }); - - it("Test java.project.addLibraryFolders", async function() { - // tslint:disable-next-line:prefer-const - let [referencedItem, section] = await expandInJavaProjects('invisible', 'Referenced Libraries'); - await referencedItem.click(); - const button = await getActionButton(referencedItem, `Add Jar Libraries to Project Classpath...`); - await button.getDriver().actions() - // .mouseMove(buttons[0]) - .keyDown(seleniumWebdriver.Key.ALT) - .click(button) - .keyUp(seleniumWebdriver.Key.ALT) - .perform(); - await sleep(5000); - const input = await InputBox.create(); - await input.setText(path.join(invisibleProjectPath, "libSource")); - await input.confirm(); - await sleep(5000); - referencedItem = await section.findItem("Referenced Libraries") as TreeItem; - await referencedItem.expand(); - assert.ok(await section.findItem("simple.jar"), `Library "simple.jar" should be found`); - }); - - it("Test java.project.create", async function() { - const projectFolder = createTmpProjectFolder("newProject"); - await fse.ensureDir(projectFolder); - await new Workbench().executeCommand("java.project.create"); - let inputBox = await InputBox.create(); - const picks = await inputBox.getQuickPicks(); - assert.equal("No build tools", await picks[0].getLabel()); - await picks[0].select(); - await sleep(3000); - inputBox = await InputBox.create(); - await inputBox.setText(projectFolder); - await inputBox.confirm(); - await sleep(3000); - inputBox = await InputBox.create(); - await inputBox.setText(newProjectName); - await inputBox.confirm(); - await sleep(5000); - assert.ok(await fse.pathExists(path.join(projectFolder, newProjectName, "src", "App.java")), `The template source file should be created`); - assert.ok(await fse.pathExists(path.join(projectFolder, newProjectName, "README.md")), `The template README file should be created`); - }); - - -}); - -async function collapseFileSection() { - const fileSections = await new SideBarView().getContent().getSections(); - await fileSections[0].collapse(); -} - -async function expandMainCodeInJavaProjects() { - const section = await new SideBarView().getContent().getSection("Java Projects"); - await section.click(); - const appNode = await section.findItem("my-app") as TreeItem; - await appNode.expand(); - const srcFolderNode = await section.findItem('src/main/java') as TreeItem; - await srcFolderNode.expand(); - const packageNode = await section.findItem("com.mycompany.app") as TreeItem; - await packageNode.expand(); - return section; -} - -async function expandInJavaProjects(label: string, ...otherLabels: string[]): Promise<[TreeItem, ViewSection]> { - // Collapse file section to make sure that the AppToRename tree item fits in the current viewport. - // .findItem will only find tree items in the current viewport. - await collapseFileSection(); - const section = await new SideBarView().getContent().getSection("Java Projects"); - await section.click(); - let lastNode = await section.findItem(label) as TreeItem; - await lastNode.expand(); - for (const otherLabel of otherLabels) { - lastNode = await section.findItem(otherLabel) as TreeItem; - await lastNode.expand(); - } - return [lastNode, section]; -} - -async function openAppJavaSourceCode(): Promise<[ViewSection, TreeItem]> { - const fileSections = await new SideBarView().getContent().getSections(); - await fileSections[0].expand(); - const srcNode = await fileSections[0].findItem("src") as TreeItem; - await srcNode.expand(); - const folderNode = await fileSections[0].findItem("main") as TreeItem; - await folderNode.expand(); - const subFolderNode = await fileSections[0].findItem("com") as TreeItem; - await subFolderNode.expand(); - const appFolderNode = await fileSections[0].findItem("app") as TreeItem; - await appFolderNode.expand(); - const fileNode = await fileSections[0].findItem("App.java") as TreeItem; - await fileNode.click(); - return [fileSections[0], fileNode]; -} - -async function createJavaResource() { - await collapseFileSection(); - const section = await new SideBarView().getContent().getSection("Java Projects"); - const item = await section.findItem("my-app") as TreeItem; - assert.ok(item, `Project "my-app" should be found`); - await item.click(); - await clickActionButton(item, 'New...'); - const inputBox = await InputBox.create(); - assert.ok(await inputBox.getPlaceHolder() === "Select resource type to create.", - `InputBox "Select resource type to create" should appear.`); - return inputBox; -} - -async function clickActionButton(item: TreeItem, label: string) { - const button = await getActionButton(item, label); - await button.click(); -} - -async function getActionButton(item: TreeItem, label: string) { - // Using item.getActionButton('New...') throws an error: - // tslint:disable-next-line:max-line-length - // "no such element: Unable to locate element: {\"method\":\"xpath\",\"selector\":\".//a[contains(@class, 'action-label') and @role='button' and @title='New...']\"} - // This should be filled as an issue (I haven't find one). - // The problem is the @title='New...' which should be @aria-label='New...' for vscode 1.83.1 (and probably above). - return item.findElement(By.xpath(`.//a[contains(@class, 'action-label') and @role='button' and contains(@aria-label, '${label}')]`)); -} - -async function ensureExplorerIsOpen() { - const control = await new ActivityBar().getViewControl('Explorer'); - if (control === undefined) { - throw new Error(`Explorer control should not be null.`); - } - await control.openView(); -} - diff --git a/test/ui/index.ts b/test/ui/index.ts deleted file mode 100644 index 09de28d9..00000000 --- a/test/ui/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -import * as fse from "fs-extra"; -import * as path from "path"; -import * as semver from "semver"; -import { ExTester } from "vscode-extension-tester"; - -/* tslint:disable:no-console */ -async function main(): Promise { - try { - // Run UI command tests - const packageContent = await fse.readFile(path.join(__dirname, "..", "..", "..", "package.json")); - const packageJSON = JSON.parse(packageContent.toString()); - let vscodeVersion = packageJSON.engines.vscode; - if (!vscodeVersion) { - console.log("No valid version of VSCode engine was found in package.json"); - process.exit(1); - } - vscodeVersion = semver.minVersion(vscodeVersion); - const version = vscodeVersion.version; - const testPath = path.join(__dirname, "command.test.js"); - const exTester = new ExTester(); - await exTester.downloadCode(version); - await exTester.installVsix(); - await exTester.installFromMarketplace("redhat.java"); - await exTester.downloadChromeDriver(version); - await exTester.setupRequirements({vscodeVersion: version}); - process.exit(await exTester.runTests(testPath, {vscodeVersion: version, resources: []})); - } catch (err) { - console.log(err); - process.exit(1); - } -} - -main(); diff --git a/tsconfig.json b/tsconfig.json index 20c38219..98f55334 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,11 +15,13 @@ "noImplicitReturns": true, "noUnusedParameters": true, "strictNullChecks": true, - "alwaysStrict": true + "alwaysStrict": true, + "skipLibCheck": true }, "exclude": [ "node_modules", ".vscode-test", - "test-resources" + "test-resources", + "test/e2e" ] }