diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 0000000000..44c83732fa --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,8 @@ +{ + "instanceUrl": "https://msazure.visualstudio.com", + "projectName": "One", + "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell", + "notificationAliases": ["andschwa@microsoft.com", "slee@microsoft.com"], + "codebaseName": "PowerShell_vscode-powershell_20240328", + "tools": ["CredScan", "PoliCheck", "BinSkim"] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..31cbf8b559 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{json,yaml,yml,code-workspace}] +indent_size = 2 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..d775e01095 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,6 @@ +# Enabled on GitHub automatically +# Enable this file in your git config: +# git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Prettier reformatting +f978bae02ad48ddb5f8d4eb21512fe9b17541c5b diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..e6caee9a0c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Set svg to binary type, as SVG is unlikely to be editted by hand. Can be treated as checked in blob +*.svg binary diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..d2f790a4d5 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,16 @@ +# https://help.github.com/articles/about-codeowners/ + +# Global pattern +* @PowerShell/extension + +# Developer files +src/ @PowerShell/extension-dev +test/ @PowerShell/extension-dev +tools/ @PowerShell/extension-dev +.editorconfig @PowerShell/extension-dev +.gitattributes @PowerShell/extension-dev +.gitignore @PowerShell/extension-dev +extension-dev.code-workspace @PowerShell/extension-dev +package-lock.json @PowerShell/extension-dev +package.json @PowerShell/extension-dev +vscode-powershell.build.ps1 @PowerShell/extension-dev diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000000..d90459770a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,99 @@ +name: 🐛 Bug report +description: Open an issue about a bug that needs fixing. +labels: ["Issue-Bug", "Needs: Triage"] +body: + - type: checkboxes + attributes: + label: Prerequisites + options: + - label: I have written a descriptive issue title. + required: true + - label: I have searched all [_open and closed_ issues](https://github.com/PowerShell/vscode-powershell/issues?q=is%3Aissue) to ensure it has not already been reported. + - label: I have read the [troubleshooting](https://github.com/PowerShell/vscode-powershell/blob/main/docs/troubleshooting.md) guide. + - label: I am sure this issue is with the _extension itself_ and does not reproduce in a standalone [PowerShell](https://github.com/PowerShell/PowerShell/issues/new/choose) instance. + - label: I have verified that I am using the latest version of Visual Studio Code and the PowerShell extension. + - label: If this is a security issue, I have read the [security issue reporting guidance](https://github.com/PowerShell/vscode-powershell/blob/main/SECURITY.md). + - type: textarea + id: summary + attributes: + label: Summary + description: Explain the problem briefly below. + placeholder: I am experiencing a problem with X. I think Y should be happening but Z is actually happening. + validations: + required: true + - type: textarea + id: powershell-version + attributes: + label: PowerShell Version + description: Paste verbatim output from `$PSVersionTable; $Host` below. **Please include `$Host`** so we know this version is from the Extension Terminal! + render: console + placeholder: | + PS> $PSVersionTable; $Host + + Name Value + ---- ----- + PSVersion 7.4.0 + PSEdition Core + GitCommitId 7.4.0 + OS Microsoft Windows 10.0.22631 + Platform Win32NT + PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} + PSRemotingProtocolVersion 2.3 + SerializationVersion 1.1.0.1 + WSManStackVersion 3.0 + + Name : Visual Studio Code Host + Version : 2023.11.0 + InstanceId : 803ce61b-6187-4574-9c1f-827ebb11b8b6 + UI : System.Management.Automation.Internal.Host.InternalHostUserInterface + CurrentCulture : en-US + CurrentUICulture : en-US + PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy + DebuggerEnabled : True + IsRunspacePushed : False + Runspace : System.Management.Automation.Runspaces.LocalRunspace + validations: + required: true + - type: textarea + id: vscode-version + attributes: + label: Visual Studio Code Version + description: Paste verbatim output from `code --version` below. + render: console + placeholder: | + PS> code --version + + 1.57.1 + 507ce72a4466fbb27b715c3722558bb15afa9f48 + arm64 + validations: + required: true + - type: textarea + id: extension-version + attributes: + label: Extension Version + description: Paste verbatim output from `code --list-extensions --show-versions | Select-String powershell` below. + render: console + placeholder: | + PS> code --list-extensions --show-versions | Select-String powershell + + ms-vscode.powershell@2021.8.0 + validations: + required: true + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to Reproduce + description: List of steps, sample code, failing test or link to a project that reproduces the behavior. Make sure you place a stack trace inside a code (```) block to avoid linking unrelated issues. + validations: + required: true + - type: textarea + id: visuals + attributes: + label: Visuals + description: Please upload images or animations that can be used to reproduce issues in the area below. Try the [Steps Recorder](https://support.microsoft.com/en-us/windows/record-steps-to-reproduce-a-problem-46582a9b-620f-2e36-00c9-04e25d784e47) on Windows or [Screenshot](https://support.apple.com/en-us/HT208721) on macOS. + - type: textarea + id: logs + attributes: + label: Logs + description: Please upload logs collected by following these [instructions](https://github.com/PowerShell/vscode-powershell/blob/main/docs/troubleshooting.md#logs) in the area below. Be careful to scrub sensitive information! diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..f3be2597dc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 🙋 Ask a question + url: https://aka.ms/powershell-vscode-discord + about: "Find us in #vscode on the PowerShell Community Discord" diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000000..22599f9c7e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,26 @@ +name: ✨ Feature request +description: Open an issue about a potential new feature or improvement. +labels: ["Issue-Enhancement", "Needs: Triage"] +body: + - type: checkboxes + attributes: + label: Prerequisites + options: + - label: I have written a descriptive issue title. + required: true + - label: I have searched all [issues](https://github.com/PowerShell/vscode-powershell/issues?q=is%3Aissue) to ensure it has not already been reported. + required: true + - type: textarea + id: summary + attributes: + label: Summary + description: Explain the feature request below. + placeholder: I would like to do X because it would be useful for Y and I cannot currently do it with Z. + validations: + required: true + - type: textarea + id: proposed-design + attributes: + label: Proposed Design + description: Optionally explain any technical design below. + placeholder: We could accomplish this by extending X to take Y and yield Z. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..0d3e79dc8f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## PR Summary + + + +## PR Checklist + +Note: Tick the boxes below that apply to this pull request by putting an `x` between the square brackets. +Please mark anything not applicable to this PR `NA`. + +- [ ] PR has a meaningful title +- [ ] Summarized changes +- [ ] PR has tests +- [ ] This PR is ready to merge and is not work in progress + - If the PR is work in progress, please add the prefix `WIP:` to the beginning of the title and remove the prefix when the PR is ready diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000000..cc5a1aa807 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,16 @@ +changelog: + exclude: + labels: + - Ignore + authors: + - dependabot + categories: + - title: Enhancements & Features ✨ + labels: + - Issue-Enhancement + - title: Squashed Bugs 🐛 + labels: + - Issue-Bug + - title: Other Changes 🙏 + labels: + - "*" diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml new file mode 100644 index 0000000000..c53d576379 --- /dev/null +++ b/.github/workflows/ci-test.yml @@ -0,0 +1,82 @@ +name: CI Tests +permissions: + contents: read + +on: + push: + branches: [main] + pull_request: + # The branches below must be a subset of the branches above + branches: [main] + merge_group: + types: [checks_requested] + +jobs: + ci: + name: node + strategy: + matrix: + os: [windows-latest, macos-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + env: + DOTNET_NOLOGO: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + DISPLAY: ":99.0" + timeout-minutes: 10 + steps: + - name: Checkout PowerShellEditorServices + uses: actions/checkout@v4 + with: + repository: PowerShell/PowerShellEditorServices + path: PowerShellEditorServices + + - name: Checkout vscode-powershell + uses: actions/checkout@v4 + with: + path: vscode-powershell + + - name: Validate snippets JSON file + shell: pwsh + run: $null = ConvertFrom-Json -InputObject (Get-Content -Raw -Path './snippets/PowerShell.json') + working-directory: vscode-powershell + + - name: Install dotnet + uses: actions/setup-dotnet@v4 + with: + cache: true + cache-dependency-path: PowerShellEditorServices/**/*.csproj + global-json-file: PowerShellEditorServices/global.json + config-file: PowerShellEditorServices/nuget.config + + - name: Install PSResources + shell: pwsh + run: ./vscode-powershell/tools/installPSResources.ps1 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: vscode-powershell/package-lock.json + + - name: Start X virtual framebuffer + if: matrix.os == 'ubuntu-latest' + run: /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + + - name: Build, test and package + shell: pwsh + run: Invoke-Build -Configuration Release + working-directory: vscode-powershell + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: vscode-powershell-vsix-${{ matrix.os }} + path: "**/*.vsix" + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: vscode-powershell-test-results-${{ matrix.os }} + path: "**/test-results.xml" diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml new file mode 100644 index 0000000000..8ababb3c9e --- /dev/null +++ b/.github/workflows/close-stale-issues.yml @@ -0,0 +1,45 @@ +name: Issue Housekeeping + +permissions: + issues: write + +on: + schedule: + - cron: "0 * * * *" + +jobs: + stale-resolved-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + name: Label resolved issues as needing fix verification + with: + any-of-labels: "Resolution-Answered,Resolution-Duplicate,Resolution-External,Resolution-Fixed,Resolution-Inactive" + stale-issue-label: "Needs: Fix Verification" + days-before-stale: 0 + days-before-close: -1 + stale-issue-message: "This issue has been labeled as resolved, please verify the provided fix (or other reason)." + labels-to-remove-when-stale: "Needs: Maintainer Attention,Needs: Triage" + stale-fixed-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + name: Close issues needing fix verification after 1 week of inactivity + with: + stale-issue-label: "Needs: Fix Verification" + days-before-stale: -1 + labels-to-add-when-unstale: "Needs: Maintainer Attention" + close-issue-reason: completed + close-issue-message: "This issue has been labeled as needing fix verification and has not had any activity a week. It has been closed for housekeeping purposes." + stale-feedback-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + name: Close issues needing author feedback after 1 week of inactivity + with: + stale-issue-label: "Needs: Author Feedback" + days-before-stale: -1 + labels-to-add-when-unstale: "Needs: Maintainer Attention" + labels-to-remove-when-unstale: "Needs: Triage" + close-issue-reason: completed + close-issue-message: "This issue has been labeled as needing feedback and has not had any activity a week. It has been closed for housekeeping purposes." diff --git a/.gitignore b/.gitignore index c006f31f5e..e89c3c2740 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,13 @@ -bin/ -out/ +**.js +**.js.map +.vscode-test/ +*.vsix +dist/ +modules +modules/ node_modules/ -vscode-powershell.zip -vscps-preview.zip -*.vsix \ No newline at end of file +out/ +test/mocks/BinaryModule/bin/ +test/mocks/BinaryModule/obj/ +test-results.xml +tsconfig.tsbuildinfo diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..0bc786ac44 --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Andy Jordan diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000000..7f90a5dce8 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "MD013": false, + "MD033": false, + "MD022": false, + "MD024": false +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..03dacc382f --- /dev/null +++ b/.npmrc @@ -0,0 +1,8 @@ +; NOTE: All lines except the registry must be deleted for 'artifacts-npm-credprovider' to work +; We generally want to save install/update commands +save=true +; We use a public Azure Artifacts mirror +registry=https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/npm/registry/ +always-auth=true +; But we don't want references to it in the lockfile +omit-lockfile-registry-resolved=true diff --git a/.pipelines/vscode-powershell-OneBranch.yml b/.pipelines/vscode-powershell-OneBranch.yml new file mode 100644 index 0000000000..bebeb7ac58 --- /dev/null +++ b/.pipelines/vscode-powershell-OneBranch.yml @@ -0,0 +1,186 @@ +################################################################################# +# OneBranch Pipelines # +# This pipeline was created by EasyStart from a sample located at: # +# https://aka.ms/obpipelines/easystart/samples # +# Documentation: https://aka.ms/obpipelines # +# Yaml Schema: https://aka.ms/obpipelines/yaml/schema # +# Retail Tasks: https://aka.ms/obpipelines/tasks # +# Support: https://aka.ms/onebranchsup # +################################################################################# + +trigger: + - main + +schedules: + - cron: "25 9 * * 3" + displayName: Weekly CodeQL + branches: + include: + - main + always: true + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +parameters: + - name: debug + displayName: Enable debug output + type: boolean + default: false + - name: OfficialBuild + displayName: Use Official OneBranch template + type: boolean + default: false + +variables: + system.debug: ${{ parameters.debug }} + BuildConfiguration: Release + WindowsContainerImage: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest + OneBranchTemplate: ${{ iif(parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@templates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@templates') }} + +extends: + # https://aka.ms/obpipelines/templates + template: ${{ variables.OneBranchTemplate }} + parameters: + globalSdl: # https://aka.ms/obpipelines/sdl + asyncSdl: + enabled: true + forStages: [build] + featureFlags: + EnableCDPxPAT: false + WindowsHostVersion: + Version: 2022 + release: + category: NonAzure + stages: + - stage: build + jobs: + - job: main + displayName: Build package + pool: + type: windows + variables: + ob_outputDirectory: $(Build.SourcesDirectory)/out + ob_sdl_codeSignValidation_excludes: -|**\*.js # Node.js JavaScript signatures are not supported + steps: + - pwsh: | + $version = (Get-Content -Raw -Path package.json | ConvertFrom-Json).version + Write-Output "##vso[task.setvariable variable=vsixVersion;isOutput=true]$version" + $prerelease = ([semver]$version).Minor % 2 -ne 0 + if ($prerelease) { $version += "-preview" } + Write-Output "##vso[task.setvariable variable=version;isOutput=true]$version" + Write-Output "##vso[task.setvariable variable=prerelease;isOutput=true]$prerelease" + name: package + displayName: Get version from package.json + - task: onebranch.pipeline.version@1 + displayName: Set OneBranch version + inputs: + system: Custom + customVersion: $(package.version) + - task: DownloadPipelineArtifact@2 + displayName: Download Official PowerShellEditorServices + inputs: + source: specific + project: One + definition: 433526 + allowPartiallySucceededBuilds: true + buildVersionToDownload: latestFromBranch + tags: onebranch_build_type_official + branchName: refs/heads/main + artifact: drop_build_main + - task: ExtractFiles@1 + displayName: Extract PowerShellEditorServices + inputs: + archiveFilePatterns: $(Pipeline.Workspace)/PowerShellEditorServices.zip + destinationFolder: $(Build.SourcesDirectory)/modules + - pwsh: | + $manifest = Test-ModuleManifest $(Build.SourcesDirectory)/modules/PowerShellEditorServices/PowerShellEditorServices.psd1 + Write-Host Using PowerShellEditorServices v$($manifest.Version) + displayName: PowerShellEditorServices version + - pwsh: ./tools/installPSResources.ps1 -PSRepository CFS + displayName: Install PSResources + - pwsh: Invoke-Build Test -Configuration $(BuildConfiguration) + displayName: Build and test + - task: onebranch.pipeline.signing@1 + displayName: Sign 1st-party example PowerShell files + inputs: + command: sign + signing_profile: external_distribution + search_root: $(Build.SourcesDirectory)/examples + files_to_sign: "**/*.ps1;**/*.psd1;**/*.psm1" + - pwsh: Invoke-Build Package + displayName: Create package + - pwsh: | + npx vsce generate-manifest --packagePath out/powershell-$(package.vsixVersion).vsix + cp out/powershell-$(package.vsixVersion).manifest out/powershell-$(package.vsixVersion).signature.p7s + displayName: Generate VSIX manifest + - task: onebranch.pipeline.signing@1 + displayName: Sign VSIX manifest + inputs: + command: sign + cp_code: "CP-401405-VSCodePublisherSign" + search_root: $(Build.SourcesDirectory)/out + files_to_sign: "*.signature.p7s" + - stage: release + dependsOn: build + condition: and(succeeded(), ${{ eq(parameters.OfficialBuild, true) }}) + variables: + ob_release_environment: ${{ iif(parameters.OfficialBuild, 'Production', 'Test') }} + version: $[ stageDependencies.build.main.outputs['package.version'] ] + vsixVersion: $[ stageDependencies.build.main.outputs['package.vsixVersion'] ] + prerelease: $[ stageDependencies.build.main.outputs['package.prerelease'] ] + jobs: + - job: github + displayName: Publish draft to GitHub + pool: + type: release + templateContext: + inputs: + - input: pipelineArtifact + artifactName: drop_build_main + steps: + - task: GitHubRelease@1 + displayName: Create GitHub release + inputs: + gitHubConnection: github.com_andyleejordan + repositoryName: PowerShell/vscode-powershell + target: main + assets: | + $(Pipeline.Workspace)/powershell-$(vsixVersion).vsix + $(Pipeline.Workspace)/powershell-$(vsixVersion).manifest + $(Pipeline.Workspace)/powershell-$(vsixVersion).signature.p7s + tagSource: userSpecifiedTag + tag: v$(version) + isDraft: true + isPreRelease: $(prerelease) + addChangeLog: false + releaseNotesSource: inline + releaseNotesInline: "" + - job: vscode + displayName: Publish to VS Code Marketplace + pool: + type: release + templateContext: + inputs: + - input: pipelineArtifact + artifactName: drop_build_main + workflow: vsce + vsce: + serviceConnection: powershell-vscode-marketplace + vsixPath: "$(Pipeline.Workspace)/powershell-$(vsixVersion).vsix" + signaturePath: "$(Pipeline.Workspace)/powershell-$(vsixVersion).signature.p7s" + manifestPath: "$(Pipeline.Workspace)/powershell-$(vsixVersion).manifest" + preRelease: $(prerelease) + useCustomVSCE: true + feed: + organization: msazure + project: One + feedName: vsce + steps: + - pwsh: | + Write-Host Publishing: $(vsixVersion), pre-release: $(prerelease) + displayName: No-op step to satisfy pipeline requirements diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..3772289cad --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +dist/ +modules/ +out/ diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 0000000000..7b14da081f --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,21 @@ +import { defineConfig } from "@vscode/test-cli"; +import { existsSync } from "fs"; + +export default defineConfig({ + files: "test/**/*.test.ts", + // It may break CI but we'll know sooner rather than later + version: "insiders", + launchArgs: [ + // Other extensions are unnecessary while testing + "--disable-extensions", + // Undocumented but valid option to use a temporary profile for testing + "--profile-temp", + ], + workspaceFolder: `test/${existsSync("C:\\powershell-7\\pwsh.exe") ? "OneBranch" : "TestEnvironment"}.code-workspace`, + mocha: { + ui: "bdd", // describe, it, etc. + require: ["esbuild-register"], // transpile TypeScript on-the-fly + slow: 2 * 1000, // 2 seconds for slow test + timeout: 2 * 60 * 1000, // 2 minutes to allow for debugging + }, +}); diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index fab999a673..0000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "0.1.0", - "configurations": [ - { - "request": "launch", - "name": "Launch Extension", - "type": "extensionHost", - //"runtimeExecutable": "${execPath}", - "runtimeExecutable": "c:/dev/Monaco/tools/code.bat", - "args": [ - "--extensionDevelopmentPath=${workspaceRoot}", - "c:/Users/daviwil/Documents/DemoFiles" - ], - "stopOnEntry": false, - "sourceMaps": true, - "outDir": "out", - "preLaunchTask": "npm" - }, - { - "name": "Attach", - "type": "node", - "address": "localhost", - "port": 5858, - "sourceMaps": false - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 20af2f68a6..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a132a04214..0000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,30 +0,0 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// A task runner that calls a custom npm script that compiles the extension. -{ - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile"], - - // The tsc compiler is started in watching mode - "isWatching": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" -} \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore index a582583549..a056db7fb7 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,9 +1,10 @@ -.vscode/** -typings/** -**/*.ts -.gitignore -tsconfig.json -build/** -bin/EditorServices.log -bin/DebugService.log -bin/*.vshost.* \ No newline at end of file +** +!*.md +!*.txt +!dist/extension.js +!docs/ +!examples/ +!media/ +!modules/ +!snippets/ +!themes/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..c7bd8f3455 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5068 @@ +# PowerShell Extension Release History + +## v2025.5.0-preview +### Tuesday, September 09, 2025 + +With PowerShell Editor Services [v4.4.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.4.0)! + +Now with screen reader support! + +See more details at the GitHub Release for [v2025.5.0-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.5.0-preview). + +## v2025.2.0 +### Monday, June 30, 2025 + +With PowerShell Editor Services [v4.3.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.3.0)! + +New stable release! + +See more details at the GitHub Release for [v2025.2.0](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.2.0). + +## v2025.3.1-preview +### Wednesday, June 25, 2025 + +With PowerShell Editor Services [v4.3.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.3.0)! + +PowerShell installed via `brew` now found! + +See more details at the GitHub Release for [v2025.3.1-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.3.1-preview). + +## v2025.3.0-preview +### Tuesday, March 18, 2025 + +With PowerShell Editor Services [v4.3.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.3.0)! + +Now with [PSScriptAnalyzer v1.2.4](https://github.com/PowerShell/PSScriptAnalyzer/releases/tag/1.24.0) +and [PSReadLine v2.4.1-beta1](https://github.com/PowerShell/PSReadLine/releases/tag/v2.4.1-beta1). + +See more details at the GitHub Release for [v2025.3.0-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.3.0-preview). + +## v2025.0.0 +### Tuesday, January 21, 2025 + +With PowerShell Editor Services [v4.2.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.2.0)! + +New Year Update! + +PowerShell 7.4+ and Windows PowerShell 5.1 (on a best-effort basis) +are now solely supported as 7.3 LTS and 7.2 are past end-of-support. + +A major bug due to a Global Assembly Cache conflict with Serilog +when using Windows PowerShell has been resolved by removing the +troublesome dependency. This also came with a wonderful logging +overhaul for both the server and client. Thanks Justin! + +Dependencies and VS Code engine have been updated. Snippets fixed. +Extension settings are now categorized. Additional PowerShell +executable path verification fixed. + +See more details at the GitHub Release for [v2025.0.0](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.0.0). + +## v2025.1.0-preview +### Thursday, January 16, 2025 + +With PowerShell Editor Services [v4.2.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.2.0)! + +VS Code engine update and snippet fix + +See more details at the GitHub Release for [v2025.1.0-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2025.1.0-preview). + +## v2024.5.2-preview +### Wednesday, December 04, 2024 + +With PowerShell Editor Services [v4.1.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.1.0)! + +Bug fixes and build improvements. + +See more details at the GitHub Release for [v2024.5.2-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.5.2-preview). + +## v2024.5.1-preview +### Monday, November 18, 2024 + +With PowerShell Editor Services [v4.0.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v4.0.0)! + +Drop support for PowerShell <7.4 and logging overhaul + +PowerShell 7.2 LTS and 7.3 are now past end-of-support and are now unsupported. +This is an incompatible API change so we're bumping the major version +of PowerShell Editor Services. +Please update to PowerShell 7.4 LTS going forward. + +This release contains a logging overhaul which purposely removes our +dependency on Serilog and should lead to improved stability with +PowerShell 5.1 (by avoiding a major GAC assembly conflict). + +See more details at the GitHub Release for [v2024.5.1-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.5.1-preview). + +## v2024.4.0 +### Monday, November 04, 2024 + +With PowerShell Editor Services [v3.21.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.21.0)! + +Call-operator support and various bug fixes. + +See more details at the GitHub Release for [v2024.4.0](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.4.0). + +## v2024.5.0-preview +### Wednesday, October 30, 2024 + +With PowerShell Editor Services [v3.21.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.21.0)! + +Call-operator support and various bug fixes. + +See more details at the GitHub Release for [v2024.5.0-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.5.0-preview). + +## v2024.2.2 +### Friday, May 03, 2024 + +With PowerShell Editor Services [v3.20.1](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.20.1)! + +Update third-party notices. + +See more details at the GitHub Release for [v2024.2.2](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.2.2). + +## v2024.2.1 +### Tuesday, April 16, 2024 + +With PowerShell Editor Services [v3.20.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.20.0)! + +Hotfix for incorrect signing certificate, sorry about that! + +Also removed Plaster integration as we were unable to correctly sign it since we no longer own it. + +See more details at the GitHub Release for [v2024.2.1](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.2.1). + +## v2024.2.0 +### Monday, April 08, 2024 + +With PowerShell Editor Services [v3.19.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.19.0)! + +New stable release! + +This release comes with PSReadLine v2.4.0-beta0 and PSScriptAnalyzer v1.22.0. + +It includes an overhauled support for Terminal Shell Integration, +so it always supports VS Code's latest features! + +The codebase was cleaned up by the removal of several deprecated features. +Multiple bugs were fixed in the shutdown process, +default debugger configurations and IntelliSense. +A setting was added to allow the exclusion of the execution policy CLI argument at startup, +so that users in restricted environments are better able to launch the extension. + +This release went through three pre-releases. +Thank you so much to all our beta testers and users for your contributions. + +See more details at the GitHub Release for [v2024.2.0](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.2.0). + +## v2024.3.2-preview +### Wednesday, April 03, 2024 + +With PowerShell Editor Services [v3.19.0](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.19.0)! + +Overhauled Terminal Shell Integration! + +See more details at the GitHub Release for [v2024.3.2-preview](https://github.com/PowerShell/vscode-powershell/releases/tag/v2024.3.2-preview). + +## v2024.3.1-preview +### Tuesday, March 5, 2024 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🙏 [vscode-powershell #4932](https://github.com/PowerShell/vscode-powershell/pull/4934) - Don't make the Command Explorer visible by default. +- ✨ 💭 [vscode-powershell #4933](https://github.com/PowerShell/vscode-powershell/pull/4933) - Fix how we pass the log directory to Editor Services. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.18.0 + +- ✨ 📟 [PowerShellEditorServices #2148](https://github.com/PowerShell/PowerShellEditorServices/pull/2148) - Update to PSReadLine v2.4.0-beta0. +- ✨ 📟 [PowerShellEditorServices #2141](https://github.com/PowerShell/PowerShellEditorServices/pull/2141) - Update to PSScriptAnalyzer v1.22.0. +- ✨ 👷 [PowerShellEditorServices #2138](https://github.com/PowerShell/PowerShellEditorServices/pull/2138) - Fixed sln file. (Thanks @dkattan!) +- #️⃣ 🙏 [PowerShellEditorServices #2137](https://github.com/PowerShell/PowerShellEditorServices/pull/2137) - Fixed TextReader disposal. (Thanks @dkattan!) +- 🐛#️⃣ 🙏 [PowerShellEditorServices #2135](https://github.com/PowerShell/PowerShellEditorServices/pull/2135) - Fix PowerShell 7.2 E2E unit test for last change. +- ✨ 🛫 [PowerShellEditorServices #1855](https://github.com/PowerShell/PowerShellEditorServices/pull/2129) - Add sane defaults to `Start-EditorServices`. +- ✨#️⃣ 🙏 [PowerShellEditorServices #2122](https://github.com/PowerShell/PowerShellEditorServices/pull/2122) - Add `UseNullPSHostUI` config so apps hosting PSES can disable it. (Thanks @dkattan!) +- 🐛 🧠 [PowerShellEditorServices #2115](https://github.com/PowerShell/PowerShellEditorServices/pull/2115) - Added null check to `GetCompletionsAsync`. (Thanks @dkattan!) + +## v2024.3.0-preview +### Thursday, January 25, 2024 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🚂 [vscode-powershell #4902](https://github.com/PowerShell/vscode-powershell/pull/4902) - Enable the native vscode-languageclient tracing option. (Thanks @JustinGrote!) +- 🐛 📟 [vscode-powershell #4900](https://github.com/PowerShell/vscode-powershell/pull/4900) - Fix `PowerShellProcess.dipose()` to fire the `onExited` event idempotently. +- ✨ 🚂 [vscode-powershell #4892](https://github.com/PowerShell/vscode-powershell/pull/4893) - Remove deprecated features. +- 🐛 🔍 [vscode-powershell #4843](https://github.com/PowerShell/vscode-powershell/pull/4888) - Fix up debugger configuration resolvers . +- ✨ 🔧 [vscode-powershell #3034](https://github.com/PowerShell/vscode-powershell/pull/4883) - Add developer setting to disable `-ExecutionPolicy Bypass` flags. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.17.0 + +- ✨ 🚂 [PowerShellEditorServices #2132](https://github.com/PowerShell/PowerShellEditorServices/pull/2132) - Remove `PowerShellEditorServices.VSCode` module / `ContentViews` feature. +- 🐛 🔍 [PowerShellEditorServices #2130](https://github.com/PowerShell/PowerShellEditorServices/pull/2130) - Fix up debugger attach handlers. + +## v2024.0.0 +### Wednesday, January 10, 2024 + +Happy New Year! This stable release includes a bunch if improvements to the LSP server, +PowerShell Editor Services and comes with a major upgrade to our testing system. Please +see the below changelog! Going forward we plan to release on a quarterly basis. Thanks for +being such fantastic users! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4865](https://github.com/PowerShell/vscode-powershell/pull/4865) - Update CI to install .NET SDK 8.0. +- ✨ 👷 [vscode-powershell #4860](https://github.com/PowerShell/vscode-powershell/pull/4860) - Bump VS Code engine. +- #️⃣ 🙏 [vscode-powershell #4833](https://github.com/PowerShell/vscode-powershell/pull/4833) - Setup ``actions/stale`` for issue management. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.14.0-v3.16.0 + +- 🐛 📟 [vscode-powershell #4854](https://github.com/PowerShell/PowerShellEditorServices/pull/2125) - Update shell integration script to fix command decorations. +- ✨ 🚨 [PowerShellEditorServices #2124](https://github.com/PowerShell/PowerShellEditorServices/pull/2124) - Test end-to-end with PowerShell Daily. +- ✨ 👷 [PowerShellEditorServices #2114](https://github.com/PowerShell/PowerShellEditorServices/pull/2114) - Add PowerShell 7.4 SDK and `net8.0` framework. +- ✨ 🚨 [PowerShellEditorServices #2110](https://github.com/PowerShell/PowerShellEditorServices/pull/2110) - Switch to GitHub Actions for all CI. +- 🐛 🔍 [vscode-powershell #4816](https://github.com/PowerShell/PowerShellEditorServices/pull/2097) - When the built-in `$null` was watched its value was incorrect. +- 🐛 🚂 [vscode-powershell #4814](https://github.com/PowerShell/PowerShellEditorServices/pull/2096) - Allow `WorkspacePaths` to be empty if we're not in a workspace. +- 🐛 📟 [vscode-powershell #4788](https://github.com/PowerShell/PowerShellEditorServices/pull/2091) - Run `SetInitialWorkingDirectoryAsync` before `LoadProfiles`. +- 🐛 🙏 [vscode-powershell #4784](https://github.com/PowerShell/PowerShellEditorServices/pull/2090) - Ignore `didOpen` notifications for `git` schemed documents from VS Code. +- 🐛 🙏 [PowerShellEditorServices #2084](https://github.com/PowerShell/PowerShellEditorServices/pull/2084) - Add `SortDocumentSymbols` to make the outline hierarchical (again). + +## v2024.1.0-preview +### Wednesday, January 03, 2024 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4865](https://github.com/PowerShell/vscode-powershell/pull/4865) - Update CI to install .NET SDK 8.0. +- ✨ 👷 [vscode-powershell #4860](https://github.com/PowerShell/vscode-powershell/pull/4860) - Bump VS Code engine. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.16.0 + +- 🐛 📟 [vscode-powershell #4854](https://github.com/PowerShell/PowerShellEditorServices/pull/2125) - Update shell integration script to fix command decorations. +- ✨ 🚨 [PowerShellEditorServices #2124](https://github.com/PowerShell/PowerShellEditorServices/pull/2124) - Test end-to-end with PowerShell Daily. +- ✨ 👷 [PowerShellEditorServices #2114](https://github.com/PowerShell/PowerShellEditorServices/pull/2114) - Add PowerShell 7.4 SDK and `net8.0` framework. +- ✨ 🚨 [PowerShellEditorServices #2110](https://github.com/PowerShell/PowerShellEditorServices/pull/2110) - Switch to GitHub Actions for all CI. + +## v2023.11.1-preview +### Thursday, December 07, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4833](https://github.com/PowerShell/vscode-powershell/pull/4833) - Setup ``actions/stale`` for issue management. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.15.0 + +- 🐛 🔍 [vscode-powershell #4816](https://github.com/PowerShell/PowerShellEditorServices/pull/2097) - When the built-in `$null` was watched its value was incorrect. +- 🐛 🚂 [vscode-powershell #4814](https://github.com/PowerShell/PowerShellEditorServices/pull/2096) - Allow `WorkspacePaths` to be empty if we're not in a workspace. + +## v2023.11.0-preview +### Tuesday, November 07, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.14.0 + +- 🐛 📟 [vscode-powershell #4788](https://github.com/PowerShell/PowerShellEditorServices/pull/2091) - Run `SetInitialWorkingDirectoryAsync` before `LoadProfiles`. +- 🐛 🙏 [vscode-powershell #4784](https://github.com/PowerShell/PowerShellEditorServices/pull/2090) - Ignore `didOpen` notifications for `git` schemed documents from VS Code. +- 🐛 🙏 [PowerShellEditorServices #2084](https://github.com/PowerShell/PowerShellEditorServices/pull/2084) - Add `SortDocumentSymbols` to make the outline hierarchical (again). + +## v2023.8.0 +### Wednesday, October 11, 2023 + +This one took a while! As always, these changes were available in the pre-release channel +which went through six versions to get us to today's release. + +The `cwd` setting now supports `~` for home directory, relative paths, and named workspace +folders. The `additionalPowerShellExes` setting also now supports `~`, checks for missing +extensions if necessary, and both settings smartly strip surrounding quotes from the +user-supplied value. These two settings are now far more user-friendly. + +Thanks to efforts across the team, we are shipping the extension with the latest and +greatest PSReadLine, `v2.3.4`! + +The extension commands AKA `$psEditor` API was reworked and no longer mangles path casing. +It also now exposes the `CloseFile` and `SaveFile` methods, and supports multi-root +workspaces. + +A new setting `integratedConsole.startLocation` was added to control the Extension +Terminal's starting position. Thanks @krishankanumuri! + +To wrap things up, another crash when `$ErrorActionPreference = "stop"` was resolved. A +race condition for the language status item's name and icon was fixed. Our telemetry went +down after a package upgrade which required a cross-team effort to resolve (it's now also +cleaned up to send just what we're using). The DSC breakpoints capability now works as +intended without causing module load errors or emitting "sticky" progress information. A +bug when the log level was set to `None` broke the server was fixed. Our server's major +dependency, OmniSharp's `csharp-language-server-protocol`, was updated to v0.19.9 which +means we can now use the current LSP spec v3.17. We had to work with the project to +resolve a serialization regression. Finally, a lot of various build improvements were +made. + +Please note the change in our versioning schema: the middle version number no longer +corresponds to the month, but is simply incremented. Even versions are stable, and odd +versions are pre-release, with the latter purposefully being versioned higher than the +former in order to keep both channels available in the Visual Studio Code marketplace. + +Thanks to all the many community contributors whose efforts make releases such as these +possible! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🙏 [vscode-powershell #4780](https://github.com/PowerShell/vscode-powershell/pull/4780) - Stop hiding Activity Bar in ISE Mode. +- #️⃣ 🙏 [vscode-powershell #4762](https://github.com/PowerShell/vscode-powershell/pull/4763) - Downgrade `vscode-languageclient` to v8.1.0. +- ✨ 📖 [vscode-powershell #4739](https://github.com/PowerShell/vscode-powershell/pull/4739) - Add official support policy document. +- ⚡️ 💭 [vscode-powershell #4734](https://github.com/PowerShell/vscode-powershell/pull/4734) - Remove unused telemetry. +- ✨ 📖 [vscode-powershell #4729](https://github.com/PowerShell/vscode-powershell/pull/4729) - Add note about installing ESLint globally for VS Code extension. +- #️⃣ 🙏 [vscode-powershell #4711](https://github.com/PowerShell/vscode-powershell/pull/4711) - Update extension telemetry dependency. +- ✨ 👷 [vscode-powershell #4707](https://github.com/PowerShell/vscode-powershell/pull/4707) - Move `--sourcemap` to scripts instead of `Invoke-Build`. (Thanks @JustinGrote!) +- #️⃣ 🙏 [vscode-powershell #4702](https://github.com/PowerShell/vscode-powershell/pull/4704) - Use a `CustomRequest` to disconnect the dotnet debugger from attach sessions. (Thanks @JustinGrote!) +- 🐛 🙏 [vscode-powershell #2960](https://github.com/PowerShell/vscode-powershell/pull/4703) - Respect file path casing in extension commands. +- 🐛 📺 [vscode-powershell #4696](https://github.com/PowerShell/vscode-powershell/pull/4696) - Fix race condition with displaying PowerShell name on icon. +- 🐛 🔧 [vscode-powershell #4557](https://github.com/PowerShell/vscode-powershell/pull/4687) - Support `~`, `./` and named workspace folders in `cwd`. +- ✨ 🔧 [vscode-powershell #4686](https://github.com/PowerShell/vscode-powershell/pull/4686) - Enhance `additionalPowerShellExes` setting. +- #️⃣ 🙏 [vscode-powershell #4684](https://github.com/PowerShell/vscode-powershell/pull/4684) - Remove LinkEditorServices comment in development.md. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4676](https://github.com/PowerShell/vscode-powershell/pull/4676) - Move ESLint Dependabot group to npm. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4667](https://github.com/PowerShell/vscode-powershell/pull/4667) - Bump ESLint packages to v6. +- #️⃣ 🙏 [vscode-powershell #4661](https://github.com/PowerShell/vscode-powershell/pull/4661) - Update readme. +- 🐛 👷 [vscode-powershell #4651](https://github.com/PowerShell/vscode-powershell/pull/4651) - Fix unit test for Windows running on arm64. +- ✨ 👷 [vscode-powershell #4641](https://github.com/PowerShell/vscode-powershell/pull/4641) - Update VS Code engine to 1.79.0. +- ✨ 🔧 [vscode-powershell #4181](https://github.com/PowerShell/vscode-powershell/pull/4639) - Add `startLocation` setting for Extension Terminal. (Thanks @krishankanumuri!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.13.0 + +- ✨ 📟 [PowerShellEditorServices #2087](https://github.com/PowerShell/PowerShellEditorServices/pull/2087) - Upgrade bundled PSReadLine module to v2.3.4. +- 🐛 🔍 [PowerShellEditorServices #2081](https://github.com/PowerShell/PowerShellEditorServices/pull/2081) - Silence progress output of `Get-DscResource` (take two). +- 🐛 🚂 [PowerShellEditorServices #2083](https://github.com/PowerShell/PowerShellEditorServices/pull/2083) - Upgrade OmniSharp to v0.19.9. +- ✨ 📟 [PowerShellEditorServices #2080](https://github.com/PowerShell/PowerShellEditorServices/pull/2080) - Bump to new PSReadLine stable release v2.3.3. +- 🐛 🔍 [PowerShellEditorServices #2068](https://github.com/PowerShell/PowerShellEditorServices/pull/2068) - Wrap import of DSC module with `ProgressPreference = SilentlyContinue`. +- 🐛 💭 [vscode-powershell #4735](https://github.com/PowerShell/PowerShellEditorServices/pull/2066) - Add `None` to `PsesLogLevel` enum. +- ⚡️ 💭 [PowerShellEditorServices #2065](https://github.com/PowerShell/PowerShellEditorServices/pull/2065) - Remove unused telemetry. +- 🐛 🔍 [vscode-powershell #3904](https://github.com/PowerShell/PowerShellEditorServices/pull/2064) - Fix debugging script blocks that aren't in files. +- 🐛 🚂 [vscode-powershell #3971](https://github.com/PowerShell/PowerShellEditorServices/pull/2062) - Import `PSDesiredStateConfiguration` by name. +- 🐛 🔍 [PowerShellEditorServices #2037](https://github.com/PowerShell/PowerShellEditorServices/pull/2058) - Ignore not finding DSC module. +- ✨ 🚨 [vscode-powershell #3484](https://github.com/PowerShell/PowerShellEditorServices/pull/2055) - Move `ConstrainedLanguageMode` tests to separate task. +- ✨ 📟 [PowerShellEditorServices #2054](https://github.com/PowerShell/PowerShellEditorServices/pull/2054) - Update PSReadLine to `v2.3.2-beta2`. +- ✨ 🙏 [PowerShellEditorServices #2053](https://github.com/PowerShell/PowerShellEditorServices/pull/2053) - Fix up extension API. +- 🐛 📟 [PowerShellEditorServices #2050](https://github.com/PowerShell/PowerShellEditorServices/pull/2052) - Fix shell integration for PowerShell 5.1 with strict mode. +- ✨ 📟 [PowerShellEditorServices #2046](https://github.com/PowerShell/PowerShellEditorServices/pull/2046) - Bump PSReadLine to beta for extension preview. + +## v2023.9.5-preview +### Tuesday, October 10, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🙏 [vscode-powershell #4780](https://github.com/PowerShell/vscode-powershell/pull/4780) - Stop hiding Activity Bar in ISE Mode. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.13.0 + +- ✨ 📟 [PowerShellEditorServices #2087](https://github.com/PowerShell/PowerShellEditorServices/pull/2087) - Upgrade bundled PSReadLine module to v2.3.4. + +## v2023.9.4-preview +### Friday, September 29, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4762](https://github.com/PowerShell/vscode-powershell/pull/4763) - Downgrade `vscode-languageclient` to v8.1.0. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.12.0 + +Just updating the client above. + +## v2023.9.3-preview +### Thursday, September 28, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📖 [vscode-powershell #4739](https://github.com/PowerShell/vscode-powershell/pull/4739) - Add official support policy document. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.12.0 + +- 🐛 🔍 [PowerShellEditorServices #2081](https://github.com/PowerShell/PowerShellEditorServices/pull/2081) - Silence progress output of `Get-DscResource` (take two). +- 🐛 🚂 [PowerShellEditorServices #2083](https://github.com/PowerShell/PowerShellEditorServices/pull/2083) - Upgrade OmniSharp to v0.19.9. +- ✨ 📟 [PowerShellEditorServices #2080](https://github.com/PowerShell/PowerShellEditorServices/pull/2080) - Bump to new PSReadLine stable release v2.3.3. +- 🐛 🔍 [PowerShellEditorServices #2068](https://github.com/PowerShell/PowerShellEditorServices/pull/2068) - Wrap import of DSC module with `ProgressPreference = SilentlyContinue`. + +## v2023.9.2-preview +### Wednesday, September 13, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ⚡️ 💭 [vscode-powershell #4734](https://github.com/PowerShell/vscode-powershell/pull/4734) - Remove unused telemetry. +- ✨ 📖 [vscode-powershell #4729](https://github.com/PowerShell/vscode-powershell/pull/4729) - Add note about installing ESLint globally for VS Code extension. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.11.0 + +- 🐛 💭 [vscode-powershell #4735](https://github.com/PowerShell/PowerShellEditorServices/pull/2066) - Add `None` to `PsesLogLevel` enum. +- ⚡️ 💭 [PowerShellEditorServices #2065](https://github.com/PowerShell/PowerShellEditorServices/pull/2065) - Remove unused telemetry. +- 🐛 🔍 [vscode-powershell #3904](https://github.com/PowerShell/PowerShellEditorServices/pull/2064) - Fix debugging script blocks that aren't in files. +- 🐛 🚂 [vscode-powershell #3971](https://github.com/PowerShell/PowerShellEditorServices/pull/2062) - Import `PSDesiredStateConfiguration` by name. + +## v2023.9.1-preview +### Friday, August 25, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4711](https://github.com/PowerShell/vscode-powershell/pull/4711) - Update extension telemetry dependency. +- ✨ 👷 [vscode-powershell #4707](https://github.com/PowerShell/vscode-powershell/pull/4707) - Move `--sourcemap` to scripts instead of `Invoke-Build`. (Thanks @JustinGrote!) +- #️⃣ 🙏 [vscode-powershell #4702](https://github.com/PowerShell/vscode-powershell/pull/4704) - Use a CustomRequest to disconnect the dotnet debugger from attach sessions.. (Thanks @JustinGrote!) +- 🐛 🙏 [vscode-powershell #2960](https://github.com/PowerShell/vscode-powershell/pull/4703) - Respect file path casing in extension commands. +- 🐛 📺 [vscode-powershell #4696](https://github.com/PowerShell/vscode-powershell/pull/4696) - Fix race condition with displaying PowerShell name on icon. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.10.0 + +- 🐛 🔍 [PowerShellEditorServices #2037](https://github.com/PowerShell/PowerShellEditorServices/pull/2058) - Ignore not finding DSC module. +- ✨ 🚨 [vscode-powershell #3484](https://github.com/PowerShell/PowerShellEditorServices/pull/2055) - Move `ConstrainedLanguageMode` tests to separate task. +- ✨ 📟 [PowerShellEditorServices #2054](https://github.com/PowerShell/PowerShellEditorServices/pull/2054) - Update PSReadLine to `v2.3.2-beta2`. +- ✨ 🙏 [PowerShellEditorServices #2053](https://github.com/PowerShell/PowerShellEditorServices/pull/2053) - Fix up extension API. +- 🐛 📟 [PowerShellEditorServices #2050](https://github.com/PowerShell/PowerShellEditorServices/pull/2052) - Fix shell integration for PowerShell 5.1 with strict mode. + +## v2023.9.0-preview +### Wednesday, August 09, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🔧 [vscode-powershell #4557](https://github.com/PowerShell/vscode-powershell/pull/4687) - Support `~`, `./` and named workspace folders in `cwd`. +- ✨ 🔧 [vscode-powershell #4686](https://github.com/PowerShell/vscode-powershell/pull/4686) - Enhance `additionalPowerShellExes` setting. +- #️⃣ 🙏 [vscode-powershell #4684](https://github.com/PowerShell/vscode-powershell/pull/4684) - Remove LinkEditorServices comment in development.md. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4676](https://github.com/PowerShell/vscode-powershell/pull/4676) - Move ESLint Dependabot group to npm. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4667](https://github.com/PowerShell/vscode-powershell/pull/4667) - Bump ESLint packages to v6. +- #️⃣ 🙏 [vscode-powershell #4661](https://github.com/PowerShell/vscode-powershell/pull/4661) - Update readme. +- 🐛 👷 [vscode-powershell #4651](https://github.com/PowerShell/vscode-powershell/pull/4651) - Fix unit test for Windows running on arm64. +- ✨ 👷 [vscode-powershell #4641](https://github.com/PowerShell/vscode-powershell/pull/4641) - Update VS Code engine to 1.79.0. +- ✨ 🔧 [vscode-powershell #4181](https://github.com/PowerShell/vscode-powershell/pull/4639) - Add `startLocation` setting for Extension Terminal. (Thanks @krishankanumuri!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.9.0 + +- ✨ 📟 [PowerShellEditorServices #2046](https://github.com/PowerShell/PowerShellEditorServices/pull/2046) - Bump PSReadLine to beta for extension preview. + +## v2023.6.0 +### Tuesday, June 06, 2023 + +This release focused on fixing the "disappearing output" bug present in PowerShell 5.1, +where an old bug with the `Out-Default` cmdlet's `TranscribeOnly` flag could cause the +Extension Terminal to stop displaying output. While the root cause in the cmdlet is fixed +upstream, that fix is only in PowerShell Core, and not backported to Windows PowerShell. +We were able to workaround the bug with a very careful use of reflection to reset the +flag's value at the appropriate times (see the three takes it took to get this right). + +We also refactored the client's startup logic so that it should be impossible to create a +ghost Extension Terminal, and the error handling and logging was given a thorough cleanup. +Finally, two noisy bugs were fixed: when completions are canceled the useless error +message is no longer produced, and when the DSC module is only loaded in one attempt +instead of repeatedly. + +Please enjoy these bugfixes! We sure enjoy making the extension more stable. + +Don't forget to catch Andy's talk, "PowerShell Extension for VS Code Deep Dive" at +[PSConfEU](https://psconf.eu) on Thursday, 22 June 2023! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4599](https://github.com/PowerShell/vscode-powershell/pull/4599) - Make `sessionManager.start()` idempotent. +- 🐛 🛫 [vscode-powershell #4584](https://github.com/PowerShell/vscode-powershell/pull/4584) - Robustify startup, error handling, and logging. +- 🐛 📺 [vscode-powershell #4553](https://github.com/PowerShell/vscode-powershell/pull/4570) - Remove the MSI install logic (it's unreliable). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.7 + +- 🐛 📟 [PowerShellEditorServices #2031](https://github.com/PowerShell/PowerShellEditorServices/pull/2031) - Fix the `TranscribeOnly` bug (take three). +- 🐛 💭 [vscode-powershell #4582](https://github.com/PowerShell/PowerShellEditorServices/pull/2028) - Ignore cancellation of completion requests. +- 🐛 📟 [vscode-powershell #3991](https://github.com/PowerShell/PowerShellEditorServices/pull/2026) - Fix the `TranscribeOnly` bug (take two). +- 🐛 📟 [vscode-powershell #3991](https://github.com/PowerShell/PowerShellEditorServices/pull/2023) - Fix disappearing output in PowerShell 5.1. +- 🐛 🔍 [PowerShellEditorServices #2020](https://github.com/PowerShell/PowerShellEditorServices/pull/2020) - Fix repeated failure to load DSC module. + +## v2023.5.4-preview +### Tuesday, May 30, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +No changes, just pulling in PSES. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.7 + +- 🐛 📟 [PowerShellEditorServices #2031](https://github.com/PowerShell/PowerShellEditorServices/pull/2031) - Fix the `TranscribeOnly` bug (take three). + +## v2023.5.3-preview +### Wednesday, May 24, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4599](https://github.com/PowerShell/vscode-powershell/pull/4599) - Make `sessionManager.start()` idempotent. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.6 + +No changes. + +## v2023.5.2-preview +### Tuesday, May 23, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🛫 [vscode-powershell #4584](https://github.com/PowerShell/vscode-powershell/pull/4584) - Robustify startup, error handling, and logging. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.6 + +- 🐛 💭 [vscode-powershell #4582](https://github.com/PowerShell/PowerShellEditorServices/pull/2028) - Ignore cancellation of completion requests. +- 🐛 📟 [vscode-powershell #3991](https://github.com/PowerShell/PowerShellEditorServices/pull/2026) - Fix the `TranscribeOnly` bug (take two). + +## v2023.5.1-preview +### Friday, May 12, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 📺 [vscode-powershell #4553](https://github.com/PowerShell/vscode-powershell/pull/4570) - Remove the MSI install logic (it's unreliable). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.5 + +- 🐛 📟 [vscode-powershell #3991](https://github.com/PowerShell/PowerShellEditorServices/pull/2023) - Fix disappearing output in PowerShell 5.1. +- 🐛 🔍 [PowerShellEditorServices #2020](https://github.com/PowerShell/PowerShellEditorServices/pull/2020) - Fix repeated failure to load DSC module. + +## v2023.5.0 +### Wednesday, May 03, 2023 + +This release focused on include Justin Grote's new "attach .NET debugger" debug +configuration for binary PowerShell modules, and on handling start-up failures more +gracefully. If the start-up fails because the configured PowerShell is out-of-date, +instead of a confusing "undefined" error message we now detect the problem, inform the +user with a pop-up message of it, and offer to open the installation and/or update +instructions. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #4549](https://github.com/PowerShell/vscode-powershell/pull/4549) - Update readme and troubleshooting docs. +- ✨ 🙏 [vscode-powershell #4548](https://github.com/PowerShell/vscode-powershell/pull/4548) - Use named debug configurations instead of duplicating them. +- 🐛 🚨 [vscode-powershell #4547](https://github.com/PowerShell/vscode-powershell/pull/4547) - Fix flaky test. +- 🐛 🛫 [vscode-powershell #4543](https://github.com/PowerShell/vscode-powershell/pull/4543) - Update startup logic to handle session failure reasons. +- #️⃣ 🙏 [vscode-powershell #4534](https://github.com/PowerShell/vscode-powershell/pull/4534) - Add ESBuild Problem Matcher Extension. (Thanks @JustinGrote!) +- 🐛 🙏 [vscode-powershell #4521](https://github.com/PowerShell/vscode-powershell/pull/4532) - Handle end-of-support PowerShell with error message. +- ✨ 👷 [vscode-powershell #4518](https://github.com/PowerShell/vscode-powershell/pull/4518) - Enable Mocha Test Explorer Integration. (Thanks @JustinGrote!) +- 🐛 🔍 [vscode-powershell #4517](https://github.com/PowerShell/vscode-powershell/pull/4517) - Fix `attachDotnetDebugger` with custom config. (Thanks @fflaten!) +- 🐛 🔍 [vscode-powershell #4516](https://github.com/PowerShell/vscode-powershell/pull/4516) - Add new debug configurations to `package.json`. (Thanks @JustinGrote!) +- #️⃣ 🔍 [vscode-powershell #4511](https://github.com/PowerShell/vscode-powershell/pull/4511) - Add additional debug configuration templates for Pester and binary modules. (Thanks @JustinGrote!) +- #️⃣ 🔍🙏 [vscode-powershell #4510](https://github.com/PowerShell/vscode-powershell/pull/4510) - Improve extension authoring experience with new Build Tasks and Launch Configs. (Thanks @JustinGrote!) +- ✨ 👷 [vscode-powershell #4502](https://github.com/PowerShell/vscode-powershell/pull/4503) - Enable VS Code unit tests in Linux CI. +- ✨ 🙏 [vscode-powershell #4498](https://github.com/PowerShell/vscode-powershell/pull/4500) - Enable ESLint `explicit-function-return-type`. +- ✨ 🔍 [vscode-powershell #3903](https://github.com/PowerShell/vscode-powershell/pull/3903) - Add `attachDotnetDebugger` debug option. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.4 + +- 🐛 🛫 [vscode-powershell #4509](https://github.com/PowerShell/PowerShellEditorServices/pull/2018) - Set session failure with reason when applicable. +- ✨ 📖 [PowerShellEditorServices #2016](https://github.com/PowerShell/PowerShellEditorServices/pull/2016) - Add guide to configure Neovim. (Thanks @csc027!) + +## v2023.4.1-preview +### Tuesday, April 25, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🛫 [vscode-powershell #4543](https://github.com/PowerShell/vscode-powershell/pull/4543) - Update startup logic to handle session failure reasons. +- #️⃣ 🙏 [vscode-powershell #4534](https://github.com/PowerShell/vscode-powershell/pull/4534) - Add ESBuild Problem Matcher Extension. (Thanks @JustinGrote!) +- 🐛 🙏 [vscode-powershell #4521](https://github.com/PowerShell/vscode-powershell/pull/4532) - Handle end-of-support PowerShell with error message. +- ✨ 👷 [vscode-powershell #4518](https://github.com/PowerShell/vscode-powershell/pull/4518) - Enable Mocha Test Explorer Integration. (Thanks @JustinGrote!) +- 🐛 🔍 [vscode-powershell #4517](https://github.com/PowerShell/vscode-powershell/pull/4517) - Fix `attachDotnetDebugger` with custom config. (Thanks @fflaten!) +- 🐛 🔍 [vscode-powershell #4516](https://github.com/PowerShell/vscode-powershell/pull/4516) - Add new debug configurations to `package.json`. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.4 + +- 🐛 🛫 [vscode-powershell #4509](https://github.com/PowerShell/PowerShellEditorServices/pull/2018) - Set session failure with reason when applicable. +- ✨ 📖 [PowerShellEditorServices #2016](https://github.com/PowerShell/PowerShellEditorServices/pull/2016) - Add guide to configure Neovim. (Thanks @csc027!) + +## v2023.4.0-preview +### Wednesday, April 12, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🔍 [vscode-powershell #4511](https://github.com/PowerShell/vscode-powershell/pull/4511) - Add additional debug configuration templates for Pester and binary modules. (Thanks @JustinGrote!) +- #️⃣ 🔍🙏 [vscode-powershell #4510](https://github.com/PowerShell/vscode-powershell/pull/4510) - Improve extension authoring experience with new Build Tasks and Launch Configs. (Thanks @JustinGrote!) +- ✨ 👷 [vscode-powershell #4502](https://github.com/PowerShell/vscode-powershell/pull/4503) - Enable VS Code unit tests in Linux CI. +- ✨ 🙏 [vscode-powershell #4498](https://github.com/PowerShell/vscode-powershell/pull/4500) - Enable ESLint `explicit-function-return-type`. +- ✨ 🔍 [vscode-powershell #3903](https://github.com/PowerShell/vscode-powershell/pull/3903) - Add `attachDotnetDebugger` debug option. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.3 + +- No update. + +## v2023.3.3 +### Thursday, March 30, 2023 + +This is primarily a bug-fix focused release, and we want to say thanks to all our loyal +preview extension users! The "PowerShell Preview" extension has now been officially +deprecated, with "preview" releases now available via the "pre-release" option on the +stable "PowerShell" extension in the marketplace. While you should be migrated +automatically, feel free to just uninstall the preview and install the now one-and-only +extension, but please keep testing our pre-releases! This change makes it much simpler to +use, as you no longer have to switch between two different extensions and instead can use +VS Code's marketplace to install your choice of version! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #4481](https://github.com/PowerShell/vscode-powershell/pull/4481) - Remove problematic `[RepoNames]` PowerShell class. +- ✨ 👷 [vscode-powershell #4464](https://github.com/PowerShell/vscode-powershell/pull/4464) - Remove `preview` label from marketplace. +- ✨ 👷 [vscode-powershell #3716](https://github.com/PowerShell/vscode-powershell/pull/4462) - Adopt the pre-release extension feature. +- 🐛 ✂️ [vscode-powershell #4455](https://github.com/PowerShell/vscode-powershell/pull/4455) - Fix up "Calculated Property" snippet. (Thanks @DougDyreng!) +- 🐛 📺 [vscode-powershell #4453](https://github.com/PowerShell/vscode-powershell/pull/4454) - Fix `GenerateBugReport` command to pre-fill template. +- ✨ 🙏 [vscode-powershell #4425](https://github.com/PowerShell/vscode-powershell/pull/4425) - Hide last line in folded ranges for ISE Mode. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4417](https://github.com/PowerShell/vscode-powershell/pull/4417) - Fix up dependencies. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.3 + +- Documentation update and CI fix. +- 🐛 🙏 [vscode-powershell #4443](https://github.com/PowerShell/PowerShellEditorServices/pull/2006) - Fix declaration detection for variables with type constraints. +- ✨ 🙏 [vscode-powershell #3604](https://github.com/PowerShell/PowerShellEditorServices/pull/2003) - Add document symbols for `#region`. +- ✨ 🙏 [PowerShellEditorServices #2000](https://github.com/PowerShell/PowerShellEditorServices/pull/2000) - Code clean-up and fixing end-to-end tests. +- 🐛 🐢 [PowerShellEditorServices #1998](https://github.com/PowerShell/PowerShellEditorServices/pull/1998) - Support module-qualified calls for Pester keywords. (Thanks @fflaten!) +- 🐛 🙏 [vscode-powershell #3192](https://github.com/PowerShell/PowerShellEditorServices/pull/1997) - Fix New-EditorFile adding content in current file. (Thanks @fflaten!) + +## v2023.3.2-preview +### Monday, March 27, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #4481](https://github.com/PowerShell/vscode-powershell/pull/4481) - Remove problematic `[RepoNames]` PowerShell class. +- ✨ 👷 [vscode-powershell #4464](https://github.com/PowerShell/vscode-powershell/pull/4464) - Remove `preview` label from marketplace. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.3 + +- Documentation update and CI fix. + +## v2023.3.1-preview +### Wednesday, March 15, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 👷 [vscode-powershell #3716](https://github.com/PowerShell/vscode-powershell/pull/4462) - Adopt the pre-release extension feature. +- 🐛 ✂️ [vscode-powershell #4455](https://github.com/PowerShell/vscode-powershell/pull/4455) - Fix up "Calculated Property" snippet. (Thanks @DougDyreng!) +- 🐛 📺 [vscode-powershell #4453](https://github.com/PowerShell/vscode-powershell/pull/4454) - Fix `GenerateBugReport` command to pre-fill template. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.2 + +No changes. + +## v2023.3.0-preview +### Thursday, March 09, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🙏 [vscode-powershell #4425](https://github.com/PowerShell/vscode-powershell/pull/4425) - Hide last line in folded ranges for ISE Mode. (Thanks @fflaten!) +- #️⃣ 🙏 [vscode-powershell #4417](https://github.com/PowerShell/vscode-powershell/pull/4417) - Fix up dependencies. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.2 + +- 🐛 🙏 [vscode-powershell #4443](https://github.com/PowerShell/PowerShellEditorServices/pull/2006) - Fix declaration detection for variables with type constraints. +- ✨ 🙏 [vscode-powershell #3604](https://github.com/PowerShell/PowerShellEditorServices/pull/2003) - Add document symbols for `#region`. +- ✨ 🙏 [PowerShellEditorServices #2000](https://github.com/PowerShell/PowerShellEditorServices/pull/2000) - Code clean-up and fixing end-to-end tests. +- 🐛 🐢 [PowerShellEditorServices #1998](https://github.com/PowerShell/PowerShellEditorServices/pull/1998) - Support module-qualified calls for Pester keywords. (Thanks @fflaten!) +- 🐛 🙏 [vscode-powershell #3192](https://github.com/PowerShell/PowerShellEditorServices/pull/1997) - Fix New-EditorFile adding content in current file. (Thanks @fflaten!) + +## v2023.2.1 +### Thursday, February 23, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Primarily an update to v3.8 of PowerShell Editor Services, as previewed over February. +Includes a massive enhancement to extension's symbol support, nearly completing the +[Consistent References][] project, with the final work in an upcoming preview. Enjoy! + +[Consistent References]: https://github.com/PowerShell/vscode-powershell/projects/13 + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.1 + +- ✨ 📁 [vscode-powershell #2112](https://github.com/PowerShell/PowerShellEditorServices/pull/1995) - Add `WorkspaceFolders` and use it when enumerating files. +- ✨ 🙏 [vscode-powershell #1481](https://github.com/PowerShell/PowerShellEditorServices/pull/1993) - Count `${Function:My-Function}` as a function reference. +- 🐛 🙏 [vscode-powershell #1089](https://github.com/PowerShell/PowerShellEditorServices/pull/1990) - Strip scope from function references. +- 🐛 🙏 [PowerShellEditorServices #1989](https://github.com/PowerShell/PowerShellEditorServices/pull/1989) - Keep only first assignment as declaration. +- ✨ 🐢 [PowerShellEditorServices #1988](https://github.com/PowerShell/PowerShellEditorServices/pull/1988) - Support Run/Debug tests in PSKoans-files. (Thanks @fflaten!) + +In the PR below we rewrote all the symbol logic. Classes (and their properties and +methods) are now proper symbols. Instead of a dozen similar-yet-different Abstract Symbol +Tree (AST) PowerShell script visitors handling different parts of each symbol-related +request, we have a single visitor that builds a cached dictionary of symbols for each +file. This was a massive simplification of the code that also leads to huge performance +improvements across all the symbol related features: + +- [Go to Symbol in Workspace](https://code.visualstudio.com/Docs/editor/editingevolved#_open-symbol-by-name) +- [Go to Symbol in Editor](https://code.visualstudio.com/Docs/editor/editingevolved#_go-to-symbol) +- [Go to Definition](https://code.visualstudio.com/Docs/editor/editingevolved#_go-to-definition) +- [Go to References / CodeLens](https://code.visualstudio.com/Docs/editor/editingevolved#_reference-information) +- [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view) + +Please try it out and give us feedback! There's plenty of room for more improvement, and +this will be much easier going forward. + +- ✨ 🙏 [PowerShellEditorServices #1984](https://github.com/PowerShell/PowerShellEditorServices/pull/1984) - Integrating class symbol support. + +## v2023.2.1-preview +### Monday, February 13, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Includes the updates from PowerShell Editor Services below: + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.1 + +- ✨ 📁 [vscode-powershell #2112](https://github.com/PowerShell/PowerShellEditorServices/pull/1995) - Add `WorkspaceFolders` and use it when enumerating files. +- ✨ 🙏 [vscode-powershell #1481](https://github.com/PowerShell/PowerShellEditorServices/pull/1993) - Count `${Function:My-Function}` as a function reference. +- 🐛 🙏 [vscode-powershell #1089](https://github.com/PowerShell/PowerShellEditorServices/pull/1990) - Strip scope from function references. +- 🐛 🙏 [PowerShellEditorServices #1989](https://github.com/PowerShell/PowerShellEditorServices/pull/1989) - Keep only first assignment as declaration. +- ✨ 🐢 [PowerShellEditorServices #1988](https://github.com/PowerShell/PowerShellEditorServices/pull/1988) - Support Run/Debug tests in PSKoans-files. (Thanks @fflaten!) + +## v2023.2.0-preview +### Thursday, February 02, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +This preview includes all the work outlined below for enhanced symbol support. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.8.0 + +In the PR below we rewrote all the symbol logic. Classes (and their properties and +methods) are now proper symbols. Instead of a dozen similar-yet-different Abstract Symbol +Tree (AST) PowerShell script visitors handling different parts of each symbol-related +request, we have a single visitor that builds a cached dictionary of symbols for each +file. This was a massive simplification of the code that also leads to huge performance +improvements across all the symbol related features: + +- [Go to Symbol in Workspace](https://code.visualstudio.com/Docs/editor/editingevolved#_open-symbol-by-name) +- [Go to Symbol in Editor](https://code.visualstudio.com/Docs/editor/editingevolved#_go-to-symbol) +- [Go to Definition](https://code.visualstudio.com/Docs/editor/editingevolved#_go-to-definition) +- [Go to References / CodeLens](https://code.visualstudio.com/Docs/editor/editingevolved#_reference-information) +- [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view) + +Please try it out and give us feedback! There's plenty of room for more improvement, and +this will be much easier going forward. + +- ✨ 🙏 [PowerShellEditorServices #1984](https://github.com/PowerShell/PowerShellEditorServices/pull/1984) - Integrating class symbol support. + +## v2023.1.0 +### Wednesday, January 18, 2023 + +First stable release for the new year, includes a multitude of fixes for the debugger! +Expanding variables with properties that are inaccessible no longer causes a short-circuit +preventing the rest of the properties from being expanded, variable values whose expansion +results in PowerShell code being executed now works as expected, and in general all the +correct properties are now present. We look forward to adding the ability to view static +and private fields in a future update. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #4357](https://github.com/PowerShell/vscode-powershell/pull/4357) - Fix `@vscode/vsce` dependency after its rename. +- 🐛 ✂️ [vscode-powershell #4346](https://github.com/PowerShell/vscode-powershell/pull/4347) - Fix class snippet (unnecessary space between `<` and `#`). (Thanks @ALiwoto!) +- 🐛 🛫 [vscode-powershell #4329](https://github.com/PowerShell/vscode-powershell/pull/4331) - Automatically find "PowerShell Daily" at its common path. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.3 + +- 🐛 🚂 [vscode-powershell #4343](https://github.com/PowerShell/PowerShellEditorServices/pull/1982) - Update VS Code shell integration script. +- ✨ 🙏 [PowerShellEditorServices #1981](https://github.com/PowerShell/PowerShellEditorServices/pull/1981) - Make `Set-ScriptExtent` not slow. +- 🐛 🙏 [PowerShellEditorServices #1959](https://github.com/PowerShell/PowerShellEditorServices/pull/1980) - Use an empty array instead of `null`. +- 🐛 🔍 [vscode-powershell #4174](https://github.com/PowerShell/PowerShellEditorServices/pull/1975) - Fix several bugs in the debugger. +- #️⃣ 🙏 [PowerShellEditorServices #1973](https://github.com/PowerShell/PowerShellEditorServices/pull/1973) - Update `Microsoft.PowerShell.SDK` with workaround. + +## v2023.1.0-preview +### Wednesday, January 04, 2023 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #4357](https://github.com/PowerShell/vscode-powershell/pull/4357) - Fix `@vscode/vsce` dependency after its rename. +- 🐛 ✂️ [vscode-powershell #4346](https://github.com/PowerShell/vscode-powershell/pull/4347) - Fix class snippet (unnecessary space between `<` and `#`). (Thanks @ALiwoto!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.3 + +- 🐛 🚂 [vscode-powershell #4343](https://github.com/PowerShell/PowerShellEditorServices/pull/1982) - Update VS Code shell integration script. +- ✨ 🙏 [PowerShellEditorServices #1981](https://github.com/PowerShell/PowerShellEditorServices/pull/1981) - Make `Set-ScriptExtent` not slow. +- 🐛 🙏 [PowerShellEditorServices #1959](https://github.com/PowerShell/PowerShellEditorServices/pull/1980) - Use an empty array instead of `null`. + +## v2022.12.2-preview +### Tuesday, December 20, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🛫 [vscode-powershell #4329](https://github.com/PowerShell/vscode-powershell/pull/4331) - Automatically find "PowerShell Daily" at its common path. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.2 + +- 🐛 🔍 [vscode-powershell #4174](https://github.com/PowerShell/PowerShellEditorServices/pull/1975) - Fix several bugs in the debugger. +- #️⃣ 🙏 [PowerShellEditorServices #1973](https://github.com/PowerShell/PowerShellEditorServices/pull/1973) - Update `Microsoft.PowerShell.SDK` with workaround. + +## v2022.12.1 +### Thursday, December 15, 2022 + +This release brings a variety of bugfixes and feature improvements, including everyone's +favorite: [VS Code Terminal Shell Integration][shell-integration] in the PowerShell +Extension Terminal! We overhauled the PowerShell update notification feature, with support +for more platforms and architectures. Also checkout the revamped settings descriptions in +VS Code, complete with formatting and hyperlinks. + +[shell-integration]: https://code.visualstudio.com/docs/terminal/shell-integration + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🔧 [vscode-powershell #4315](https://github.com/PowerShell/vscode-powershell/pull/4320) - Enhance (and correct) our settings' descriptions using markdown. +- 🐛 ✂️ [vscode-powershell #3964](https://github.com/PowerShell/vscode-powershell/pull/4311) - Fix `try-catch` snippet (missing a `$`). +- 🐛 🔧 [vscode-powershell #4308](https://github.com/PowerShell/vscode-powershell/pull/4308) - Restore original settings after disabling ISE mode. +- ✨ 🚂 [vscode-powershell #4301](https://github.com/PowerShell/vscode-powershell/pull/4307) - Bump engine to 1.67.0 and update panel graphics. +- ✨ 🛫 [vscode-powershell #3226](https://github.com/PowerShell/vscode-powershell/pull/4306) - Rewrite `UpdatePowerShell` feature. +- 🐛 🛫 [vscode-powershell #3435](https://github.com/PowerShell/vscode-powershell/pull/4298) - Skip auto-update on unsupported Windows architectures. +- 🐛 🔧 [vscode-powershell #4297](https://github.com/PowerShell/vscode-powershell/pull/4297) - Fix small bug with `powerShellDefaultVersion` warning. +- ✨ 🔧 [vscode-powershell #4129](https://github.com/PowerShell/vscode-powershell/pull/4295) - Show warning if `powerShellDefaultVersion` is set but not found. +- ✨ 📁 [vscode-powershell #2153](https://github.com/PowerShell/vscode-powershell/pull/3796) - Fully support multi-root workspaces. +- 🐛 💭 [vscode-powershell #4202](https://github.com/PowerShell/vscode-powershell/pull/4276) - Make `Logger.WriteLine` thread-safe and fix bug with UNC paths. +- ✨ 📟 [vscode-powershell #4271](https://github.com/PowerShell/vscode-powershell/pull/4271) - Send shell integration setting to server. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.1 + +- 🐛 🚂 [vscode-powershell #4212](https://github.com/PowerShell/PowerShellEditorServices/pull/1970) - Fix `ShowHelpHandler` by running with `RequiresForeground`. +- ✨ 👷 [PowerShellEditorServices #1879](https://github.com/PowerShell/PowerShellEditorServices/pull/1967) - Drop support for end-of-life PowerShell 7.0. +- ✨ 🛫 [PowerShellEditorServices #1965](https://github.com/PowerShell/PowerShellEditorServices/pull/1965) - Send `GitCommitId` over `GetVersionHandler`. +- 🐛 🛫 [PowerShellEditorServices #1964](https://github.com/PowerShell/PowerShellEditorServices/pull/1964) - Remove unnecessary `PowerShellProcessArchitecture`. +- 🐛 🚂 [PowerShellEditorServices #1953](https://github.com/PowerShell/PowerShellEditorServices/pull/1953) - Fix `IsExternalInit` bug, re-enable tests, and update OmniSharp to v0.19.7. +- 🐛 🙏 [PowerShellEditorServices #1962](https://github.com/PowerShell/PowerShellEditorServices/pull/1962) - Revert manual pin of Newtonsoft.Json. +- 🐛 📟 [vscode-powershell #4279](https://github.com/PowerShell/PowerShellEditorServices/pull/1961) - Replace backtick-e with `$([char]0x1b)`. +- ✨ 📟 [vscode-powershell #3901](https://github.com/PowerShell/PowerShellEditorServices/pull/1958) - Enable VS Code's shell integration. +- 🐛 🔍 [vscode-powershell #4269](https://github.com/PowerShell/PowerShellEditorServices/pull/1957) - Escape single quotes when launching a script by path. +- ✨ 🚨 [PowerShellEditorServices #1955](https://github.com/PowerShell/PowerShellEditorServices/pull/1955) - Add PowerShell 7.3 to test matrix. + +## v2022.12.1-preview +### Monday, December 12, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🔧 [vscode-powershell #4315](https://github.com/PowerShell/vscode-powershell/pull/4320) - Enhance (and correct) our settings' descriptions using markdown. +- 🐛 ✂️ [vscode-powershell #3964](https://github.com/PowerShell/vscode-powershell/pull/4311) - Fix `try-catch` snippet (missing a `$`). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.1 + +- 🐛 🚂 [vscode-powershell #4212](https://github.com/PowerShell/PowerShellEditorServices/pull/1970) - Fix `ShowHelpHandler` by running with `RequiresForeground`. + +## v2022.12.0-preview +### Tuesday, December 06, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🔧 [vscode-powershell #4308](https://github.com/PowerShell/vscode-powershell/pull/4308) - Restore original settings after disabling ISE mode. +- ✨ 🚂 [vscode-powershell #4301](https://github.com/PowerShell/vscode-powershell/pull/4307) - Bump engine to 1.67.0 and update panel graphics. +- ✨ 🛫 [vscode-powershell #3226](https://github.com/PowerShell/vscode-powershell/pull/4306) - Rewrite `UpdatePowerShell` feature. +- 🐛 🛫 [vscode-powershell #3435](https://github.com/PowerShell/vscode-powershell/pull/4298) - Skip auto-update on unsupported Windows architectures. +- 🐛 🔧 [vscode-powershell #4297](https://github.com/PowerShell/vscode-powershell/pull/4297) - Fix small bug with `powerShellDefaultVersion` warning. +- ✨ 🔧 [vscode-powershell #4129](https://github.com/PowerShell/vscode-powershell/pull/4295) - Show warning if `powerShellDefaultVersion` is set but not found. +- ✨ 📁 [vscode-powershell #2153](https://github.com/PowerShell/vscode-powershell/pull/3796) - Fully support multi-root workspaces. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.7.0 + +- ✨ 👷 [PowerShellEditorServices #1879](https://github.com/PowerShell/PowerShellEditorServices/pull/1967) - Drop support for end-of-life PowerShell 7.0. +- ✨ 🛫 [PowerShellEditorServices #1965](https://github.com/PowerShell/PowerShellEditorServices/pull/1965) - Send `GitCommitId` over `GetVersionHandler`. +- 🐛 🛫 [PowerShellEditorServices #1964](https://github.com/PowerShell/PowerShellEditorServices/pull/1964) - Remove unnecessary `PowerShellProcessArchitecture`. +- 🐛 🚂 [PowerShellEditorServices #1953](https://github.com/PowerShell/PowerShellEditorServices/pull/1953) - Fix `IsExternalInit` bug, re-enable tests, and update OmniSharp to v0.19.7. + +## v2022.11.2-preview +### Tuesday, November 29, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Just dependency updates. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.6.3 + +- 🐛 🙏 [PowerShellEditorServices #1962](https://github.com/PowerShell/PowerShellEditorServices/pull/1962) - Revert manual pin of Newtonsoft.Json. +- 🐛 📟 [vscode-powershell #4279](https://github.com/PowerShell/PowerShellEditorServices/pull/1961) - Replace backtick-e with `$([char]0x1b)`. + +## v2022.11.1-preview +### Monday, November 21, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 💭 [vscode-powershell #4202](https://github.com/PowerShell/vscode-powershell/pull/4276) - Make `Logger.WriteLine` thread-safe and fix bug with UNC paths. +- ✨ 📟 [vscode-powershell #4271](https://github.com/PowerShell/vscode-powershell/pull/4271) - Send shell integration setting to server. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.6.2 + +- ✨ 📟 [vscode-powershell #3901](https://github.com/PowerShell/PowerShellEditorServices/pull/1958) - Enable VS Code's shell integration. +- 🐛 🔍 [vscode-powershell #4269](https://github.com/PowerShell/PowerShellEditorServices/pull/1957) - Escape single quotes when launching a script by path. +- ✨ 🚨 [PowerShellEditorServices #1955](https://github.com/PowerShell/PowerShellEditorServices/pull/1955) - Add PowerShell 7.3 to test matrix. + +## v2022.11.0 +### Wednesday, November 16, 2022 + +The November release represents a renewed focus on the client, that is, the TypeScript +extension for Visual Studio Code. We've paid back a significant amount of technical debt +by enabling both the TypeScript compiler's and ESLint linter's strict checks, helping us +ensure we are writing correct code. We've increased the client's logging, made the +walkthrough's installation instructions cross-platform, added a warning popup when custom +configured additional PowerShell executables aren't found, and fixed a couple debugger +configuration edge cases. + +A regression for the `OnIdle` handler was fixed in the server, complete with regression +tests covering the registration and triggering of idle events registered both in a profile +and during a session. A workaround was implemented for a completion bug in PowerShell that +was causing the LSP session to disconnect when used with third-party clients. When +executing scripts, the path is now escaped with single quotes instead of double quotes, +addressing the edge case where a path contains a dollar sign, and is now inline with +PowerShell's semantics. + +The build is now correctly published in release mode which should be more performant and +won't allow the user to accidentally enable the "wait for debugger" scenario (which can +appear as a hang, though it is a correctly working feature that is now hidden behind more +developer settings). Additionally, checks were added to both the server and client build +pipelines to assert that the bits are in release mode before packaging, as it was +unfortunately the act of running the tests that erroneously and silently overwrote release +bits with debug bits. + +Finally, a long-standing bug that often prevented the server from starting with Windows +PowerShell was resolved. Known to users as the `DryIoc` error (which was a misleading +stacktrace that commonly popped up), we tracked down a broken dependency of OmniSharp that +when present and loaded into the GAC caused a type resolution error. While it took a year +for us to find the root cause, the fix was a single line dependency update for OmniSharp, +and then some work to incorporate the OmniSharp update into the server. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🚂 [vscode-powershell #3561](https://github.com/PowerShell/vscode-powershell/pull/4206) - Enable `strict` TypeScript mode . +- 🐛 🔍 [vscode-powershell #4201](https://github.com/PowerShell/vscode-powershell/pull/4203) - Fix automatic focus to temporary debug terminal (if it exists). +- 🐛 🚂 [vscode-powershell #4213](https://github.com/PowerShell/vscode-powershell/pull/4228) - Remove `FindModule.ts` since its long since been deprecated. +- 🐛 🔍 [vscode-powershell #4223](https://github.com/PowerShell/vscode-powershell/pull/4227) - Only check a script's extension if a script file was given. +- ✨ 👷 [vscode-powershell #4220](https://github.com/PowerShell/vscode-powershell/pull/4220) - Add assertion to build that PSES bits are built in release configuration. +- ✨ 🚂 [vscode-powershell #3561](https://github.com/PowerShell/vscode-powershell/pull/4206) - Enable `strict` TypeScript mode . +- 🐛 🔍 [vscode-powershell #4201](https://github.com/PowerShell/vscode-powershell/pull/4203) - Fix automatic focus to temporary debug terminal (if it exists). +- ✨ 👷 [vscode-powershell #2882](https://github.com/PowerShell/vscode-powershell/pull/3331) - Replace TSLint with ESLint. +- ✨ 💭 [vscode-powershell #4242](https://github.com/PowerShell/vscode-powershell/pull/4242) - Show warning when additional PowerShell is not found. +- 🐛 🛫 [vscode-powershell #4241](https://github.com/PowerShell/vscode-powershell/pull/4241) - Guard `-WaitForDebugger` flag client-side too. +- ✨ 💭 [vscode-powershell #4240](https://github.com/PowerShell/vscode-powershell/pull/4240) - Capture more logs. +- ✨ 💭 [vscode-powershell #4235](https://github.com/PowerShell/vscode-powershell/pull/4235) - Refactor `settings.ts`. +- 🐛 📺 [vscode-powershell #4149](https://github.com/PowerShell/vscode-powershell/pull/4233) - Add cross-platform installation to walkthrough. +- 🐛 🔍 [vscode-powershell #4231](https://github.com/PowerShell/vscode-powershell/pull/4231) - Check script extension for current file only. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.6.1 + +- 🐛 🚂 [vscode-powershell #4219](https://github.com/PowerShell/PowerShellEditorServices/pull/1936) - Fix regression around `OnIdle` handler. +- 🐛 🧠 [PowerShellEditorServices #1926](https://github.com/PowerShell/PowerShellEditorServices/pull/1935) - Catch exceptions within completion handler. +- 🐛 👷 [vscode-powershell #4218](https://github.com/PowerShell/PowerShellEditorServices/pull/1933) - Fix release build. +- ✨ 📖 [PowerShellEditorServices #1932](https://github.com/PowerShell/PowerShellEditorServices/pull/1932) - Add example of starting PSES in a script to readme. (Thanks @smartguy1196!) +- #️⃣ 🙏 [PowerShellEditorServices #1931](https://github.com/PowerShell/PowerShellEditorServices/pull/1931) - Fix broken links in readme. (Thanks @smartguy1196!) +- #️⃣ 🙏 [PowerShellEditorServices #1947](https://github.com/PowerShell/PowerShellEditorServices/pull/1947) - Manually update `Newtonsoft.Json`. +- 🐛 🚂 [vscode-powershell #4175](https://github.com/PowerShell/PowerShellEditorServices/pull/1946) - Bump OmniSharp to `v0.19.6`. +- 🐛 🔍 [vscode-powershell #4238](https://github.com/PowerShell/PowerShellEditorServices/pull/1940) - Wrap script paths with single instead of double quotes. + +## v2022.11.0-preview +### Thursday, November 03, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 💭 [vscode-powershell #4242](https://github.com/PowerShell/vscode-powershell/pull/4242) - Show warning when additional PowerShell is not found. +- 🐛 🛫 [vscode-powershell #4241](https://github.com/PowerShell/vscode-powershell/pull/4241) - Guard `-WaitForDebugger` flag client-side too. +- ✨ 💭 [vscode-powershell #4240](https://github.com/PowerShell/vscode-powershell/pull/4240) - Capture more logs. +- ✨ 💭 [vscode-powershell #4235](https://github.com/PowerShell/vscode-powershell/pull/4235) - Refactor `settings.ts`. +- 🐛 📺 [vscode-powershell #4149](https://github.com/PowerShell/vscode-powershell/pull/4233) - Add cross-platform installation to walkthrough. +- 🐛 🔍 [vscode-powershell #4231](https://github.com/PowerShell/vscode-powershell/pull/4231) - Check script extension for current file only. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.6.1 + +- #️⃣ 🙏 [PowerShellEditorServices #1947](https://github.com/PowerShell/PowerShellEditorServices/pull/1947) - Manually update `Newtonsoft.Json`. +- 🐛 🚂 [vscode-powershell #4175](https://github.com/PowerShell/PowerShellEditorServices/pull/1946) - Bump OmniSharp to `v0.19.6`. +- 🐛 🔍 [vscode-powershell #4238](https://github.com/PowerShell/PowerShellEditorServices/pull/1940) - Wrap script paths with single instead of double quotes. + +## v2022.10.2-preview +### Tuesday, October 25, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🚂 [vscode-powershell #4213](https://github.com/PowerShell/vscode-powershell/pull/4228) - Remove `FindModule.ts` since its long since been deprecated. +- 🐛 🔍 [vscode-powershell #4223](https://github.com/PowerShell/vscode-powershell/pull/4227) - Only check a script's extension if a script file was given. +- ✨ 👷 [vscode-powershell #4220](https://github.com/PowerShell/vscode-powershell/pull/4220) - Add assertion to build that PSES bits are built in release configuration. +- ✨ 🚂 [vscode-powershell #3561](https://github.com/PowerShell/vscode-powershell/pull/4206) - Enable `strict` TypeScript mode . +- 🐛 🔍 [vscode-powershell #4201](https://github.com/PowerShell/vscode-powershell/pull/4203) - Fix automatic focus to temporary debug terminal (if it exists). +- ✨ 👷 [vscode-powershell #2882](https://github.com/PowerShell/vscode-powershell/pull/3331) - Replace TSLint with ESLint. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.6.0 + +- 🐛 🚂 [vscode-powershell #4219](https://github.com/PowerShell/PowerShellEditorServices/pull/1936) - Fix regression around `OnIdle` handler. +- 🐛 🧠 [PowerShellEditorServices #1926](https://github.com/PowerShell/PowerShellEditorServices/pull/1935) - Catch exceptions within completion handler. +- 🐛 👷 [vscode-powershell #4218](https://github.com/PowerShell/PowerShellEditorServices/pull/1933) - Fix release build. +- ✨ 📖 [PowerShellEditorServices #1932](https://github.com/PowerShell/PowerShellEditorServices/pull/1932) - Add example of starting PSES in a script to readme. (Thanks @smartguy1196!) +- #️⃣ 🙏 [PowerShellEditorServices #1931](https://github.com/PowerShell/PowerShellEditorServices/pull/1931) - Fix broken links in readme. (Thanks @smartguy1196!) + +## v2022.10.0 +### Thursday, October 20, 2022 + +This October stable release incorporates a number of bugfixes throughout September and +early October, though is not based on the latest preview, v2022.10.1-preview, as the +refactors involved in enabling TypeScript's strict type checking and ESLint's strict +linting will need more testing. However, based on the success of the PowerShell Script +Analyzer's [v1.21.0][pssa-v1.21] release we wanted to get this to you sooner! + +Highlighted bugfixes include: supporting events registered to PowerShell's `OnIdle` +handler so that Azure cmdlets such as `Az.Tools.Predictor` now work, a lock around the +client's `start()` so the extension terminal cannot accidentally be spawned multiple +times, and making the default debug configurations not override your current working +directory (by unsetting `cwd` on all of them). + +In addition to fixing bugs, we also reintroduced a fan-favorite feature: the PowerShell +Language Status Icon will visually indicate if the execution pipeline is busy. For +example, a long-running task in the PowerShell Extension Terminal or a launched editor +command will show a spinner! + +Finally, I wanted to call out work by Patrick to significantly improve the performance of +reference finding (which powers the reference code lenses), so large workspaces can now be +used more easily. If these performance improvements are still not enough for a particular +workspace, we also introduced two new settings to fine-tune the feature: + +- `powershell.analyzeOpenDocumentsOnly` when enabled will only search for references within open documents +- `powershell.enableReferencesCodeLens` can be used to disable reference finding without having to turn off other code lenses + +[pssa-v1.21]: https://github.com/PowerShell/PSScriptAnalyzer/releases/tag/1.21.0 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🔍 [vscode-powershell #4201](https://github.com/PowerShell/vscode-powershell/pull/4203) - Fix automatic focus to temporary debug terminal (if it exists). +- 🐛 ✂️ [vscode-powershell #4195](https://github.com/PowerShell/vscode-powershell/pull/4195) - Fix Function Help snippet. (Thanks @okhoel!) +- ✨ 📺 [vscode-powershell #4193](https://github.com/PowerShell/vscode-powershell/pull/4193) - Handle busy notification for all PowerShell tasks. +- ✨ ‍🕵️ [vscode-powershell #4164](https://github.com/PowerShell/vscode-powershell/pull/4164) - Enable new PSScriptAnalyzer option `avoidSemicolonsAsLineTerminators`. (Thanks @bergmeister!) +- ✨ 📺 [vscode-powershell #3954](https://github.com/PowerShell/vscode-powershell/pull/4187) - Re-implement indicator when running registered editor commands. +- 🐛 🔍 [vscode-powershell #4185](https://github.com/PowerShell/vscode-powershell/pull/4186) - Only check a script's extension if a script was given. +- 🐛 🔍 [vscode-powershell #4082](https://github.com/PowerShell/vscode-powershell/pull/4172) - Refactor the debug launch configuration resolvers. +- 🐛 📁 [vscode-powershell #4163](https://github.com/PowerShell/vscode-powershell/pull/4171) - Fix incorrect docstring for `powershell.cwd`. +- #️⃣ 🙏 [vscode-powershell #4170](https://github.com/PowerShell/vscode-powershell/pull/4170) - Add setting to only analyze open documents for references. +- 🐛 🛫 [vscode-powershell #4160](https://github.com/PowerShell/vscode-powershell/pull/4161) - Lock `SessionManager.start()` so only one session is started. +- ✨ 🔧 [vscode-powershell #4139](https://github.com/PowerShell/vscode-powershell/pull/4139) - Add setting to control the references code lens. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.4 + +- ✨ 🚂 [PowerShellEditorServices #1928](https://github.com/PowerShell/PowerShellEditorServices/pull/1928) - Generalize the execution busy status to all PowerShell tasks. +- ✨ ‍🕵️ [PowerShellEditorServices #1916](https://github.com/PowerShell/PowerShellEditorServices/pull/1916) - Upgrade PSScriptAnalyzer to 1.21.0. (Thanks @bergmeister!) +- ✨ 🙏 [PowerShellEditorServices #1924](https://github.com/PowerShell/PowerShellEditorServices/pull/1924) - Re-implement indicator when running registered editor commands. +- 🐛 🛫 [vscode-powershell #4048](https://github.com/PowerShell/PowerShellEditorServices/pull/1918) - Created a nested PowerShell for the top-level loop. +- #️⃣ 🙏 [PowerShellEditorServices #1917](https://github.com/PowerShell/PowerShellEditorServices/pull/1917) - Overhaul workspace search for symbol references. +- ✨ 🚨 [PowerShellEditorServices #1914](https://github.com/PowerShell/PowerShellEditorServices/pull/1914) - Add regression tests for F5 and F8 saving to history. +- ✨ 🙏 [PowerShellEditorServices #1900](https://github.com/PowerShell/PowerShellEditorServices/pull/1900) - Add setting to control references code lens. + +## v2022.10.1-preview +### Monday, October 17, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🚂 [vscode-powershell #3561](https://github.com/PowerShell/vscode-powershell/pull/4206) - Enable `strict` TypeScript mode . +- 🐛 🔍 [vscode-powershell #4201](https://github.com/PowerShell/vscode-powershell/pull/4203) - Fix automatic focus to temporary debug terminal (if it exists). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.4 + +No changes. + +## v2022.10.0-preview +### Friday, October 07, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 ✂️ [vscode-powershell #4195](https://github.com/PowerShell/vscode-powershell/pull/4195) - Fix Function Help snippet. (Thanks @okhoel!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.4 + +No changes. + +## v2022.9.2-preview +### Friday, September 30, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #4193](https://github.com/PowerShell/vscode-powershell/pull/4193) - Handle busy notification for all PowerShell tasks. +- ✨ ‍🕵️ [vscode-powershell #4164](https://github.com/PowerShell/vscode-powershell/pull/4164) - Enable new PSScriptAnalyzer option `avoidSemicolonsAsLineTerminators`. (Thanks @bergmeister!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.4 + +- ✨ 🚂 [PowerShellEditorServices #1928](https://github.com/PowerShell/PowerShellEditorServices/pull/1928) - Generalize the execution busy status to all PowerShell tasks. +- ✨ ‍🕵️ [PowerShellEditorServices #1916](https://github.com/PowerShell/PowerShellEditorServices/pull/1916) - Upgrade PSScriptAnalyzer to 1.21.0. (Thanks @bergmeister!) + +## v2022.9.1-preview +### Wednesday, September 28, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #3954](https://github.com/PowerShell/vscode-powershell/pull/4187) - Re-implement indicator when running registered editor commands. +- 🐛 🔍 [vscode-powershell #4185](https://github.com/PowerShell/vscode-powershell/pull/4186) - Only check a script's extension if a script was given. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.3 + +- ✨ 🙏 [PowerShellEditorServices #1924](https://github.com/PowerShell/PowerShellEditorServices/pull/1924) - Re-implement indicator when running registered editor commands. + +## v2022.9.0-preview +### Tuesday, September 27, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🔍 [vscode-powershell #4082](https://github.com/PowerShell/vscode-powershell/pull/4172) - Refactor the debug launch configuration resolvers. +- 🐛 📁 [vscode-powershell #4163](https://github.com/PowerShell/vscode-powershell/pull/4171) - Fix incorrect docstring for `powershell.cwd`. +- #️⃣ 🙏 [vscode-powershell #4170](https://github.com/PowerShell/vscode-powershell/pull/4170) - Add setting to only analyze open documents for references. +- 🐛 🛫 [vscode-powershell #4160](https://github.com/PowerShell/vscode-powershell/pull/4161) - Lock `SessionManager.start()` so only one session is started. +- ✨ 🔧 [vscode-powershell #4139](https://github.com/PowerShell/vscode-powershell/pull/4139) - Add setting to control the references code lens. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.2 + +- 🐛 🛫 [vscode-powershell #4048](https://github.com/PowerShell/PowerShellEditorServices/pull/1918) - Created a nested PowerShell for the top-level loop. +- #️⃣ 🙏 [PowerShellEditorServices #1917](https://github.com/PowerShell/PowerShellEditorServices/pull/1917) - Overhaul workspace search for symbol references. +- ✨ 🚨 [PowerShellEditorServices #1914](https://github.com/PowerShell/PowerShellEditorServices/pull/1914) - Add regression tests for F5 and F8 saving to history. +- ✨ 🙏 [PowerShellEditorServices #1900](https://github.com/PowerShell/PowerShellEditorServices/pull/1900) - Add setting to control references code lens. + +## v2022.8.5 +### Tuesday, August 30, 2022 + +This release incorporates all the changes since v2022.7.2, first tested across six +previews. Thanks for using PowerShell in VS Code! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🔧 [vscode-powershell #4151](https://github.com/PowerShell/vscode-powershell/pull/4152) - Add `integratedConsole.startInBackground` to completely hide the terminal. +- ✨ 📖 [vscode-powershell #4080](https://github.com/PowerShell/vscode-powershell/pull/4147) - Create a walkthrough experience for PowerShell. (Thanks @S-Hakim!) +- #️⃣ 🚂🙏 [vscode-powershell #4141](https://github.com/PowerShell/vscode-powershell/pull/4141) - Improve language client library close action message. +- 🐛 🛫 [vscode-powershell #4136](https://github.com/PowerShell/vscode-powershell/pull/4140) - Handle edge case where user closes `cwd` picker. +- ✨ 🙏 [vscode-powershell #4117](https://github.com/PowerShell/vscode-powershell/pull/4117) - Add `ToggleISEMode` command with tests. +- 🐛 🛫 [vscode-powershell #4128](https://github.com/PowerShell/vscode-powershell/pull/4131) - Update `vscode-languageclient` and refactor (a lot of TLC). +- ✨ 📺 [vscode-powershell #3266](https://github.com/PowerShell/vscode-powershell/pull/4125) - Fix debugger to start language client when necessary. +- 🐛 🛫 [vscode-powershell #4111](https://github.com/PowerShell/vscode-powershell/pull/4121) - Use `vscode.workspace.fs` and suppress startup banner for `dotnet` installs of PowerShell. +- 🐛 ✂️ [vscode-powershell #4120](https://github.com/PowerShell/vscode-powershell/pull/4120) - Remove extraneous `)` from the do-while snippet. (Thanks @ncook-hxgn!) +- ✨ 📺 [vscode-powershell #4100](https://github.com/PowerShell/vscode-powershell/pull/4105) - Remove popup when extension updates. +- 🐛 📁 [vscode-powershell #4102](https://github.com/PowerShell/vscode-powershell/pull/4104) - Fix edge case for workspaces defined with zero folders. +- 🐛 📁 [vscode-powershell #4098](https://github.com/PowerShell/vscode-powershell/pull/4099) - Fix `checkIfDirectoryExists()` so `validateCwdSetting()` works. +- ✨ 📟 [vscode-powershell #2523](https://github.com/PowerShell/vscode-powershell/pull/4096) - Don't hide extension terminal entirely. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.1 + +- 🐛 ‍🕵️ [PowerShellEditorServices #1906](https://github.com/PowerShell/PowerShellEditorServices/pull/1907) - Remove `null` markers to avoid `NullReferenceException`. +- 🐛 📁 [PowerShellEditorServices #1901](https://github.com/PowerShell/PowerShellEditorServices/pull/1902) - Fix file close in workspace service for Linux. (Thanks @fflaten!) +- ✨ 🐢 [PowerShellEditorServices #1892](https://github.com/PowerShell/PowerShellEditorServices/pull/1899) - Add symbols for Pester setup and teardown blocks. (Thanks @fflaten!) +- 🐛 🔍 [PowerShellEditorServices #1897](https://github.com/PowerShell/PowerShellEditorServices/pull/1898) - Add artificial stack frame to represent contexts without one. +- 🐛 🔍 [PowerShellEditorServices #1894](https://github.com/PowerShell/PowerShellEditorServices/pull/1894) - Fix stepping while watch expressions or interactive pipeline is running. +- ✨ 🐢 [PowerShellEditorServices #1891](https://github.com/PowerShell/PowerShellEditorServices/pull/1893) - Fix whitespace in Pester symbol and add test. (Thanks @fflaten!) +- 🐛 🙏 [PowerShellEditorServices #1887](https://github.com/PowerShell/PowerShellEditorServices/pull/1890) - Fix symbol highlight when hovering function name. (Thanks @fflaten!) +- ✨ 🚨 [PowerShellEditorServices #1874](https://github.com/PowerShell/PowerShellEditorServices/pull/1874) - Add end-to-end integration test with Vim. +- 🐛 ‍🕵️ [vscode-powershell #4112](https://github.com/PowerShell/PowerShellEditorServices/pull/1873) - Fix (and test) regression with PSScriptAnalyzer default rules. +- ✨ 🚨 [PowerShellEditorServices #1872](https://github.com/PowerShell/PowerShellEditorServices/pull/1872) - Add regression tests for parse error DiagnosticMarkers. (Thanks @fflaten!) +- ✨ 🚨 [PowerShellEditorServices #1870](https://github.com/PowerShell/PowerShellEditorServices/pull/1870) - Add `DoesNotDuplicateScriptMarkersAsync` regression test. +- 🐛 ‍🕵️ [PowerShellEditorServices #1869](https://github.com/PowerShell/PowerShellEditorServices/pull/1869) - Fix duplicate DiagnosticMarkers when reopening a file. (Thanks @fflaten!) +- ✨ 🚨 [PowerShellEditorServices #1867](https://github.com/PowerShell/PowerShellEditorServices/pull/1867) - Add regression test for when `prompt` is undefined. +- 🐛 🛫 [vscode-powershell #4073](https://github.com/PowerShell/PowerShellEditorServices/pull/1866) - Fix bug where error in `prompt` function crashed REPL. +- #️⃣ 🙏 [vscode-powershell #2697](https://github.com/PowerShell/PowerShellEditorServices/pull/1864) - Use `HostInfo.BundledModulePath` to find PSScriptAnalyzer. + +## v2022.8.5-preview +### Thursday, August 25, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🔧 [vscode-powershell #4151](https://github.com/PowerShell/vscode-powershell/pull/4152) - Add `integratedConsole.startInBackground` to completely hide the terminal. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.1 + +- 🐛 ‍🕵️ [PowerShellEditorServices #1906](https://github.com/PowerShell/PowerShellEditorServices/pull/1907) - Remove `null` markers to avoid `NullReferenceException`. + +## v2022.8.4-preview +### Friday, August 19, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📖 [vscode-powershell #4080](https://github.com/PowerShell/vscode-powershell/pull/4147) - Create a walkthrough experience for PowerShell. (Thanks @S-Hakim!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.0 + +No update. + +## v2022.8.3-preview +### Thursday, August 18, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🚂🙏 [vscode-powershell #4141](https://github.com/PowerShell/vscode-powershell/pull/4141) - Improve language client library close action message. +- 🐛 🛫 [vscode-powershell #4136](https://github.com/PowerShell/vscode-powershell/pull/4140) - Handle edge case where user closes `cwd` picker. +- ✨ 🙏 [vscode-powershell #4117](https://github.com/PowerShell/vscode-powershell/pull/4117) - Add `ToggleISEMode` command with tests. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.5.0 + +- 🐛 📁 [PowerShellEditorServices #1901](https://github.com/PowerShell/PowerShellEditorServices/pull/1902) - Fix file close in workspace service for Linux. (Thanks @fflaten!) +- ✨ 🐢 [PowerShellEditorServices #1892](https://github.com/PowerShell/PowerShellEditorServices/pull/1899) - Add symbols for Pester setup and teardown blocks. (Thanks @fflaten!) +- 🐛 🔍 [PowerShellEditorServices #1897](https://github.com/PowerShell/PowerShellEditorServices/pull/1898) - Add artificial stack frame to represent contexts without one. +- 🐛 🔍 [PowerShellEditorServices #1894](https://github.com/PowerShell/PowerShellEditorServices/pull/1894) - Fix stepping while watch expressions or interactive pipeline is running. +- ✨ 🐢 [PowerShellEditorServices #1891](https://github.com/PowerShell/PowerShellEditorServices/pull/1893) - Fix whitespace in Pester symbol and add test. (Thanks @fflaten!) +- 🐛 🙏 [PowerShellEditorServices #1887](https://github.com/PowerShell/PowerShellEditorServices/pull/1890) - Fix symbol highlight when hovering function name. (Thanks @fflaten!) + +## v2022.8.2-preview +### Friday, August 12, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🛫 [vscode-powershell #4128](https://github.com/PowerShell/vscode-powershell/pull/4131) - Update `vscode-languageclient` and refactor (a lot of TLC). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.4.10 + +- Just dependency updates. + +## v2022.8.1-preview +### Thursday, August 11, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #3266](https://github.com/PowerShell/vscode-powershell/pull/4125) - Fix debugger to start language client when necessary. +- 🐛 🛫 [vscode-powershell #4111](https://github.com/PowerShell/vscode-powershell/pull/4121) - Use `vscode.workspace.fs` and suppress startup banner for `dotnet` installs of PowerShell. +- 🐛 ✂️ [vscode-powershell #4120](https://github.com/PowerShell/vscode-powershell/pull/4120) - Remove extraneous `)` from the do-while snippet. (Thanks @ncook-hxgn!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.4.9 + +- ✨ 🚨 [PowerShellEditorServices #1874](https://github.com/PowerShell/PowerShellEditorServices/pull/1874) - Add end-to-end integration test with Vim. +- 🐛 ‍🕵️ [vscode-powershell #4112](https://github.com/PowerShell/PowerShellEditorServices/pull/1873) - Fix (and test) regression with PSScriptAnalyzer default rules. +- ✨ 🚨 [PowerShellEditorServices #1872](https://github.com/PowerShell/PowerShellEditorServices/pull/1872) - Add regression tests for parse error DiagnosticMarkers. (Thanks @fflaten!) +- ✨ 🚨 [PowerShellEditorServices #1870](https://github.com/PowerShell/PowerShellEditorServices/pull/1870) - Add `DoesNotDuplicateScriptMarkersAsync` regression test. +- 🐛 ‍🕵️ [PowerShellEditorServices #1869](https://github.com/PowerShell/PowerShellEditorServices/pull/1869) - Fix duplicate DiagnosticMarkers when reopening a file. (Thanks @fflaten!) + +## v2022.8.0-preview +### Wednesday, August 03, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #4100](https://github.com/PowerShell/vscode-powershell/pull/4105) - Remove popup when extension updates. +- 🐛 📁 [vscode-powershell #4102](https://github.com/PowerShell/vscode-powershell/pull/4104) - Fix edge case for workspaces defined with zero folders. +- 🐛 📁 [vscode-powershell #4098](https://github.com/PowerShell/vscode-powershell/pull/4099) - Fix `checkIfDirectoryExists()` so `validateCwdSetting()` works. +- ✨ 📟 [vscode-powershell #2523](https://github.com/PowerShell/vscode-powershell/pull/4096) - Don't hide extension terminal entirely. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.4.8 + +- ✨ 🚨 [PowerShellEditorServices #1867](https://github.com/PowerShell/PowerShellEditorServices/pull/1867) - Add regression test for when `prompt` is undefined. +- 🐛 🛫 [vscode-powershell #4073](https://github.com/PowerShell/PowerShellEditorServices/pull/1866) - Fix bug where error in `prompt` function crashed REPL. +- #️⃣ 🙏 [vscode-powershell #2697](https://github.com/PowerShell/PowerShellEditorServices/pull/1864) - Use `HostInfo.BundledModulePath` to find PSScriptAnalyzer. + +## v2022.7.2 +### Friday, July 29, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 💭 [vscode-powershell #4093](https://github.com/PowerShell/vscode-powershell/pull/4093) - Change `storageUri` to `globalStorageUri` for log and session files. +- ✨ 📟 [vscode-powershell #4053](https://github.com/PowerShell/vscode-powershell/pull/4090) - Rename "Integrated Console" to "Extension Terminal". +- ✨ 🚨 [vscode-powershell #4089](https://github.com/PowerShell/vscode-powershell/pull/4089) - Update and extend CI matrix. +- ✨ 🚂 [vscode-powershell #4088](https://github.com/PowerShell/vscode-powershell/pull/4088) - Use `context.storageUri` for session file (and refactor). +- ✨ 🔧 [vscode-powershell #4067](https://github.com/PowerShell/vscode-powershell/pull/4071) - Use `context.storageUri` for logs and support `None` level. +- ✨ 🔧 [vscode-powershell #4064](https://github.com/PowerShell/vscode-powershell/pull/4064) - Add multi-root choice experience to `powershell.cwd`. +- ✨ 📺 [vscode-powershell #4063](https://github.com/PowerShell/vscode-powershell/pull/4063) - Change configuration title to just `PowerShell`. +- ✨ 📖 [vscode-powershell #4062](https://github.com/PowerShell/vscode-powershell/pull/4062) - Add note about accidentally disabling completions. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.4.7 + +- ✨ 🚨 [PowerShellEditorServices #1861](https://github.com/PowerShell/PowerShellEditorServices/pull/1861) - Add `DebuggerBreaksInUntitledScript` unit test. +- ✨ 📟 [PowerShellEditorServices #1860](https://github.com/PowerShell/PowerShellEditorServices/pull/1860) - Rename "Integrated Console" to "Extension Terminal". +- ✨ 🚨 [PowerShellEditorServices #1859](https://github.com/PowerShell/PowerShellEditorServices/pull/1859) - Update and extend CI matrix. +- ✨ 🚨 [PowerShellEditorServices #1858](https://github.com/PowerShell/PowerShellEditorServices/pull/1858) - Add regression test for debugging script with dot-source operator. +- ✨ 🚨 [PowerShellEditorServices #1857](https://github.com/PowerShell/PowerShellEditorServices/pull/1857) - Add regression test for `$PSDebugContext` in `prompt` function. +- 🐛 🛫 [PowerShellEditorServices #1849](https://github.com/PowerShell/PowerShellEditorServices/pull/1851) - Add `Directory.Exists()` check to `SetInitialWorkingDirectoryAsync()`. +- ✨ 🚨 [PowerShellEditorServices #1850](https://github.com/PowerShell/PowerShellEditorServices/pull/1850) - Catch `OperationCanceledException` in both command loops. +- ✨ 🚨 [PowerShellEditorServices #1793](https://github.com/PowerShell/PowerShellEditorServices/pull/1848) - Improve CI stability. +- ✨ 🚨 [PowerShellEditorServices #1846](https://github.com/PowerShell/PowerShellEditorServices/pull/1846) - Add end-to-end Pester unit test. + +## v2022.7.2-preview +### Tuesday, July 26, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 💭 [vscode-powershell #4093](https://github.com/PowerShell/vscode-powershell/pull/4093) - Change `storageUri` to `globalStorageUri` for log and session files. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) v3.4.7 + +No changes. + +## v2022.7.1-preview +### Monday, July 25, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📟 [vscode-powershell #4053](https://github.com/PowerShell/vscode-powershell/pull/4090) - Rename "Integrated Console" to "Extension Terminal". +- ✨ 🚨 [vscode-powershell #4089](https://github.com/PowerShell/vscode-powershell/pull/4089) - Update and extend CI matrix. +- ✨ 🚂 [vscode-powershell #4088](https://github.com/PowerShell/vscode-powershell/pull/4088) - Use `context.storageUri` for session file (and refactor). +- ✨ 🔧 [vscode-powershell #4067](https://github.com/PowerShell/vscode-powershell/pull/4071) - Use `context.storageUri` for logs and support `None` level. +- ✨ 🔧 [vscode-powershell #4064](https://github.com/PowerShell/vscode-powershell/pull/4064) - Add multi-root choice experience to `powershell.cwd`. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🚨 [PowerShellEditorServices #1861](https://github.com/PowerShell/PowerShellEditorServices/pull/1861) - Add `DebuggerBreaksInUntitledScript` unit test. +- ✨ 📟 [PowerShellEditorServices #1860](https://github.com/PowerShell/PowerShellEditorServices/pull/1860) - Rename "Integrated Console" to "Extension Terminal". +- ✨ 🚨 [PowerShellEditorServices #1859](https://github.com/PowerShell/PowerShellEditorServices/pull/1859) - Update and extend CI matrix. +- ✨ 🚨 [PowerShellEditorServices #1858](https://github.com/PowerShell/PowerShellEditorServices/pull/1858) - Add regression test for debugging script with dot-source operator. +- ✨ 🚨 [PowerShellEditorServices #1857](https://github.com/PowerShell/PowerShellEditorServices/pull/1857) - Add regression test for `$PSDebugContext` in `prompt` function. + +## v2022.7.0-preview +### Monday, July 11, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #4063](https://github.com/PowerShell/vscode-powershell/pull/4063) - Change configuration title to just `PowerShell`. +- ✨ 📖 [vscode-powershell #4062](https://github.com/PowerShell/vscode-powershell/pull/4062) - Add note about accidentally disabling completions. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🛫 [PowerShellEditorServices #1849](https://github.com/PowerShell/PowerShellEditorServices/pull/1851) - Add `Directory.Exists()` check to `SetInitialWorkingDirectoryAsync()`. +- ✨ 🚨 [PowerShellEditorServices #1850](https://github.com/PowerShell/PowerShellEditorServices/pull/1850) - Catch `OperationCanceledException` in both command loops. +- ✨ 🚨 [PowerShellEditorServices #1793](https://github.com/PowerShell/PowerShellEditorServices/pull/1848) - Improve CI stability. +- ✨ 🚨 [PowerShellEditorServices #1846](https://github.com/PowerShell/PowerShellEditorServices/pull/1846) - Add end-to-end Pester unit test. + +## v2022.6.3 +### Wednesday, June 30, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📖 [vscode-powershell #4046](https://github.com/PowerShell/vscode-powershell/pull/4046) - Update tooling and READMEs for branch rename. +- ✨ 🔧 [vscode-powershell #4033](https://github.com/PowerShell/vscode-powershell/pull/4034) - Mark unused `useX86Host` setting as deprecated. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🙏 [PowerShellEditorServices #1844](https://github.com/PowerShell/PowerShellEditorServices/pull/1845) - Update PSReadLine to v2.2.6. +- ✨ 📖 [PowerShellEditorServices #1843](https://github.com/PowerShell/PowerShellEditorServices/pull/1843) - Find/replace of `master` to `main` for branch rename. +- 🐛 📟 [vscode-powershell #3683](https://github.com/PowerShell/PowerShellEditorServices/pull/1841) - Add command to PSReadLine history before cancellation. +- 🐛 🔍 [PowerShellEditorServices #1839](https://github.com/PowerShell/PowerShellEditorServices/pull/1839) - Fix logic checking for untitled or raw scripts. +- 🐛 🔍 [PowerShellEditorServices #1838](https://github.com/PowerShell/PowerShellEditorServices/pull/1838) - Don't use `RunContinuationsAsynchronously` for our `TaskCompletionSource`. +- 🐛 📟 [vscode-powershell #4021](https://github.com/PowerShell/PowerShellEditorServices/pull/1836) - Fix piping to native commands for Windows PowerShell. +- ✨ 📖 [PowerShellEditorServices #1831](https://github.com/PowerShell/PowerShellEditorServices/pull/1833) - Add readme about `ReadKey` workarounds. +- ✨ 🚨 [PowerShellEditorServices #1832](https://github.com/PowerShell/PowerShellEditorServices/pull/1832) - Improve `$PROFILE` variable and profile loading test. +- ✨ 🚨 [PowerShellEditorServices #1830](https://github.com/PowerShell/PowerShellEditorServices/pull/1830) - Add regression test for untitled scripts in Windows PowerShell. +- ✨ 🚨 [PowerShellEditorServices #1828](https://github.com/PowerShell/PowerShellEditorServices/pull/1828) - Add regression test for accidentally allowing removal of `$psEditor`. + +## v2022.6.3-preview +### Wednesday, June 29, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📖 [vscode-powershell #4046](https://github.com/PowerShell/vscode-powershell/pull/4046) - Update tooling and READMEs for branch rename. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🙏 [PowerShellEditorServices #1844](https://github.com/PowerShell/PowerShellEditorServices/pull/1845) - Update PSReadLine to v2.2.6. +- ✨ 📖 [PowerShellEditorServices #1843](https://github.com/PowerShell/PowerShellEditorServices/pull/1843) - Find/replace of `master` to `main` for branch rename. +- 🐛 📟 [vscode-powershell #3683](https://github.com/PowerShell/PowerShellEditorServices/pull/1841) - Add command to PSReadLine history before cancellation. + +## v2022.6.2-preview +### Wednesday, June 22, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🔧 [vscode-powershell #4033](https://github.com/PowerShell/vscode-powershell/pull/4034) - Mark unused `useX86Host` setting as deprecated. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [PowerShellEditorServices #1839](https://github.com/PowerShell/PowerShellEditorServices/pull/1839) - Fix logic checking for untitled or raw scripts. +- 🐛 🔍 [PowerShellEditorServices #1838](https://github.com/PowerShell/PowerShellEditorServices/pull/1838) - Don't use `RunContinuationsAsynchronously` for our `TaskCompletionSource`. +- 🐛 📟 [vscode-powershell #4021](https://github.com/PowerShell/PowerShellEditorServices/pull/1836) - Fix piping to native commands for Windows PowerShell. +- ✨ 📖 [PowerShellEditorServices #1831](https://github.com/PowerShell/PowerShellEditorServices/pull/1833) - Add readme about `ReadKey` workarounds. +- ✨ 🚨 [PowerShellEditorServices #1832](https://github.com/PowerShell/PowerShellEditorServices/pull/1832) - Improve `$PROFILE` variable and profile loading test. +- ✨ 🚨 [PowerShellEditorServices #1830](https://github.com/PowerShell/PowerShellEditorServices/pull/1830) - Add regression test for untitled scripts in Windows PowerShell. +- ✨ 🚨 [PowerShellEditorServices #1828](https://github.com/PowerShell/PowerShellEditorServices/pull/1828) - Add regression test for accidentally allowing removal of `$psEditor`. + +## v2022.6.1 +### Tuesday, June 21, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +New stable release with all changes below since `v2022.5.1`: + +- 🐛 📖 [vscode-powershell #4018](https://github.com/PowerShell/vscode-powershell/pull/4018) - Fix outdated link to security guidelines. (Thanks @rklec!) +- 🐛 👷 [vscode-powershell #3993](https://github.com/PowerShell/vscode-powershell/pull/3993) - Revert modifications caused by Code's test run. +- 🐛 🚂 [vscode-powershell #3992](https://github.com/PowerShell/vscode-powershell/pull/3992) - Fix how we check extension mode. +- 🐛 🛫 [vscode-powershell #3986](https://github.com/PowerShell/vscode-powershell/pull/3986) - Pass `EnableProfileLoading` and `InitialWorkingDirectory` as `initializationOptions`. +- ✨ 📺 [vscode-powershell #3976](https://github.com/PowerShell/vscode-powershell/pull/3976) - Add warning about intellisense to PSIC terminate dialog. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +Includes `v3.4.3` with all changes below since `v3.3.5`: + +- ✨ 📟 [PowerShellEditorServices #1823](https://github.com/PowerShell/PowerShellEditorServices/pull/1823) - Utilize the `AddToHistory` delegate from PSRL proxy. +- ✨ 🛫 [PowerShellEditorServices #1821](https://github.com/PowerShell/PowerShellEditorServices/pull/1821) - Add regression test for no defined profiles. +- ✨ 👷 [PowerShellEditorServices #1820](https://github.com/PowerShell/PowerShellEditorServices/pull/1820) - Add Emacs regression tests for PSES. +- 🐛 🧠 [PowerShellEditorServices #1819](https://github.com/PowerShell/PowerShellEditorServices/pull/1819) - Remove bad UX of commit characters for paths. +- 🐛 🔍 [PowerShellEditorServices #1818](https://github.com/PowerShell/PowerShellEditorServices/pull/1818) - Exit debugger stop early if cause is PSE. +- ✨ 👷 [PowerShellEditorServices #1817](https://github.com/PowerShell/PowerShellEditorServices/pull/1817) - Fix build script to support Windows on Arm64. +- 🐛 🔍 [PowerShellEditorServices #1815](https://github.com/PowerShell/PowerShellEditorServices/pull/1815) - Set `IsDebuggingRemoteRunspace` sooner for attach. +- 🐛 🙏 [PowerShellEditorServices #1814](https://github.com/PowerShell/PowerShellEditorServices/pull/1814) - Fix error when piping `IFilePosition` to `ConvertTo-ScriptExtent`. +- ✨ 🧠 [PowerShellEditorServices #1809](https://github.com/PowerShell/PowerShellEditorServices/pull/1809) - Additional IntelliSense fixes and ToolTip overhaul. +- 🐛 🛫 [PowerShellEditorServices #1807](https://github.com/PowerShell/PowerShellEditorServices/pull/1807) - Fix startup bug when zero profiles are present. +- 🐛 🔍 [vscode-powershell #3965](https://github.com/PowerShell/PowerShellEditorServices/pull/1804) - Wrap untitled script with newlines. +- 🐛 🔍 [vscode-powershell #3980](https://github.com/PowerShell/PowerShellEditorServices/pull/1803) - Fix execution of debug prompt commands. +- 🐛 📟 [PowerShellEditorServices #1802](https://github.com/PowerShell/PowerShellEditorServices/pull/1802) - Set `EnableProfileLoading` default to `true`. +- 🐛 🙏 [PowerShellEditorServices #1695](https://github.com/PowerShell/PowerShellEditorServices/pull/1801) - Re-enable stdio clients by fixing initialization sequence. +- ✨ 🧠 [PowerShellEditorServices #1799](https://github.com/PowerShell/PowerShellEditorServices/pull/1799) - Fix a lot of IntelliSense issues. +- #️⃣ 🙏 [vscode-powershell #3962](https://github.com/PowerShell/PowerShellEditorServices/pull/1797) - Increase stack size for PowerShell 5. (Thanks @nohwnd!) + +## v2022.6.1-preview +### Monday, June 13, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 📖 [vscode-powershell #4018](https://github.com/PowerShell/vscode-powershell/pull/4018) - Fix outdated link to security guidelines. (Thanks @rklec!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 📟 [PowerShellEditorServices #1823](https://github.com/PowerShell/PowerShellEditorServices/pull/1823) - Utilize the `AddToHistory` delegate from PSRL proxy. +- ✨ 🛫 [PowerShellEditorServices #1821](https://github.com/PowerShell/PowerShellEditorServices/pull/1821) - Add regression test for no defined profiles. +- ✨ 👷 [PowerShellEditorServices #1820](https://github.com/PowerShell/PowerShellEditorServices/pull/1820) - Add Emacs regression tests for PSES. +- 🐛 🧠 [PowerShellEditorServices #1819](https://github.com/PowerShell/PowerShellEditorServices/pull/1819) - Remove bad UX of commit characters for paths. +- 🐛 🔍 [PowerShellEditorServices #1818](https://github.com/PowerShell/PowerShellEditorServices/pull/1818) - Exit debugger stop early if cause is PSE. +- ✨ 👷 [PowerShellEditorServices #1817](https://github.com/PowerShell/PowerShellEditorServices/pull/1817) - Fix build script to support Windows on Arm64. +- 🐛 🔍 [PowerShellEditorServices #1815](https://github.com/PowerShell/PowerShellEditorServices/pull/1815) - Set `IsDebuggingRemoteRunspace` sooner for attach. +- 🐛 🙏 [PowerShellEditorServices #1814](https://github.com/PowerShell/PowerShellEditorServices/pull/1814) - Fix error when piping `IFilePosition` to `ConvertTo-ScriptExtent`. + +## v2022.5.5-preview +### Friday, May 20, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +No changes. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🧠 [PowerShellEditorServices #1809](https://github.com/PowerShell/PowerShellEditorServices/pull/1809) - Additional IntelliSense fixes and ToolTip overhaul. + +## v2022.5.4-preview +### Thursday, May 19, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +No changes. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🛫 [PowerShellEditorServices #1807](https://github.com/PowerShell/PowerShellEditorServices/pull/1807) - Fix startup bug when zero profiles are present. + +## v2022.5.3-preview +### Thursday, May 19, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #3993](https://github.com/PowerShell/vscode-powershell/pull/3993) - Revert modifications caused by Code's test run. +- 🐛 🚂 [vscode-powershell #3992](https://github.com/PowerShell/vscode-powershell/pull/3992) - Fix how we check extension mode. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +No changes. + +## v2022.5.2-preview +### Tuesday, May 17, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🛫 [vscode-powershell #3986](https://github.com/PowerShell/vscode-powershell/pull/3986) - Pass `EnableProfileLoading` and `InitialWorkingDirectory` as `initializationOptions`. +- ✨ 📺 [vscode-powershell #3976](https://github.com/PowerShell/vscode-powershell/pull/3976) - Add warning about intellisense to PSIC terminate dialog. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [vscode-powershell #3965](https://github.com/PowerShell/PowerShellEditorServices/pull/1804) - Wrap untitled script with newlines. +- 🐛 🔍 [vscode-powershell #3980](https://github.com/PowerShell/PowerShellEditorServices/pull/1803) - Fix execution of debug prompt commands. +- 🐛 📟 [PowerShellEditorServices #1802](https://github.com/PowerShell/PowerShellEditorServices/pull/1802) - Set `EnableProfileLoading` default to `true`. +- 🐛 🙏 [PowerShellEditorServices #1695](https://github.com/PowerShell/PowerShellEditorServices/pull/1801) - Re-enable stdio clients by fixing initialization sequence. +- ✨ 🧠 [PowerShellEditorServices #1799](https://github.com/PowerShell/PowerShellEditorServices/pull/1799) - Fix a lot of IntelliSense issues. +- #️⃣ 🙏 [vscode-powershell #3962](https://github.com/PowerShell/PowerShellEditorServices/pull/1797) - Increase stack size for PowerShell 5. (Thanks @nohwnd!) + +## v2022.5.1 +### Friday, May 06, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🔍 [vscode-powershell #3950](https://github.com/PowerShell/vscode-powershell/pull/3951) - Handle `sendKeyPress` events for temporary integrated consoles. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [vscode-powershell #3950](https://github.com/PowerShell/PowerShellEditorServices/pull/1791) - Send `sendKeyPress` event across DAP for temporary integrated consoles. + +## v2022.5.0 +### Tuesday, May 03, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Welcome to the new and improved PowerShell for Visual Studio Code! + +This update represents a complete overhaul of the core PowerShell engine of PowerShell +Editor Services, intending to create a more reliable and stable user experience. This +release represents nearly two years' work, tracked in PSES +[#1295](https://github.com/PowerShell/PowerShellEditorServices/issues/1295) and +implemented in PSES +[#1459](https://github.com/PowerShell/PowerShellEditorServices/pull/1459). It is our +response to many issues opened by users over the last several years. + +Thank you to all of the community members who opened issues which helped motivate this +major update. + +These major updates have also been tested over the last 6 months, in 13 releases of our +[PowerShell Preview extension for Visual Studio +Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.powershell). A +huge thank you to all of the community members who have tested these changes to the +extension and have worked with us to polish the extension before releasing it through our +stable channel. + +Please see our +[blog](https://devblogs.microsoft.com/powershell/major-update-to-the-powershell-extension-for-visual-studio-code) +for more details! + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🙏 [PowerShellEditorServices #1787](https://github.com/PowerShell/PowerShellEditorServices/pull/1787) - Bump PSReadLine to `v2.2.5`. + +## v2022.5.0-preview +### Monday, May 02, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Fourth Release Candidate! Thanks for finding bugs and helping us squash them! + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 📟 [PowerShellEditorServices #1785](https://github.com/PowerShell/PowerShellEditorServices/pull/1785) - Add `IHostUISupportsMultipleChoiceSelection` implementation. +- 🐛 🔍 [PowerShellEditorServices #1784](https://github.com/PowerShell/PowerShellEditorServices/pull/1784) - Do not exit from `DebuggerStop` unless resuming. + +## v2022.4.3-preview +### Thursday, April 28, 2022 + +Third Release Candidate. Our recent debugger and `ReadKey` overhauls revealed some other +bugs that needed squashing! Please test this thoroughly. We're gaining confidence! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🙏 [vscode-powershell #3939](https://github.com/PowerShell/vscode-powershell/pull/3939) - Send `p` instead of `\0` for `sendKeyPress`. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🛫 [PowerShellEditorServices #1782](https://github.com/PowerShell/PowerShellEditorServices/pull/1782) - Fix ordering of startup tasks so `psEditor` is defined before profiles are loaded. +- 🐛 📟 [PowerShellEditorServices #1781](https://github.com/PowerShell/PowerShellEditorServices/pull/1781) - Bring back `WriteWithPrompt()`. +- 🐛 📟 [vscode-powershell #3937](https://github.com/PowerShell/PowerShellEditorServices/pull/1779) - Update to latest PSReadLine beta (with fix for race condition). +- 🐛 🔍 [PowerShellEditorServices #1778](https://github.com/PowerShell/PowerShellEditorServices/pull/1778) - Fix extra prompting and manual debugger commands. +- ✨ 🚂 [PowerShellEditorServices #1777](https://github.com/PowerShell/PowerShellEditorServices/pull/1777) - Consolidate `InterruptCurrentForeground` and `MustRunInForeground`. +- ✨ 🚂 [PowerShellEditorServices #1776](https://github.com/PowerShell/PowerShellEditorServices/pull/1776) - Don't cancel on disposal of `CancellationScope`. + +## v2022.4.2-preview +### Wednesday, April 20, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Just including updates to PowerShell Editor Services. This is the second Release +Candidate! Please give it a thorough test. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 👷 [PowerShellEditorServices #1761](https://github.com/PowerShell/PowerShellEditorServices/pull/1766) - Bump `net461` to `net462` due to upcoming end of support. +- 🐛 💎 [vscode-powershell #3928](https://github.com/PowerShell/PowerShellEditorServices/pull/1764) - Fix formatting handlers and PSScriptAnalyzer loading. +- 🐛 🔍 [PowerShellEditorServices #1762](https://github.com/PowerShell/PowerShellEditorServices/pull/1762) - Fix prompt spam and general debugger reliability improvements. +- ✨ 🙏 [PowerShellEditorServices #1479](https://github.com/PowerShell/PowerShellEditorServices/pull/1759) - Enable IDE0005 (unneccessary using statements) as error. +- 🐛 🙏 [PowerShellEditorServices #1754](https://github.com/PowerShell/PowerShellEditorServices/pull/1758) - With a fix in PSReadLine, we don't have to return a "null" key press. + +## v2022.4.1-preview +### Monday, April 18, 2022 + +This is our first Release Candidate. We've merged a set of major fixes to the debugger so +that attaching to remote processes / runspaces now works again. While the extension is not +perfect (yet), we believe at this point the preview far exceeds the stable extension in +terms of usability and stability, and it is time to roll this out. Please give this a +thorough testing, as we hope to roll it into the stable extension next week. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #3919](https://github.com/PowerShell/vscode-powershell/pull/3919) - Improve Settings Editor experience in a few places. (Thanks @TylerLeonhardt!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- #️⃣ 🙏 [PowerShellEditorServices #1757](https://github.com/PowerShell/PowerShellEditorServices/pull/1757) - Enable code analysis and formatting as errors on build. +- ✨ 🚂 [PowerShellEditorServices #1755](https://github.com/PowerShell/PowerShellEditorServices/pull/1755) - Apply automatic fixes (manually). +- 🐛 🔍 [PowerShellEditorServices #1736](https://github.com/PowerShell/PowerShellEditorServices/pull/1752) - Fix attach to process debugging. + +## v2022.4.0-preview +### Tuesday, April 12, 2022 + +We delayed moving the preview branch to stable in order to fix issues surrounding our +`ReadKey` / `ReadLine` logic. This preview contains a new minor release of PowerShell +Editor Services with an entire rewrite of that logic, utilizing what we hope is a much +better workaround for the underlying issue in .NET's `Console.ReadKey`. Please give this +release a thorough testing, especially in the console with PSReadLine. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🙏 [vscode-powershell #3911](https://github.com/PowerShell/vscode-powershell/pull/3911) - Add `sendKeyPress` notification used to "cancel" `Console.ReadKey`. +- 🐛 ✂️ [vscode-powershell #3276](https://github.com/PowerShell/vscode-powershell/pull/3900) - Fix snippet prefixes (especially `#region`). +- ✨ 📺 [vscode-powershell #3897](https://github.com/PowerShell/vscode-powershell/pull/3897) - Add PowerShell icon to Integrated Console. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🙏 [PowerShellEditorServices #1751](https://github.com/PowerShell/PowerShellEditorServices/pull/1751) - Re-workaround uncancellable `Console.ReadKey`. +- 🐛 ‍🕵️ [PowerShellEditorServices #1749](https://github.com/PowerShell/PowerShellEditorServices/pull/1749) - Correctly map `SuggestedCorrection` to `MarkerCorrection`. (Thanks @bergmeister!) + +## v2022.3.1-preview +### Thursday, March 24, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 📺 [vscode-powershell #3878](https://github.com/PowerShell/vscode-powershell/pull/3883) - Add several more commands to activation events. +- 🐛 📖 [vscode-powershell #3857](https://github.com/PowerShell/vscode-powershell/pull/3879) - Update troubleshooting guide etc. +- 🐛 📺 [vscode-powershell #3874](https://github.com/PowerShell/vscode-powershell/pull/3877) - Add PowerShell version to language status item. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- #️⃣ 🙏 [PowerShellEditorServices #1746](https://github.com/PowerShell/PowerShellEditorServices/pull/1746) - Replace `_consoleHostUI` with `_underlyingHostUI`. + +## v2022.3.0-preview +### Thursday, March 10, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #2499](https://github.com/PowerShell/vscode-powershell/pull/3869) - Use Code's new Language Status API. +- ✨ 📺 [vscode-powershell #3866](https://github.com/PowerShell/vscode-powershell/pull/3866) - Fix title of PowerShell Command Explorer pane. +- ✨ 📺 [vscode-powershell #3865](https://github.com/PowerShell/vscode-powershell/pull/3865) - Replace custom graphics with updated Codicons. +- ✨ 🔧 [vscode-powershell #3858](https://github.com/PowerShell/vscode-powershell/pull/3859) - Deprecate `promptToUpdatePackageManagement`. +- 🐛 📟 [vscode-powershell #3360](https://github.com/PowerShell/vscode-powershell/pull/3854) - Use new `isTransient` API to prevent duplicate integrated consoles. +- 🐛 🔍 [vscode-powershell #3259](https://github.com/PowerShell/vscode-powershell/pull/3852) - Fix Pester `Test/Debug` code lenses to now change directory. +- ✨ ✂️ [vscode-powershell #3839](https://github.com/PowerShell/vscode-powershell/pull/3839) - Modernize built-in snippets. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🧠 [vscode-powershell #3364](https://github.com/PowerShell/PowerShellEditorServices/pull/1738) - Improve completion logic (more icons!). +- 🐛 🛫 [PowerShellEditorServices #1576](https://github.com/PowerShell/PowerShellEditorServices/pull/1735) - Remove `PackageManagement` module update prompt. +- 🐛 📟 [PowerShellEditorServices #1734](https://github.com/PowerShell/PowerShellEditorServices/pull/1734) - Finish redirection of `$Host.PrivateData`. +- 🐛 📟 [PowerShellEditorServices #1639](https://github.com/PowerShell/PowerShellEditorServices/pull/1732) - Redirect `PSHost.Notify*Application` methods. + +## v2022.2.2-preview +### Thursday, February 24, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 📟 [vscode-powershell #3820](https://github.com/PowerShell/vscode-powershell/pull/3847) - Remove `-NonInteractive` from PowerShell startup sequence. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🛫 [vscode-powershell #2658](https://github.com/PowerShell/PowerShellEditorServices/pull/1726) - Avoid error when `exclude` entry is a clause. +- 🐛 🚂 [vscode-powershell #3691](https://github.com/PowerShell/PowerShellEditorServices/pull/1725) - Fix editor commands to interrupt current prompt. +- ✨ 🔍 [PowerShellEditorServices #1724](https://github.com/PowerShell/PowerShellEditorServices/pull/1724) - Re-enable line breakpoints for untitled scripts. +- ✨ 🙏 [PowerShellEditorServices #1709](https://github.com/PowerShell/PowerShellEditorServices/pull/1723) - Update PSReadLine to 2.2.2. +- 🐛 📟 [vscode-powershell #3807](https://github.com/PowerShell/PowerShellEditorServices/pull/1719) - Reset progress messages at end of REPL. +- 🐛 ‍🕵️ [PowerShellEditorServices #1718](https://github.com/PowerShell/PowerShellEditorServices/pull/1718) - Return a code action for each diagnostic record. (Thanks @bergmeister!) + +## v2022.2.1-preview +### Wednesday, February 16, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #3824](https://github.com/PowerShell/vscode-powershell/pull/3824) - Add known `PowerShell.OnIdle` event bug to `troubleshooting.md`. (Thanks @StevenBucher98!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [vscode-powershell #3832](https://github.com/PowerShell/PowerShellEditorServices/pull/1712) - Avoid stopping the debugger when canceling other tasks in a debug session. +- 🐛 📟 [PowerShellEditorServices #1607](https://github.com/PowerShell/PowerShellEditorServices/pull/1711) - Redirect `EditorServicesConsolePSHost.PrivateData` to `_internalHost`. +- 🐛 📟 [PowerShellEditorServices #1699](https://github.com/PowerShell/PowerShellEditorServices/pull/1710) - Handle edge case where `prompt` is undefined. +- 🐛 🔍 [PowerShellEditorServices #1704](https://github.com/PowerShell/PowerShellEditorServices/pull/1704) - Avoid recording debugger commands in the history. +- ✨ 🔍 [PowerShellEditorServices #1703](https://github.com/PowerShell/PowerShellEditorServices/pull/1703) - Use `static readonly` for default `ExecutionOptions`. +- 🐛 🔍 [vscode-powershell #3655](https://github.com/PowerShell/PowerShellEditorServices/pull/1702) - Fix running untitled scripts with arguments (but break line breakpoints) . +- ✨ 🙏 [PowerShellEditorServices #1694](https://github.com/PowerShell/PowerShellEditorServices/pull/1694) - Add `Thread.Sleep(100)` to throttle REPL when it's non-interactive. (Thanks @colinblaise!) + +## v2022.2.0-preview +### Wednesday, February 02, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Just including several PSES fixes, namely around the F5 and F8 bugs. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 📟 [vscode-powershell #3786](https://github.com/PowerShell/PowerShellEditorServices/pull/1691) - Print prompt and command when `WriteInputToHost` is true. +- 🐛 📟 [vscode-powershell #3685](https://github.com/PowerShell/PowerShellEditorServices/pull/1690) - Display prompt after `F8` finishes. +- 🐛 🔍 [vscode-powershell #3522](https://github.com/PowerShell/PowerShellEditorServices/pull/1685) - Synchronize PowerShell debugger and DAP server state. +- ✨ 🔍 [PowerShellEditorServices #1680](https://github.com/PowerShell/PowerShellEditorServices/pull/1680) - Display `DictionaryEntry` as key/value pairs in debugger. (Thanks @JustinGrote!) + +## v2022.1.1-preview +### Monday, January 24, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 📺 [vscode-powershell #3710](https://github.com/PowerShell/vscode-powershell/pull/3772) - Fix `PowerShell.Debug.Start` to just launch current file. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- #️⃣ 💎 [PowerShellEditorServices #1676](https://github.com/PowerShell/PowerShellEditorServices/pull/1676) - Use EditorConfig for dotnet build and suppress existing issues. (Thanks @JustinGrote!) +- 🐛 🔍 [PowerShellEditorServices #1672](https://github.com/PowerShell/PowerShellEditorServices/pull/1670) - Handle `debuggerResult` being null in `ProcessDebuggerResult`. +- 🐛 🙏 [PowerShellEditorServices #1663](https://github.com/PowerShell/PowerShellEditorServices/pull/1669) - Fix off-by-one error in validation within `GetOffsetAtPosition`. +- 🐛 📟 [PowerShellEditorServices #1667](https://github.com/PowerShell/PowerShellEditorServices/pull/1668) - Fix `Write-Host -NoNewLine` and `-*Color`. (Thanks @SeeminglyScience!) +- 🐛 🔍 [PowerShellEditorServices #1661](https://github.com/PowerShell/PowerShellEditorServices/pull/1664) - Fix `DebuggerSetsVariablesWithConversion` test. +- ✨ 🙏 [vscode-powershell #2800](https://github.com/PowerShell/PowerShellEditorServices/pull/1662) - Enable resolution of an alias to its function definition. +- ✨ 🔍 [PowerShellEditorServices #1633](https://github.com/PowerShell/PowerShellEditorServices/pull/1634) - Display `IEnumerables` and `IDictionaries` in debugger prettily (with "Raw View" available). (Thanks @JustinGrote!) + +## v2022.1.0-preview +### Monday, January 10, 2022 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Happy New Year! Please enjoy a new preview release! We have re-enabled nearly all of the +tests in PowerShell Editor Services, and are becoming more confident in our ability to fix +your reported issues without introducing regressions. Thanks so much for continuing to use +and help improve the extension. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🙏 [PowerShellEditorServices #1658](https://github.com/PowerShell/PowerShellEditorServices/pull/1658) - Bump PSReadLine module to 2.2.0-beta5. +- 🐛 🚨 [PowerShellEditorServices #1444](https://github.com/PowerShell/PowerShellEditorServices/pull/1657) - Re-enable `ExtensionCommandTests.cs`. +- 🐛 🙏 [PowerShellEditorServices #1656](https://github.com/PowerShell/PowerShellEditorServices/pull/1656) - Resurrect support to resolve aliased references. +- 🐛 🚨 [PowerShellEditorServices #1445](https://github.com/PowerShell/PowerShellEditorServices/pull/1655) - Split and clean up `LanguageServiceTests.cs`. +- 🐛 🔍 [vscode-powershell #3715](https://github.com/PowerShell/PowerShellEditorServices/pull/1652) - Fix regression with `F5` to use `.` instead of `&` operator. +- ✨ 🚨 [vscode-powershell #3677](https://github.com/PowerShell/PowerShellEditorServices/pull/1651) - Enable `PsesInternalHostTests` (previously `PowerShellContextTests`). + +## v2021.12.0 +### Wednesday, December 22, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +This release *does not* include the latest major update of PowerShell Editor Services. We +are updating the stable extension to bring some bug fixes forward. Please try out the +[PowerShell Preview extension][] for the latest and hopefully greatest experience, and +help us squash those bugs! + +[PowerShell Preview extension]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.powershell + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +This extension update includes PowerShell Editor Services [v2.5.3][], a re-release of +[v2.5.2][] which was the last version before the major pipeline and threading overhaul was +merged in [v3.0.0][]. By re-releasing we are able to update the module's signature with a +renewed certificate. + +[v2.5.3]: https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v2.5.3 +[v2.5.2]: https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v2.5.2 +[v3.0.0]: https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v3.0.0 + +## v2021.12.0-preview +### Monday, December 20, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +We're hard at work continuing to improvo the stability and coverage of the PowerShell +Preview so we can bring the updates to the regular extension. Most recently we got the unit tests +covering the debugger back online, which revealed a bug in the ability to set variables +through the debugger. We're continuing to work to resolve this and re-enable the rest of +our tests. Please keep using the Preview if you're able and filing bug reports, we +appreciate it! + +- 🐛 🔍 [vscode-powershell #3713](https://github.com/PowerShell/vscode-powershell/pull/3728) - Support debugging without a workspace. +- 🐛 📺 [vscode-powershell #3709](https://github.com/PowerShell/vscode-powershell/pull/3735) - Fix `EnableISEMode` for Azure Data Studio. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🚂 [vscode-powershell #3718](https://github.com/PowerShell/PowerShellEditorServices/pull/1647) - Create `$psEditor` as a constant. +- #️⃣ 🙏 [PowerShellEditorServices #1641](https://github.com/PowerShell/PowerShellEditorServices/pull/1641) - Added check to see if `PSModulePath` already contained `BundledModulePath`. (Thanks @dkattan!) +- #️⃣ 🙏 [PowerShellEditorServices #1640](https://github.com/PowerShell/PowerShellEditorServices/pull/1640) - Implemented `-LanguageServiceOnly` switch. (Thanks @dkattan!) +- 🐛 🛫 [PowerShellEditorServices #1638](https://github.com/PowerShell/PowerShellEditorServices/pull/1638) - Fix `BundledModulePath` and PSReadLine loading (redux). +- 🐛 🔍 [PowerShellEditorServices #1635](https://github.com/PowerShell/PowerShellEditorServices/pull/1635) - Re-enable `DebugServiceTests` suite. + +## v2021.11.1-preview +### Monday, November 22, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 👷 [vscode-powershell #3682](https://github.com/PowerShell/vscode-powershell/pull/3682) - Remove Windows Server 2016 from CI. +- #️⃣ 🙏 [vscode-powershell #3681](https://github.com/PowerShell/vscode-powershell/pull/3681) - Update `vsce` to `2.2.0`. +- 🐛 🚨 [vscode-powershell #3674](https://github.com/PowerShell/vscode-powershell/pull/3674) - Skip `UpdatePowerShell` tests in CI. +- ✨ 🚨 [vscode-powershell #3643](https://github.com/PowerShell/vscode-powershell/pull/3643) - Improve test stability with `ensureEditorServicesIsConnected`. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 📖 [PowerShellEditorServices #1631](https://github.com/PowerShell/PowerShellEditorServices/pull/1631) - Add Justin Grote as maintainer. +- 🐛 🔍 [vscode-powershell #3667](https://github.com/PowerShell/PowerShellEditorServices/pull/1630) - Improve debugger's variable population mechanism. (Thanks @JustinGrote and @SeeminglyScience!) +- 🐛 👷 [PowerShellEditorServices #1628](https://github.com/PowerShell/PowerShellEditorServices/pull/1628) - Fix build for Apple M1 when running PowerShell 7.2 (arm64). +- 🐛 👷 [PowerShellEditorServices #1626](https://github.com/PowerShell/PowerShellEditorServices/pull/1626) - Remove Windows Server 2016 from CI. +- ✨ 👷 [PowerShellEditorServices #1619](https://github.com/PowerShell/PowerShellEditorServices/pull/1619) - Install a single `dotnet` SDK. + +## v2021.11.0-preview +### Wednesday, November 03, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 🐢 [vscode-powershell #3652](https://github.com/PowerShell/vscode-powershell/issues/3652) - Pester code lens broken in latest preview. +- 🐛 📟 [vscode-powershell #3653](https://github.com/PowerShell/vscode-powershell/issues/3653) - `$PROFILE` variable has changed type and behavior. +- 🐛 📟 [vscode-powershell #3650](https://github.com/PowerShell/vscode-powershell/issues/3650) - Profiles not loading in lastest preview. +- 🐛 📖 [vscode-powershell #3658](https://github.com/PowerShell/vscode-powershell/pull/3658) - Fix typo in settings for 'Force Clear Scrollback Buffer'. (Thanks @PrzemyslawKlys!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [PowerShellEditorServices #1608](https://github.com/PowerShell/PowerShellEditorServices/pull/1611) - Improve PowerShell command and argument escaping. (Thanks @JustinGrote!) +- 🐛 📟 [PowerShellEditorServices #1603](https://github.com/PowerShell/PowerShellEditorServices/pull/1606) - Add `LengthInBufferCells` back to `EditorServicesConsolePSHostRawUserInterface`. +- #️⃣ 🙏 [PowerShellEditorServices #1604](https://github.com/PowerShell/PowerShellEditorServices/pull/1604) - Fix profile loading and `$PROFILE` variable. + +## v2021.10.3-preview +### Thursday, October 28, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +No changes! New preview for PowerShell Editor Services v3.0.0! + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +This preview release includes a complete overhaul of the core PowerShell engine +of PowerShell Editor Services. +This represents over a year's work, +tracked in [PSES #1295](https://github.com/PowerShell/PowerShellEditorServices/issues/1295) +and implemented in [PSES #1459](https://github.com/PowerShell/PowerShellEditorServices/pull/1459), +and is our answer to many, many issues +opened by users over the last few years. +We're hoping you'll see a marked improvement +in the reliability, performance and footprint +of the extension as a result. + +Previously the Integrated Console was run +by setting threadpool tasks on a shared main runspace, +and where LSP servicing was done with PowerShell idle events. +This lead to overhead, threading issues +and a complex implementation intended to work around +the asymmetry between PowerShell as a synchronous, +single-threaded runtime and a language server +as an asynchronous, multi-threaded service. + +Now, PowerShell Editor Services maintains its own dedicated pipeline thread, +which is able to service requests similar to JavaScript's event loop, +meaning we can run everything synchronously on the correct thread. +We also get more efficiency because we can directly call +PowerShell APIs and code written in C# from this thread, +without the overhead of a PowerShell pipeline. + +This change has overhauled how we service LSP requests, +how the Integrated Console works, +how PSReadLine is integrated, +how debugging is implemented, +how remoting is handled, +and a long tail of other features in PowerShell Editor Services. + +Also, in making it, while 6,000 lines of code were added, +we removed 12,000, +for a more maintainable, more efficient +and easier to understand extension backend. + +While most of our testing has been re-enabled +(and we're working on adding more), +there are bound to be issues with this new implementation. +Please give this a try and let us know if you run into anything. + +We also want to thank [@SeeminglyScience](https://github.com/SeeminglyScience) +for his help and knowledge as we've made this migration. + +Finally, a crude breakdown of the work from the commits: + +- An initial dedicated pipeline thread consumer implementation +- Implement the console REPL +- Implement PSRL idle handling +- Implement completions +- Move to invoking PSRL as a C# delegate +- Implement cancellation and Ctrl+C +- Make F8 work again +- Ensure execution policy is set correctly +- Implement $PROFILE support +- Make nested prompts work +- Implement REPL debugging +- Implement remote debugging in the REPL +- Hook up the debugging UI +- Implement a new concurrent priority queue for PowerShell tasks +- Reimplement the REPL synchronously rather than on its own thread +- Really get debugging working... +- Implement DSC breakpoint support +- Reimplement legacy readline support +- Ensure stdio is still supported as an LSP transport +- Remove PowerShellContextService and other defunct code +- Get integration tests working again (and improve diagnosis of PSES failures) +- Get unit testing working again (except debug service tests) + +## v2021.10.2 +### Thursday, October 28, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +The PSScriptAnalyzer rule explanations now open the beautiful published documentation at +[docs.microsoft.com](https://docs.microsoft.com/powershell/utility-modules/psscriptanalyzer/overview). + +- ✨ ‍🕵️ [vscode-powershell #3642](https://github.com/PowerShell/vscode-powershell/pull/3642) - Point PSScriptAnalyzer rules to published documentation. (Thanks @sdwheeler!) +- ✨ 🚨 [vscode-powershell #3641](https://github.com/PowerShell/vscode-powershell/pull/3641) - Clean up unit tests' descriptions and logical separation. +- ✨ 🚨 [vscode-powershell #3631](https://github.com/PowerShell/vscode-powershell/pull/3631) - Replace `() =>` arrow lambdas with `function ()` for Mocha. +- #️⃣ 🙏 [vscode-powershell #3628](https://github.com/PowerShell/vscode-powershell/pull/3628) - Add missing `glob` dev dependency. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +No changes in this release, but the next preview will include PowerShell Editor Services +v3.0.0, with the pipeline rewrite! + +## v2021.10.1 +### Wednesday, October 20, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +Check out the new [Pester Tests][] adapter by [Justin Grote][] and inspired by [Tyler +Leonhardt][]. While still under development, it provides integration with Visual Studio +Code's new test explorer interface for Pester tests and is quite nice! + +[Pester tests]: https://marketplace.visualstudio.com/items?itemName=pspester.pester-test +[Justin Grote]: https://twitter.com/justinwgrote +[Tyler Leonhardt]: https://github.com/TylerLeonhardt + +- ✨ 👷 [vscode-powershell #3623](https://github.com/PowerShell/vscode-powershell/pull/3623) - Add `LinkEditorServices` task for developers. +- ✨️ 🙏 [vscode-powershell #3430](https://github.com/PowerShell/vscode-powershell/pull/3613) - Setting to Disable Pester Code Lens. (Thanks @JustinGrote!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 👷 [PowerShellEditorServices #1589](https://github.com/PowerShell/PowerShellEditorServices/pull/1589) - Remove `BinClean` dependency from build task. (Thanks @JustinGrote!) +- #️⃣ 🙏 [PowerShellEditorServices #1585](https://github.com/PowerShell/PowerShellEditorServices/pull/1585) - Setting to Disable Pester Code Lens. (Thanks @JustinGrote!) +- #️⃣ 🙏 [PowerShellEditorServices #1578](https://github.com/PowerShell/PowerShellEditorServices/pull/1578) - Fix typo in comments. (Thanks @glennsarti!) + +## v2021.10.0 +### Friday, October 08, 2021 + +This is a hot-fix release for an upstream change to the location of the PSScriptAnalyzer +rules documentation. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🐛 ‍🕵️ [vscode-powershell #3608](https://github.com/PowerShell/vscode-powershell/pull/3608) - Fix base URI for PSScriptAnalyzer rule documentation. (Thanks @bgold09!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +No changes, but stay tuned for major updates! +The [pipeline rewrite](https://github.com/PowerShell/vscode-powershell/projects/14) +work is under review. + +## v2021.9.2 +### Thursday, September 30, 2021 + +This release includes changes from both the `v2021.9.1-preview` and `v2021.9.2-preview`. +There were no changes made to PowerShell Editor Services, but several several bugfixes +made to the extension, and most notably, the extension code is now properly minified and +bundled. This should result in a faster and more reliable extension. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #3592](https://github.com/PowerShell/vscode-powershell/pull/3592) - Remove unused feature commands. (Thanks @CrendKing!) +- 🐛 🚨 [vscode-powershell #3570](https://github.com/PowerShell/vscode-powershell/pull/3570) - Fix path regressions and cover with tests. +- 🐛 📺 [vscode-powershell #3105](https://github.com/PowerShell/vscode-powershell/pull/3564) - Remove accidentally enabled commands. +- ✨ 👷 [vscode-powershell #2450](https://github.com/PowerShell/vscode-powershell/pull/3555) - Bundle the extension. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +No changes. + +## v2021.9.0 +### Thursday, September 09, 2021 + +This release includes changes from both `v2021.8.3-preview` and `v2021.9.0-preview`. + +A new `stopDebugger` notification was added that allows PowerShell Editor Services, +the LSP module, to stop an attached UI debugger (such as VS Code's) +for debugger sessions started by executing code with a `PSBreakpoint` attached. +This may not work in all cases but should improve usability. + +The PowerShell status bar indicator no longer uses custom coloring but instead pulls from the user's theme. +A formatting bug was fixed by community maintainer Patrick Meinecke. +A regression in the debug launch configuration's `script` parameter was fixed and covered with a test. +And finally, the bundled [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer/releases/tag/1.20.0) +was updated to `v1.20.0`. + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📖 [vscode-powershell #3544](https://github.com/PowerShell/vscode-powershell/pull/3544) - Document the trace server setting is valid (despite Code's warning). (Thanks @michal037!) +- #️⃣ 🔍 [vscode-powershell #3522](https://github.com/PowerShell/vscode-powershell/pull/3542) - Allow PowerShell session to start and stop the debugger interface. +- ✨ 📺 [vscode-powershell #2436](https://github.com/PowerShell/vscode-powershell/pull/3531) - Use status bar colors from theme instead of hardcoded values. +- ✨ 🚨 [vscode-powershell #3529](https://github.com/PowerShell/vscode-powershell/pull/3530) - Extend CI test matrix and update readme(s). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 📟 [PowerShellEditorServices #24977523](https://github.com/PowerShell/PowerShellEditorServices/pull/1571) - Implement `LengthInBufferCells` to fix ANSI formatting. (Thanks @SeeminglyScience!) +- ✨ 🔍 [vscode-powershell #3522](https://github.com/PowerShell/PowerShellEditorServices/pull/1570) - Send `stopDebugger` notification when appropriate. +- 🐛 🔍 [vscode-powershell #3537](https://github.com/PowerShell/PowerShellEditorServices/pull/1569) - Fix bug with `ExecuteScriptWithArgsAsync` when `script` is a command. +- ✨ ‍🕵️ [PowerShellEditorServices #1562](https://github.com/PowerShell/PowerShellEditorServices/pull/1562) - Pin PSScriptAnalyzer to `v1.20.0`, Plaster to `v1.1.3` and PSReadLine to `v2.1.0`. + +## v2021.8.2 +### Tuesday, August 24, 2021 + +This release also contains all changes listed in [v2021.8.1-preview](#v202181-preview) +below. Notably it fixes several major issues when debugging scripts that were caused by +threading deadlocks in both PowerShell Editor Services and its library, [OmniSharp's C# +Language Server Protocol][omnisharp] that we resolved by setting the compiler to treat +[CA2007][] as an error. This allowed us to programmatically fix _every_ awaited task to +use `.ConfigureAwait(false)` and so avoid deadlocks caused by the introduction of new +synchronization contexts in user code (such as the use of `System.Windows.Forms`). By +fixing this through a compiler rule, we effectively prevent the issue from recurring. +Additionally, we not only added a full regression test for this scenario but also +re-enabled all the prior `DebugService` unit tests in PowerShell Editor Services. + +While there is still much work to do, we are making significant headway on improve the +debugger's reliability, one of our current project focuses. See the [Debugger Reliability +Project](https://github.com/PowerShell/vscode-powershell/projects/9) for our progress. + +[omnisharp]: https://github.com/OmniSharp/csharp-language-server-protocol +[CA2007]: https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2007 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- #️⃣ 🙏 [vscode-powershell #3518](https://github.com/PowerShell/vscode-powershell/pull/3518) - Update build and task configurations. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🔍 [vscode-powershell #3513](https://github.com/PowerShell/PowerShellEditorServices/pull/1555) - Fix debugger regression where console needed input to start/continue. + +## v2021.8.1-preview +### Thursday, August 19, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 🚨 [vscode-powershell #3506](https://github.com/PowerShell/vscode-powershell/pull/3506) - Update test runner. +- 🐛#️⃣ 🙏 [vscode-powershell #3499](https://github.com/PowerShell/vscode-powershell/pull/3502) - (#3499) Remove msjsdiag.debugger-for-chrome suggestion. (Thanks @corbob!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 🛫 [PowerShellEditorServices #1547](https://github.com/PowerShell/PowerShellEditorServices/pull/1547) - Fix creation of `InitialSessionState` to use `CreateDefault2()`. +- ✨ 👷 [PowerShellEditorServices #1544](https://github.com/PowerShell/PowerShellEditorServices/pull/1546) - Explicitly disable implicit namespace imports. +- ✨ 👷 [PowerShellEditorServices #1545](https://github.com/PowerShell/PowerShellEditorServices/pull/1545) - Make `dotnet test` arguments configurable. +- 🐛 ⏱️ [vscode-powershell #3410](https://github.com/PowerShell/PowerShellEditorServices/pull/1542) - Add regression test for `System.Windows.Forms` bug. +- 🐛 👷 [PowerShellEditorServices #1541](https://github.com/PowerShell/PowerShellEditorServices/pull/1541) - Update C# language version to 10.0 to fix bug with .NET SDK 6 Preview 7. +- 🐛 🚨 [PowerShellEditorServices #1442](https://github.com/PowerShell/PowerShellEditorServices/pull/1540) - Fix tests in `Debugging/DebugServiceTests.cs` and simplify faulty script path logic. +- ✨ 🔍 [PowerShellEditorServices #1532](https://github.com/PowerShell/PowerShellEditorServices/pull/1532) - Make `ExecuteCommandAsync` cancellable . + +## v2021.8.0 +### Monday, August 09, 2021 + +The first stable release since [v2021.6.2](#v202162), this release includes all the +changes from [v2021.8.0-preview](#v202180-preview) and +[v2021.7.0-preview](#v202170-preview) (see below). While the highlights are listed here, +[please read our blog post](https://devblogs.microsoft.com/powershell/powershell-for-visual-studio-code-august-2021-update/) +for the full story! + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #3422](https://github.com/PowerShell/vscode-powershell/pull/3493) - Update extension icon (and use a special preview icon). +- ✨ 👷 [vscode-powershell #2286](https://github.com/PowerShell/vscode-powershell/pull/3461) - Pipeline-ify entire release process. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🔍 [PowerShellEditorServices #1533](https://github.com/PowerShell/PowerShellEditorServices/pull/1533) - Enable and fix many .NET Code Analysis warnings. +- ✨ 👷 [PowerShellEditorServices #1528](https://github.com/PowerShell/PowerShellEditorServices/pull/1528) - Automate entire release process. +- ✨ 🙏 [PowerShellEditorServices #1493](https://github.com/PowerShell/PowerShellEditorServices/pull/1514) - Load only bundled `PSReadLine`. +- 🐛 👷 [PowerShellEditorServices #1513](https://github.com/PowerShell/PowerShellEditorServices/pull/1513) - Import `InvokePesterStub.ps1` from `vscode-powershell` (with history). + +## v2021.8.0-preview +### Tuesday, August 03, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 📺 [vscode-powershell #3422](https://github.com/PowerShell/vscode-powershell/pull/3493) - Update extension icon (and use a special preview icon). +- ✨ 👷 [vscode-powershell #2286](https://github.com/PowerShell/vscode-powershell/pull/3461) - Pipeline-ify entire release process. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🔍 [PowerShellEditorServices #1533](https://github.com/PowerShell/PowerShellEditorServices/pull/1533) - Enable and fix many .NET Code Analysis warnings. +- ✨ 👷 [PowerShellEditorServices #1530](https://github.com/PowerShell/PowerShellEditorServices/pull/1530) - Update release and CI pipelines. +- ✨ 👷 [PowerShellEditorServices #1528](https://github.com/PowerShell/PowerShellEditorServices/pull/1528) - Automate entire release process. +- ✨ 🛫 [PowerShellEditorServices #1527](https://github.com/PowerShell/PowerShellEditorServices/pull/1527) - Add stack trace to resolve event handler on debug. +- ✨ 🛫 [PowerShellEditorServices #1523](https://github.com/PowerShell/PowerShellEditorServices/pull/1526) - Initialize runspaces with `InitialSessionState` object. + +## v2021.7.0-preview +### Thursday, July 15, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- ✨ 👷 [vscode-powershell #3458](https://github.com/PowerShell/vscode-powershell/pull/3458) - Automate more of the release. +- ✨ 👷 [vscode-powershell #3439](https://github.com/PowerShell/vscode-powershell/pull/3439) - Fix `Package` task. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ 🚨 [PowerShellEditorServices #1522](https://github.com/PowerShell/PowerShellEditorServices/pull/1522) - Run new PSReadLine test on Windows. +- ✨ 📖 [PowerShellEditorServices #1519](https://github.com/PowerShell/PowerShellEditorServices/pull/1519) - Update README.md. (Thanks @vladdoster!) +- ✨ 🙏 [PowerShellEditorServices #1493](https://github.com/PowerShell/PowerShellEditorServices/pull/1514) - Load only bundled `PSReadLine`. +- 🐛 👷 [PowerShellEditorServices #1513](https://github.com/PowerShell/PowerShellEditorServices/pull/1513) - Import `InvokePesterStub.ps1` from `vscode-powershell` (with history). +- 🐛 🛫 [PowerShellEditorServices #1503](https://github.com/PowerShell/PowerShellEditorServices/pull/1504) - Handle `incomingSettings` and `profileObject` being null. (Thanks @dkattan!) + +## v2021.6.2 +### Thursday, June 24, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 👷🐛 [vscode-powershell #2536](https://github.com/PowerShell/vscode-powershell/pull/3431) - Release refinements. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 👷🐛 [PowerShellEditorServices #1509](https://github.com/PowerShell/PowerShellEditorServices/issues/1509) - Fix signing of files in release. + +## v2021.6.1 +### Monday, June 21, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 📁✨ [vscode-powershell #3334](https://github.com/PowerShell/vscode-powershell/pull/3416) - Explicitly disable extension for untrusted workspaces. +- 📺 [vscode-powershell #3378](https://github.com/PowerShell/vscode-powershell/pull/3413) - Include `$` in PowerShell word separators. +- #️⃣ 🙏 [vscode-powershell #3390](https://github.com/PowerShell/vscode-powershell/pull/3392) - Change OS-architecture check to work with other locales. (Thanks @mat-ocl!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 [PowerShellEditorServices #1495](https://github.com/PowerShell/PowerShellEditorServices/pull/1500) - Prevent some exceptions. +- #️⃣ 🙏 [vscode-powershell #3395](https://github.com/PowerShell/PowerShellEditorServices/pull/1494) - Work around `dotnet publish` bug. + +## v2021.5.1 +### Thursday, May 27, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +This stable release includes all the changes in the previews since v2021.2.2, plus the +following: + +- 🐛🔧 [vscode-powershell #3221](https://github.com/PowerShell/vscode-powershell/pull/3377) - Disable semantic highlighting by default. +- 📖📺✨ [vscode-powershell #1943](https://github.com/PowerShell/vscode-powershell/pull/3372) - Note that ISE theme is included in this extension. +- 🔧🔍🐛✨ [vscode-powershell #3338](https://github.com/PowerShell/vscode-powershell/pull/3357) - Don't prompt to save untitled PowerShell files when debugging. + +Since we have disabled semantic highlighting by default now, if you wish to re-enable it, +use: + +```json +"[powershell]": { + "editor.semanticHighlighting.enabled": true +} +``` + +We now also remove `-` and `$` from the word separators by default for PowerShell files. +To add them back, use: + +```json +"[powershell]": { + "editor.wordSeparators": "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?" +} +``` + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +This stable release includes all the changes in the previews since v2.3.0, plus the following: + +- ✨👷 [PowerShellEditorServices #1491](https://github.com/PowerShell/PowerShellEditorServices/pull/1491) - Bump OmniSharp to `v0.19.2`. +- 🧠🐛 [vscode-powershell #715](https://github.com/PowerShell/PowerShellEditorServices/pull/1484) - Fix unintentional module import. (Thanks @MartinGC94!) + +The most significant change is the update to [OmniSharp +v0.19.2](https://github.com/OmniSharp/csharp-language-server-protocol/releases/tag/v0.19.2), +from the previous version v0.18.3, released in November 2020. OmniSharp is the underlying +Language Server Protocol and Debug Adapter Protocol server library, and as such is our +biggest dependency. This update brings us to the LSP 3.16 and DAP 1.48.x specifications, +enabling us to start incorporating all the latest LSP changes, and it includes numerous +bug fixes and enhancements resulting in a faster and more stable server and extension +experience. + +## v2021.5.0-preview +### Friday, May 21, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 🔗✨ [vscode-powershell #3359](https://github.com/PowerShell/vscode-powershell/pull/3359) - Exclude `-` and `$` from PowerShell `wordSeparators`. +- 📺✨ [vscode-powershell #3351](https://github.com/PowerShell/vscode-powershell/pull/3356) - Use PowerShell terminal icon (when available). +- 📖✨ [vscode-powershell #3339](https://github.com/PowerShell/vscode-powershell/pull/3340) - Update Description to reflect that PowerShell is for more than scripting. (Thanks @potatoqualitee!) +- 📺🐛 [vscode-powershell #3320](https://github.com/PowerShell/vscode-powershell/pull/3329) - Fix duplicated command registrations. (Thanks @MartinGC94!) +- 📖🐛 [vscode-powershell #2896](https://github.com/PowerShell/vscode-powershell/pull/3322) - Remove "All Rights Reserved" from copyright notices. +- [vscode-powershell #3179](https://github.com/PowerShell/vscode-powershell/pull/3179) - Update @types/vscode and `StatusBarItem` implementation. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🛫🐛 [vscode-powershell #3306](https://github.com/PowerShell/PowerShellEditorServices/pull/1481) - Bump OmniSharp to `v0.19.2-beta0002`. +- 💭✨ [PowerShellEditorServices #1474](https://github.com/PowerShell/PowerShellEditorServices/pull/1474) - Add more logging and internal documentation. +- 🚂✨ [PowerShellEditorServices #1467](https://github.com/PowerShell/PowerShellEditorServices/pull/1467) - Make code more explicit. +- 📖🐛 [PowerShellEditorServices #1465](https://github.com/PowerShell/PowerShellEditorServices/pull/1466) - Remove "All Rights Reserved" from copyright notices. +- 👷✨ [PowerShellEditorServices #1463](https://github.com/PowerShell/PowerShellEditorServices/pull/1464) - Enable CodeQL with `codeql-analysis.yml`. + +## v2021.4.2-preview +### Monday, April 26, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 👷✨ [vscode-powershell #3268](https://github.com/PowerShell/vscode-powershell/pull/3292) - Add `Update-Version` to `ReleaseTools` module. +- 👷🐛 [vscode-powershell #3282](https://github.com/PowerShell/vscode-powershell/pull/3286) - Fix release build pipeline. +- 👷✨ [vscode-powershell #3275](https://github.com/PowerShell/vscode-powershell/pull/3275) - Update vsce to 1.87.1. +- 👷✨ [vscode-powershell #3274](https://github.com/PowerShell/vscode-powershell/pull/3274) - Run `npm audit fix`. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🔍🐛 [PowerShellEditorServices #1460](https://github.com/PowerShell/PowerShellEditorServices/pull/1460) - Bump OmniSharp package to `0.19.2-beta0001`. +- 👷🐛 [PowerShellEditorServices #1455](https://github.com/PowerShell/PowerShellEditorServices/pull/1456) - Fix version in module definition file. + +## v2021.4.1-preview +### Friday, April 02, 2021 + +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- 👷🐛 [vscode-powershell #3267](https://github.com/PowerShell/vscode-powershell/pull/3267) - Update download host of vscode. (Thanks @thosoo!) +- 👷✨ [vscode-powershell #3195](https://github.com/PowerShell/vscode-powershell/pull/3265) - Create new `ReleaseTools` module. +- 📺✨ [vscode-powershell #3236](https://github.com/PowerShell/vscode-powershell/pull/3237) - Use title case and shorter notification text. (Thanks @Tyriar!) +- 🚨🐛 [vscode-powershell #3208](https://github.com/PowerShell/vscode-powershell/pull/3222) - Fix hardcoded extension name string. +- 📖🐛 [vscode-powershell #3049](https://github.com/PowerShell/vscode-powershell/pull/3214) - Update examples-module to use Pester 5. (Thanks @nickkimbrough!) +- 🐛 [vscode-powershell #3209](https://github.com/PowerShell/vscode-powershell/pull/3212) - Remove the rest of the experimental Notebook API. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +Please note that these changes were intended to be included in this preview +release; however, a silent pipeline failure led to the previous version of +PowerShellEditorServices being included instead. These changes will be included +in the next preview release. See: +[#3282](https://github.com/PowerShell/vscode-powershell/issues/3282) + +- 🧠✨ [PowerShellEditorServices #1176](https://github.com/PowerShell/PowerShellEditorServices/pull/1427) - Add '$' as trigger character for completion. (Thanks @MartinGC94!) +- 👷🚨✨ [PowerShellEditorServices #1426](https://github.com/PowerShell/PowerShellEditorServices/pull/1426) - Bump CI images and enable tests on Apple M1. +- ✨ [PowerShellEditorServices #1424](https://github.com/PowerShell/PowerShellEditorServices/pull/1424) - Update to use OmniSharp 0.19.0. +- #️⃣ 🙏 [PowerShellEditorServices #1418](https://github.com/PowerShell/PowerShellEditorServices/pull/1418) - Update CHANGELOG for v2.3.0. +- #️⃣ 🙏 [vscode-powershell #3180](https://github.com/PowerShell/PowerShellEditorServices/pull/1411) - Fix New-EditorFile failing when no Editor window open. (Thanks @corbob!) + +## v2021.2.2 +### Wednesday, February 24, 2021 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 📺 ✨ New semantic highlighting. (Thanks @justinytchen!) +- 🐢 ✨ Added Pester v5 support to problem matcher. (Thanks @fflaten!) +- ✨ 👮 Updated PSScriptAnalyzer to 1.19.1. Fixes formatting bugs! (Thanks @bergmeister!) +- 🛫 🐛 [vscode-powershell #3181](https://github.com/PowerShell/vscode-powershell/pull/3202) - + Fix PowerShell MSIX (Store) detection. +- 🐛 Many squashed bugs! (See previews below for details.) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 👷 ✨ No changes, just releasing a stable version. + +## v2021.2.1-preview +### Tuesday, February 23, 2021 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 👷 🐛 [vscode-powershell #3197](https://github.com/PowerShell/vscode-powershell/pull/3197) - + Some improvements to the release scripts. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 📖 🐛 [PowerShellEditorServices #1416](https://github.com/PowerShell/PowerShellEditorServices/pull/1416) - + Fix some markdownlint errors in README. +- 🛫 🐛 [PowerShellEditorServices #1415](https://github.com/PowerShell/PowerShellEditorServices/pull/1415) - + Fix configuration processing to ensure that profiles are loaded. + +## v2021.2.0-preview +### Friday, February 19, 2021 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🛫 🐛 [vscode-powershell #3132](https://github.com/PowerShell/vscode-powershell/pull/3132) - + Use new brew cask installation syntax for PowerShell installation. (Thanks @philippkahr!) +- 📺 🐛 [vscode-powershell #3177](https://github.com/PowerShell/vscode-powershell/pull/3177) - + Disable VSCode Notebook API prototype while the API is still unstable. +- 👷 ✨ [vscode-powershell #3162](https://github.com/PowerShell/vscode-powershell/pull/3162) - + Rewrite release signing pipeline. +- 💎 🐛 [vscode-powershell #3129](https://github.com/PowerShell/vscode-powershell/pull/3129) - + Add braces to PSCustomObject snippet to play nice with auto-closing pairs. +- 📖 ✨ [vscode-powershell #3152](https://github.com/PowerShell/vscode-powershell/pull/3152) - + Add @andschwa to the README as maintainer. +- 👷 🐛 [vscode-powershell #3099](https://github.com/PowerShell/vscode-powershell/pull/3099) - + Update dependencies to fix CI on macOS. +- 🐢 🐛 [vscode-powershell #3089](https://github.com/PowerShell/vscode-powershell/pull/3089) - + Remove hardcoded output format. +- 📖 🐛 [vscode-powershell #3086](https://github.com/PowerShell/vscode-powershell/pull/3086) - + Fix typo in description of legacy codelens description. (Thanks @nexxai!) +- 🚂 ✨ [vscode-powershell #3053](https://github.com/PowerShell/vscode-powershell/pull/3053) - + Use VSCode telemetry endpoint for PSES telemetry. +- 🚂 ✨ [vscode-powershell #3047](https://github.com/PowerShell/vscode-powershell/pull/3047) - + Update language server client. +- 🐢 ✨ [vscode-powershell #2998](https://github.com/PowerShell/vscode-powershell/pull/2998) - + Added Pester v5 support to problem matcher. (Thanks @fflaten!) +- ✂️ 🐛 [vscode-powershell #3023](https://github.com/PowerShell/vscode-powershell/pull/3023) - + Ensure help completions only run on powershell scripts. +- 🛫 🐛 [vscode-powershell #2973](https://github.com/PowerShell/vscode-powershell/pull/2973) - + Fix session menu fails to open when PowerShell extension is starting. (Thanks @jeffpatton1971!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 👷 ✨ [PowerShellEditorServices #1408](https://github.com/PowerShell/PowerShellEditorServices/pull/1408) - + Rewrite release signing pipeline. +- 🚨 ✨ [PowerShellEditorServices #1398](https://github.com/PowerShell/PowerShellEditorServices/pull/1398) - + Refactor e2e tests. +- 🚂 ✨ [PowerShellEditorServices #1381](https://github.com/PowerShell/PowerShellEditorServices/pull/1381) - + Hook up Telemetry LSP event and add telemetry event when users opt-out/in to features. +- 👷 🐛 [PowerShellEditorServices #1397](https://github.com/PowerShell/PowerShellEditorServices/pull/1397) - + More compliant NuGet.config. +- 📺 🐛 [vscode-powershell #3071](https://github.com/PowerShell/PowerShellEditorServices/pull/1394) - + Fix #1393: Always use local help to return cmdlet help text. (Thanks @deadlydog!) +- 🚂 ✨ [PowerShellEditorServices #1376](https://github.com/PowerShell/PowerShellEditorServices/pull/1376) - + Move to Omnisharp lib 0.18.x. +- 🛫 🐛 [vscode-powershell #2965](https://github.com/PowerShell/PowerShellEditorServices/pull/1363) - + Fix error when started in low .NET versions. +- 📖 🐛 [PowerShellEditorServices #1364](https://github.com/PowerShell/PowerShellEditorServices/pull/1364) - + Typos in README.md. (Thanks @robotboyfriend!) + +## v2020.9.0-preview +### Wednesday, September 16, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 📺✨ [vscode-powershell #2919](https://github.com/PowerShell/vscode-powershell/pull/2919) - + Create new Untitled Notebooks and support for Automatic Notebooks (`*.Notebook.ps1`). +- 📺✨ [vscode-powershell #2935](https://github.com/PowerShell/vscode-powershell/pull/2935) - + Add ISE theme settings borders. (Thanks @CalistusK!) +- 👷✨ [vscode-powershell #2922](https://github.com/PowerShell/vscode-powershell/pull/2922) - + Add editorconfig to recommended extensions for the local build. (Thanks @xtqqczze!) +- 👷✨ [vscode-powershell #2889](https://github.com/PowerShell/vscode-powershell/pull/2889) - + Use spaces instead of tabs for consistency. (Thanks @xtqqczze!) +- 👷✨ [vscode-powershell #2884](https://github.com/PowerShell/vscode-powershell/pull/2884) - + Update copyright header in `*.ps1`, `*.psm1` files. (Thanks @xtqqczze!) +- 🐢🐛 [vscode-powershell #2888](https://github.com/PowerShell/vscode-powershell/pull/2888) - + Fixed crash when running pester older than 3.4.5. (Thanks @EmmanuelPineiro!) +- 👷✨ [vscode-powershell #2881](https://github.com/PowerShell/vscode-powershell/pull/2881) - + Remove UTF-8 BOM from misc text files. (Thanks @xtqqczze!) +- 👷✨ [vscode-powershell #2876](https://github.com/PowerShell/vscode-powershell/pull/2876) - + Update text in LICENSE.txt. (Thanks @xtqqczze!) +- 📺✨ [vscode-powershell #2861](https://github.com/PowerShell/vscode-powershell/pull/2861) - + Update LSP Client to use new Semantic Highlighting APIs. (Thanks @justinytchen!) +- 👷✨ [vscode-powershell #2871](https://github.com/PowerShell/vscode-powershell/pull/2871) - + Prevent `Update Notebook dts` action from triggering on forked repositories. (Thanks @corbob!) +- 🔧🐛 [vscode-powershell #2863](https://github.com/PowerShell/vscode-powershell/pull/2863) - + Fix migration of `codeFormatting.addWhitespaceAroundPipe` setting when it doesn't already exist. +- 📺🐛 [vscode-powershell #2845](https://github.com/PowerShell/vscode-powershell/pull/2848) - + Handle block comments with text on the same line as <# #> in Notebook Mode. +- ✨ [vscode-powershell #2855](https://github.com/PowerShell/vscode-powershell/pull/2855) - + Expose the extension integration API via exports instead of editor commands. +- 📺✨ [vscode-powershell #2844](https://github.com/PowerShell/vscode-powershell/pull/2844) - + Use property scope in the PowerShell ISE theme for better Semantic Highlighting. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🧠✨ [vscode-powershell #2898](https://github.com/PowerShell/PowerShellEditorServices/pull/1352) - + Type and Namespace completions now have tooltips. (Thanks @AspenForester!) +- 🛫🐛 [vscode-powershell #2719](https://github.com/PowerShell/PowerShellEditorServices/pull/1349) - + Fix startup assembly version loading issue in PowerShell 6 and up. +- 🔗🐛 [vscode-powershell #2810](https://github.com/PowerShell/PowerShellEditorServices/pull/1348) - + Fix reference number on Windows due to directory separator difference on Windows. +- 📺✨ [PowerShellEditorServices #1343](https://github.com/PowerShell/PowerShellEditorServices/pull/1343) - + Updated Semantic Handler to work with new LSP APIs. (Thanks @justinytchen!) +- 📺✨ [PowerShellEditorServices #1337](https://github.com/PowerShell/PowerShellEditorServices/pull/1337) - + Treat `Member`s as `Properties` in Semantic Highlighting for better accuracy. + +## v2020.7.0-preview +### Thursday, July 30, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 📺✨ [vscode-powershell #2834](https://github.com/PowerShell/vscode-powershell/pull/2834) - + Enable LSP proposed features for Semantic Highlighting. Also allow the PowerShell ISE theme to use Semantic Highlighting. +- 👮✨ [vscode-powershell #2831](https://github.com/PowerShell/vscode-powershell/pull/2831) - + Expose new formatter setting `powershell.codeFormatting.useConstantStrings` from PSScriptAnalyzer 1.19.1. (Thanks @bergmeister!) +- 📺✨ [vscode-powershell #2789](https://github.com/PowerShell/vscode-powershell/pull/2789) - + Initial Notebook UI Mode in VS Code Insiders. +- 🔧✨ [vscode-powershell #2693](https://github.com/PowerShell/vscode-powershell/pull/2830) - + Migrate setting value of `powershell.codeFormatting.whitespaceAroundPipe` to new setting `powershell.codeFormatting.addWhitespaceAroundPipe` automatically. (Thanks @bergmeister!) +- 🧹✨ [vscode-powershell #2685](https://github.com/PowerShell/vscode-powershell/pull/2685) - + Refactor vscode-powershell IFeature classes to separate them into features that depend on the language server and features that don't. (Thanks @bergmeister!) +- ✨ [vscode-powershell #2799](https://github.com/PowerShell/vscode-powershell/pull/2799) - + Initial VSCode-extension-facing PowerShell API: registering, unregistering, and getting PowerShell version details. +- 🛫✨ [vscode-powershell #2796](https://github.com/PowerShell/vscode-powershell/pull/2796) - + Add setting to change the cwd of the Powershell Integrated Console. (Thanks @jwfx!) +- 🛫🐛 [vscode-powershell #2780](https://github.com/PowerShell/vscode-powershell/pull/2788) - + Fix quoting of banner for global tool. +- 🔍🐛 [vscode-powershell #2765](https://github.com/PowerShell/vscode-powershell/pull/2775) - + Emit 'terminated' event if PSES is restarted. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 📺✨ [PowerShellEditorServices #1328](https://github.com/PowerShell/PowerShellEditorServices/pull/1328) - + Enable handlers for Semantic Highlighting for better highlighting accuracy. +- 👮✨ [PowerShellEditorServices #1333](https://github.com/PowerShell/PowerShellEditorServices/pull/1333) - + Expose new rule PSAvoidUsingDoubleQuotesForConstantString added in PSScriptAnalyzer 1.19.1. (Thanks @bergmeister!) +- 📺✨ [PowerShellEditorServices #1321](https://github.com/PowerShell/PowerShellEditorServices/pull/1321) - + Needed changes for Notebook UI Support. +- 🛫✨ [PowerShellEditorServices #1323](https://github.com/PowerShell/PowerShellEditorServices/pull/1323) - + Add cwd property to settings. (Thanks @jwfx!) +- 🛫🐛 [PowerShellEditorServices #1317](https://github.com/PowerShell/PowerShellEditorServices/pull/1318) - + Move tests to PS7 and PS7.1 and fix IsNetCore check. +- 🔗✨ [PowerShellEditorServices #1316](https://github.com/PowerShell/PowerShellEditorServices/pull/1316) - + Return null when Hover request is cancelled or no symbol details. (Thanks @ralish!) +- 🛫🐛 [vscode-powershell #2763](https://github.com/PowerShell/PowerShellEditorServices/pull/1315) - + TLS 1.2 Support When Installing PackageManagement Module. (Thanks @serkanz!) + +## v2020.6.0 +### Thursday, June 11, 2020 + +- ⚡️🧠 Better performance of overall. +- ✨🛫 Support for ConstrainedLanguage mode. +- 🐛 Many squashed bugs +- ✨👮 Updated PSScriptAnalyzer to 1.19.0. + - More formatting settings! (Thanks @bergmeister!) +- 📟 ✨ Updated PSReadLine to 2.0.2. +(From now on, +the stable extension will have the latest stable version of PSReadLine and the PowerShell Preview extension will have the latest preview of PSReadLine) + +## v2020.6.1-preview +### Monday, June 08, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 👷 ✨ [vscode-powershell #2740](https://github.com/PowerShell/vscode-powershell/pull/2740) - + Add CodeQL security scanning. (Thanks @jhutchings1!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🔗 🐛 [PowerShellEditorServices #1304](https://github.com/PowerShell/PowerShellEditorServices/pull/1304) - + Use From instead of FromFileSystem fixing CodeLens references. +- 📟 ✨ [PowerShellEditorServices #1290](https://github.com/PowerShell/PowerShellEditorServices/pull/1290) - + Allow PSReadLine to work in ConstrainedLanguage mode. +- 📟 ✨ The PowerShell Preview extension now uses v2.1.0-preview.2 of PSReadLine. +If you want the predictions feature back, add the following to your `$PROFILE`: + +```pwsh +Set-PSReadLineOption -PredictionSource History +``` + +## v2020.6.0-preview +### Monday, June 01, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🐢✨ [vscode-powershell #2730](https://github.com/PowerShell/vscode-powershell/pull/2730) - + Support adding an `OutputFile` and allow running Pester tests from the command pallet. +- 🔗🐛 [vscode-powershell #2705](https://github.com/PowerShell/vscode-powershell/pull/2705) - + Tweak CodeLens logic now that we use Omnisharp's serializer. +- 📺✨ [vscode-powershell #2702](https://github.com/PowerShell/vscode-powershell/pull/2702) - + Add coloring for `$` and remove it from `wordSepartors`. (Thanks @MJECloud!) +- 📺✨ [vscode-powershell #2704](https://github.com/PowerShell/vscode-powershell/pull/2704) - + Add buttons for moving the terminal pane around. (Thanks @MartinGC94!) +- 👮‍🐛 [vscode-powershell #2703](https://github.com/PowerShell/vscode-powershell/pull/2703) - + Tweak `whitespaceAroundPipe` settings migration logic to do it only once. (Thanks @bergmeister!) +- 👮‍🐛 [vscode-powershell #2698](https://github.com/PowerShell/vscode-powershell/pull/2698) - + Change default of `powershell.codeFormatting.pipelineIndentationStyle` from None back to NoIndentation due to PSScriptAnalyzer bug. (Thanks @bergmeister!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🚂✨ [PowerShellEditorServices #1301](https://github.com/PowerShell/PowerShellEditorServices/pull/1301) - + Fix `AddLanguageProtocolLogging` OmniSharp breaking change. +- 🚨✨ [PowerShellEditorServices #1298](https://github.com/PowerShell/PowerShellEditorServices/pull/1298) - + Remove leftover csproj reference to already removed project in test project PowerShellEditorServices.Test.Host.csproj. (Thanks @bergmeister!) +- 🚂✨ [PowerShellEditorServices #1300](https://github.com/PowerShell/PowerShellEditorServices/pull/1300) - + Address breaking changes in Omnisharp lib and depend on `DocumentUri` more. +- 🚂✨ [PowerShellEditorServices #1291](https://github.com/PowerShell/PowerShellEditorServices/pull/1291) - + Depend on `DocumentUri` for handing vscode `Uri`'s. +- 🧠✨ [vscode-powershell #2706](https://github.com/PowerShell/PowerShellEditorServices/pull/1294) - + Support `completionItem/resolve` request for comparison operators to show tooltip information. + +## v2020.5.0-preview +### Wednesday, May 13, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨🐢 [vscode-powershell #2670](https://github.com/PowerShell/vscode-powershell/pull/2670) - + Add debug output setting for Pester. (Thanks @nohwnd!) +- ✨🔧 [vscode-powershell #2689](https://github.com/PowerShell/vscode-powershell/pull/2689) - + Migrate setting value of `powershell.codeFormatting.whitespaceAroundPipe` to `powershell.codeFormatting.addWhitespaceAroundPipe` automatically. (Thanks @bergmeister!) +- 🐛🔧 [vscode-powershell #2688](https://github.com/PowerShell/vscode-powershell/pull/2688) - + Respect user choice when dismissing the `powerShellExePath` dialog. (Thanks @bergmeister!) +- ✨👷 [vscode-powershell #2686](https://github.com/PowerShell/vscode-powershell/pull/2686) - + Code clean up around some unused variables. (Thanks @bergmeister!) +- 🐛🐢 [vscode-powershell #2676](https://github.com/PowerShell/vscode-powershell/pull/2676) - + Fix Pester invocation for 3x versions. (Thanks @nohwnd!) +- ✨👮‍ [vscode-powershell #2674](https://github.com/PowerShell/vscode-powershell/pull/2674) - + Add additional settings for PSScriptAnalyzer 1.19. (Thanks @bergmeister!) +- ⚡️🔍 [vscode-powershell #2672](https://github.com/PowerShell/vscode-powershell/pull/2672) - + Use in-memory debug adapter instead of spinning up new process. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🛫🐛 [PowerShellEditorServices #1285](https://github.com/PowerShell/PowerShellEditorServices/pull/1285) - + Use API on ScriptBlock to generate PSCommand to run in ConstrainedLanguage mode. +- ⚡️🧠 [PowerShellEditorServices #1283](https://github.com/PowerShell/PowerShellEditorServices/pull/1283) - + Move to Omnisharp lib 0.17.0 for increased performance. +- ✨👮 [PowerShellEditorServices #1280](https://github.com/PowerShell/PowerShellEditorServices/pull/1280) - + Add additional settings for PSScriptAnalyzer 1.19. (Thanks @bergmeister!) +- 🔗 🐛 [vscode-powershell #305](https://github.com/PowerShell/PowerShellEditorServices/pull/1279) - + Fix document highlight column. +- 🐛🧠 [PowerShellEditorServices #1276](https://github.com/PowerShell/PowerShellEditorServices/pull/1276) - + Handle when no CommandInfo comes back from Get-Command to prevent an Exception showing up in logs. + +## v2020.4.3-preview +### Tuesday, April 28, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🛫 ✨ [vscode-powershell #2651](https://github.com/PowerShell/vscode-powershell/pull/2651) - + Add setting for the PackageManagement update feature. +- 👮‍ 🐛 [vscode-powershell #2659](https://github.com/PowerShell/vscode-powershell/pull/2659) - + Remove broken 'Select PSScriptAnalyzer Rules' command. (Thanks @bergmeister!) +- 🛫 ✨ [vscode-powershell #2526](https://github.com/PowerShell/vscode-powershell/pull/2653) - + Clean up WaitForSessionFile logic and support increasing timeout with warning. +- 📟 ✨ [vscode-powershell #2644](https://github.com/PowerShell/vscode-powershell/pull/2644) - + Display preview state and version info in PSIC startup banner. (Thanks @rkeithhill!) +- 👷 ✨ [vscode-powershell #2645](https://github.com/PowerShell/vscode-powershell/pull/2645) - + Add workspace file to load both vscode-powershell and PSES. (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 📟 🐛 [PowerShellEditorServices #1272](https://github.com/PowerShell/PowerShellEditorServices/pull/1272) - + Allow progress colors to be settable and gettable from the internal host. +- 🛫 ✨ [PowerShellEditorServices #1239](https://github.com/PowerShell/PowerShellEditorServices/pull/1239) - + Prompt to update PackageManagement when using an old version. +- 🛫 ✨ [PowerShellEditorServices #1269](https://github.com/PowerShell/PowerShellEditorServices/pull/1269) - + Support ConstrainedLanguage mode. +- 📺 ✨ [PowerShellEditorServices #1268](https://github.com/PowerShell/PowerShellEditorServices/pull/1268) - + Refactor GetCommandHandler to not use dynamic. +- 🔍 🐛 [vscode-powershell #2654](https://github.com/PowerShell/PowerShellEditorServices/pull/1270) - + Fix interpolation in Log points, switch to double quotes. (Thanks @rkeithhill!) +- [PowerShellEditorServices #1267](https://github.com/PowerShell/PowerShellEditorServices/pull/1267) - + Update module manifest to match current module. +- 📟 🐛 [vscode-powershell #2637](https://github.com/PowerShell/PowerShellEditorServices/pull/1264) - + Leverage internal HostUI to check if VT100 is supported. +- 📟 🐛 [vscode-powershell #2637](https://github.com/PowerShell/PowerShellEditorServices/pull/1263) - + Use stable builds of PSReadLine for the PowerShell extension and preview builds for the PowerShell Preview extension. +- 💎 ✨ [vscode-powershell #2543](https://github.com/PowerShell/PowerShellEditorServices/pull/1262) - + Allow formatting when ScriptAnalysis setting is set to disabled. + +## v2020.4.0 +### Thursday, April 15, 2020 + +- ⚡️🧠 Better performance of overall but especially IntelliSense. +- 🐛📟 Errors show up properly on screen in PowerShell Integrated Console. +- ✨🐢 Run a single test in Pester v5 by setting `"powershell.pester.useLegacyCodeLens": false`. +- 🐛🔧 Ignore files specified in `files.exclude` and `search.exclude` in reference/CodeLens search. + +## v2020.4.2-preview +### Monday, April 13, 2020 +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛📟 [PowerShellEditorServices #1258](https://github.com/PowerShell/PowerShellEditorServices/pull/1258) - + No more warning about PowerShellEditorServices module being imported with unapproved verb. + +## v2020.4.1-preview +### Wednesday, April 09, 2020 +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨📟 [PowerShellEditorServices #1255](https://github.com/PowerShell/PowerShellEditorServices/pull/1255) - + Move PSReadLine invocation into cmdlets to get closer to supporting ConstrainedLanguage mode. Also removes hard coded PSReadLine assembly version. + +## v2020.4.0-preview +### Wednesday, April 08, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨👷 [vscode-powershell #2617](https://github.com/PowerShell/vscode-powershell/pull/2617) - + Use PowerShell Daily in CI. +- 🐛📖 [vscode-powershell #2618](https://github.com/PowerShell/vscode-powershell/pull/2618) - + Fix link to 'Exchange Online Connection' in community snippets ToC. (Thanks @hjorslev!) +- 🐛🐢 [vscode-powershell #2606](https://github.com/PowerShell/vscode-powershell/pull/2606) - + Fix Pester CodeLens setting which allows Pester v4 scripts to work again. (Thanks @nohwnd!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨👷 [PowerShellEditorServices #1252](https://github.com/PowerShell/PowerShellEditorServices/pull/1252) - + Use PowerShell Daily in CI. +- 🐛⚡️🧠🔗 [PowerShellEditorServices #1251](https://github.com/PowerShell/PowerShellEditorServices/pull/1251) - + Add cancellation to SignatureHelp request and cache results for cmdlets on `Get-Command` and `Get-Help`. + +## v2020.3.2-preview +### Tuesday, March 31, 2020 +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨📟 [PowerShellEditorServices #1245](https://github.com/PowerShell/PowerShellEditorServices/pull/1245) - + Better PSReadLine version filter check to include 2.1.0+ prereleases. +- 🐛⚡️🧠🔗 [PowerShellEditorServices #1248](https://github.com/PowerShell/PowerShellEditorServices/pull/1248) - + Fix cancellation for completions and add `textDocument/hover` cancellation support. + +## v2020.3.1-preview +### Thursday, March 26, 2020 +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛🧠 [vscode-powershell #2584](https://github.com/PowerShell/PowerShellEditorServices/pull/1243) - + Refactor GetCommandSynopsisAsync method to make sure cmdlets with module prefixes work. +- 🐛⚡️🧠📚 [vscode-powershell #2556](https://github.com/PowerShell/PowerShellEditorServices/pull/1238) - + Add cancellation for `textDocument/completion`, `textDocument/codeAction`, `textDocument/folding`. +- ✨👮 [vscode-powershell #2572](https://github.com/PowerShell/PowerShellEditorServices/pull/1241) - + Only run diagnostics on PowerShell files. +- ⚡️🧠 [PowerShellEditorServices #1237](https://github.com/PowerShell/PowerShellEditorServices/pull/1237) - + Optimize when we run GetCommandInfoAsync to use the pipeline less for Intellisense. + +## v2020.3.0-preview +### Thursday, March 12, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🐛👷‍♀️ [vscode-powershell #2533](https://github.com/PowerShell/vscode-powershell/pull/2533) - + Change source repository's recommended extension from ms-vscode.csharp to ms-dotnettools.csharp. (Thanks @devlead!) +- ✨🐢 [vscode-powershell #2441](https://github.com/PowerShell/vscode-powershell/pull/2441) - + Run a single Pester test. (Thanks @nohwnd!) +- 🐛🔧 [vscode-powershell #2524](https://github.com/PowerShell/vscode-powershell/pull/2524) - + Add `files.exclude` and `search.exclude` to configurations sent through to exclude them from PSES functionality + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨🧠 [PowerShellEditorServices #1232](https://github.com/PowerShell/PowerShellEditorServices/pull/1232) - + Only resolve completion items from commands. +- ✨🐢 [PowerShellEditorServices #1167](https://github.com/PowerShell/PowerShellEditorServices/pull/1167) - + Run a single test in Pester v5. (Thanks @nohwnd!) +- 🐛🔍 [vscode-powershell #2534](https://github.com/PowerShell/PowerShellEditorServices/pull/1230) - + Ensure that errors are written to the console when debugging. +- 🐛🔍 [vscode-powershell #2525](https://github.com/PowerShell/PowerShellEditorServices/pull/1229) - + Don't warn users when using `Clear-Host` in temp sessions. +- ✨💎 [PowerShellEditorServices #1228](https://github.com/PowerShell/PowerShellEditorServices/pull/1228) - + Add better logging for formatter and refactor it into 1 class. +- 🐛🚂 [vscode-powershell #2397](https://github.com/PowerShell/PowerShellEditorServices/pull/1227) - + Use Assembly.LoadFile for dependency loading in WinPS. +- ✨🛫 [PowerShellEditorServices #1222](https://github.com/PowerShell/PowerShellEditorServices/pull/1222) - + Make initial logging work in constrained language mode, allowing the desired user-facing error to present. +- 🐛🛫 [PowerShellEditorServices #1225](https://github.com/PowerShell/PowerShellEditorServices/pull/1225) - + Sign Clear-Host.ps1. +- 🐛🛫 [PowerShellEditorServices #1219](https://github.com/PowerShell/PowerShellEditorServices/pull/1219) - + Ensure log directory is created. +- 🐛👷‍♀️ [PowerShellEditorServices #1223](https://github.com/PowerShell/PowerShellEditorServices/pull/1223) - + Change Ms-vscode.csharp to ms-dotnettools.csharp. (Thanks @devlead!) +- 🐛🔧 [PowerShellEditorServices #1220](https://github.com/PowerShell/PowerShellEditorServices/pull/1220) - + Fix typo in settings. +- ✨🔧 [PowerShellEditorServices #1218](https://github.com/PowerShell/PowerShellEditorServices/pull/1218) - + Switch to better document selecting for vim extension. +- 🐛🧠 [PowerShellEditorServices #1217](https://github.com/PowerShell/PowerShellEditorServices/pull/1217) - + Make session-state lock task-reentrant to fix Untitled file debugging. + +## v2020.3.0 +### Thursday, March 12, 2020 + +#### Release of preview work to stable branch + +This release, coinciding with the [GA release of PowerShell 7](https://devblogs.microsoft.com/powershell/announcing-PowerShell-7-0/), +brings a year of work on the PowerShell extension into the stable release. +The timing of this release is deliberate, since some of the new features +depend on additions and bugfixes in PowerShell 7, +while others have a much better experience in PowerShell 7 +thanks to many improvements shipping with it. + +Some changes that come to the stable channel in this release include: + +- [Integration of PSReadLine into the Integrated Console](https://github.com/PowerShell/vscode-PowerShell/issues/535), + enabling syntax highlighting, a better (and more configurable) completion experience, + multiline editing and searchable history in the PowerShell Integrated Console +- Performance and reliability improvements gained + by [replacing](https://github.com/PowerShell/PowerShellEditorServices/pull/1056) + a hand-rolled Language Server Protocol stack + with the LSP server library from the Omnisharp project +- An [ISE compatibility mode](https://github.com/PowerShell/vscode-powershell/pull/2335) + setting to toggle a more ISE-like user experience +- Debugging improvements in PowerShell 7, + [using its new debugging APIs](https://github.com/PowerShell/PowerShellEditorServices/pull/1119) +- [End of support for PowerShell v3/v4 and .NET 4.5.2](https://github.com/PowerShell/vscode-PowerShell/issues/1310) + +After this release, the stable/preview channels will now function as originally intended, +where the preview channel will be the beta release +for features to come out in the following stable release. + +You may also notice that the history of the changelog has changed. +For a full list of changes between this release and the previous stable release, +see [here](https://github.com/PowerShell/vscode-powershell/blob/main/docs/preview_to_stable_changelog.md). +You can find the changelog from the old stable fork +[here](https://github.com/PowerShell/vscode-powershell/blob/legacy/1.x/CHANGELOG.md). + +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨📺 [vscode-PowerShell #2503](https://github.com/PowerShell/vscode-powershell/pull/2503) - + Pick up the PowerShell dotnet global tool as a PowerShell runtime. +- 🐛🛫 [vscode-PowerShell #2491](https://github.com/PowerShell/vscode-powershell/pull/2498) - + Fix a startup issue where console becomes unresponsive due to the client waiting for the terminal PID from VSCode. +- 🐛👮 [vscode-PowerShell #2190](https://github.com/PowerShell/vscode-powershell/pull/2484) - + Look for `PSScriptAnalyzerSettings.psd1` in the workspace root by default for script analysis, + defaulting back to the default rules when not found. +- 🧰 [vscode-PowerShell #2477](https://github.com/PowerShell/vscode-powershell/pull/2477) - + Stop using the `caption` field on `powerShell/showChoicePrompt` messages, + and instead display only the `message` field. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛📟 [PowerShellEditorServices #1201](https://github.com/PowerShell/PowerShellEditorServices/pull/1201) - + Fix newlines in error formatting. +- 🐛👮 [vscode-PowerShell #2489](https://github.com/PowerShell/PowerShellEditorServices/pull/1206) - + Fix PSScriptAnalyzer not using default rules when no settings file present. +- 🐛📟 [vscode-PowerShell #2291](https://github.com/PowerShell/PowerShellEditorServices/pull/1207) - + Fix `Read-Host` dropping characters. +- 🐛📺 [vscode-PowerShell #2424](https://github.com/PowerShell/PowerShellEditorServices/pull/1209) - + Fix `F8` not working repeatedly in an Interactive Debugging session. +- 🐛🛫 [vscode-PowerShell #2404](https://github.com/PowerShell/PowerShellEditorServices/pull/1208) - + Fix execution policy being set incorrectly at startup on Windows. +- 🐛🧠 [vscode-PowerShell #2364](https://github.com/PowerShell/PowerShellEditorServices/pull/1210) - + Fix intellisense and `F5` not working after debugging. +- 🐛🧰 [vscode-PowerShell #2495](https://github.com/PowerShell/PowerShellEditorServices/pull/1211) - + Fix PowerShellEditorServices.Commands module commands not working due to types being moved. +- 🐛👮 [vscode-PowerShell #2516](https://github.com/PowerShell/PowerShellEditorServices/pull/1216) - + Fix CommentHelp for when a function has other problems with it. + +## v2020.2.0 +### Thursday, February 20, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🐛📖 [vscode-PowerShell #2470](https://github.com/PowerShell/vscode-powershell/pull/2470) - + Fix incorrect reference to `New-ManifestModule` in documentation. (Thanks @rbleattler!) +- 🐛📺 [vscode-PowerShell #2469](https://github.com/PowerShell/vscode-powershell/pull/2469) - + Close other open pwsh instances when updating PowerShell. +- 🐛📟 [vscode-PowerShell #2434](https://github.com/powershell/vscode-powershell/pull/2437) - + Use a new VSCode API to hide the integrated terminal from the shell list + until debugging when `showOnStartup` is disabled. +- ✨🐢 [vscode-PowerShell #2445](https://github.com/PowerShell/vscode-powershell/pull/2445) - + Add `Run/Debug Pester tests` context menu options in the VSCode explorer + for Pester test files. (Thanks @bergmeister!) +- 🐛🐢 [vscode-PowerShell #2438](https://github.com/PowerShell/vscode-powershell/pull/2447/) - + Fixes test failures in Pester contexts not showing up in the Problems pane. (Thanks @tillig!) +- 🐛🔍 [vscode-PowerShell #2548](https://github.com/PowerShell/vscode-powershell/pull/2458) - + Show error message instead of not responding when temp debugging is used with an untitled file. +- 👷 [vscode-PowerShell #2465](https://github.com/PowerShell/vscode-powershell/pull/2465) - + Move macOS CI images to 10.14 (Thanks @bergmeister!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛📁 [vscode-PowerShell #2421](https://github.com/powershell/powershelleditorservices/pull/1161) - + Fix WorkspacePath so that references work with non-ASCII characters. +- 🐛📟 [vscode-PowerShell #2372](https://github.com/powershell/powershelleditorservices/pull/1162) - + Fix prompt behavior when debugging. +- 🐛🛫 [PowerShellEditorServices #1171](https://github.com/powershell/powershelleditorservices/pull/1171) - + Fix race condition where running multiple profiles caused errors. +- 🐛📟 [vscode-PowerShell #2420](https://github.com/powershell/powershelleditorservices/pull/1173) - + Fix an issue where pasting to a `Get-Credential` prompt in some Windows versions caused a crash. +- 🐛📟 [vscode-PowerShell #1790](https://github.com/powershell/powershelleditorservices/pull/1174) - + Fix an inconsistency where `Read-Host -Prompt 'prompt'` would return `$null` rather than empty string + when given no input. +- 🐛🔗 [PowerShellEditorServices #1177](https://github.com/powershell/powershelleditorservices/pull/1174) - + Fix an issue where untitled files did not work with CodeLens. +- ⚡️⏱️ [PowerShellEditorServices #1172](https://github.com/powershell/powershelleditorservices/pull/1172) - + Improve `async`/`await` and `Task` usage to reduce concurrency overhead and improve performance. +- 🐛📟 [PowerShellEditorServices #1178](https://github.com/powershell/powershelleditorservices/pull/1178) - + Improve PSReadLine experience where no new line is rendered in the console. +- ✨🔍 [PowerShellEditorServices #1119](https://github.com/powershell/powershelleditorservices/pull/1119) - + Enable new debugging APIs added in PowerShell 7, improving performance and fixing issues where + the debugger would stop responding or be unable to update breakpoints while scripts were running. +- 👷📟 [PowerShellEditorServices #1187](https://github.com/PowerShell/PowerShellEditorServices/pull/1187) - + Upgrade built-in PSReadLine to 2.0.0 GA. +- 🐛👮 [PowerShellEditorServices #1179](https://github.com/PowerShell/PowerShellEditorServices/pull/1179) - + Improve integration with PSScriptAnalyzer, improving performance, + fixing an error when PSScriptAnalyzer is not available, fix CodeActions not appearing on Windows, + fix an issue where the PSModulePath is reset by PSScriptAnalyzer opening new runspaces. +- 🚂 [PowerShellEditorServices #1183](https://github.com/PowerShell/PowerShellEditorServices/pull/1183) - + Close over public APIs not intended for external use and replace with new, async-friendly APIs. + +## v2020.1.0 +### Monday, January 13, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🛫 ✨ [vscode-powershell #2384](https://github.com/PowerShell/vscode-PowerShell/pull/2400) - + Add -Login startup option. +- 🛫 🐛 [vscode-powershell #2380](https://github.com/PowerShell/vscode-PowerShell/pull/2399) - + Make PowerShell names case insensitive for configuration. +- 🛫 📺 ✨ [vscode-powershell #2370](https://github.com/PowerShell/vscode-PowerShell/pull/2398) - + Add configuration to enable/disable banner. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 📺 [vscode-powershell #2405](https://github.com/PowerShell/PowerShellEditorServices/pull/1152) - + Add tooltip to completions ParameterValue. +- 🛫 🐛 [vscode-powershell #2393](https://github.com/PowerShell/PowerShellEditorServices/pull/1151) - + Probe netfx dir for deps. +- 🚂 ⏱️ 🐛 [vscode-powershell #2352](https://github.com/PowerShell/PowerShellEditorServices/pull/1149) - + Fix lock up that occurs when WinForms is executed on the pipeline thread. +- 💭 🐛 [vscode-powershell #2402](https://github.com/PowerShell/PowerShellEditorServices/pull/1150) - + Fix temp debugging after it broke bringing in $psEditor. +- 🧠 🐛 [vscode-powershell #2324](https://github.com/PowerShell/PowerShellEditorServices/pull/1143) - + Fix unicode character uri bug. +- 🛫 📺 ✨ [vscode-powershell #2370](https://github.com/PowerShell/PowerShellEditorServices/pull/1141) - + Make startup banner simpler. +- [vscode-powershell #2386](https://github.com/PowerShell/PowerShellEditorServices/pull/1140) - + Fix uncaught exception when SafeToString returns null. (Thanks @jborean93!) +- 🔗 🐛 [vscode-powershell #2374](https://github.com/PowerShell/PowerShellEditorServices/pull/1139) - + Simplify logic of determining Reference definition. +- 🛫 🐛 [vscode-powershell #2379](https://github.com/PowerShell/PowerShellEditorServices/pull/1138) - + Use -Option AllScope to fix Windows PowerShell error. + +## v2019.12.0 +### Wednesday, December 11, 2019 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨ 📺 [vscode-PowerShell #2335](https://github.com/PowerShell/vscode-powershell/pull/2335) - + Add editor command `PowerShell: Enable/Disable ISE Mode` for ISE emulation in VS Code. +- ⚡️ 🛫 [vscode-PowerShell #2348](https://github.com/PowerShell/vscode-PowerShell/pull/2348) - + Start EditorServices without start script. +- ✨ 📟 [vscode-PowerShell #2316](https://github.com/PowerShell/vscode-PowerShell/pull/2316) - + Add `powershell.integratedConsole.forceClearScrollbackBuffer` setting to enable `Clear-Host` to clear scrollback buffer. +- 🐛 📺 [vscode-PowerShell #2325](https://github.com/PowerShell/vscode-PowerShell/pull/2325) - + Fix update PowerShell feature on windows. +- 🔧 📁 🐛 [vscode-powershell #2099](https://github.com/PowerShell/vscode-PowerShell/pull/2304) - + Use `powerShellDefaultVersion` everywhere and stop using `powerShellExePath`. +- 🐛 📺 [vscode-PowerShell #2294](https://github.com/PowerShell/vscode-PowerShell/pull/2294) - + Buttons show up for untitled files. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 👷 📟 [PowerShellEditorServices #1129](https://github.com/PowerShell/PowerShellEditorServices/pull/1129) - + Update PSReadLine to 2.0.0-rc1 in modules.json. +- 🛫 🐛 ⚡️ [vscode-powershell #2292](https://github.com/PowerShell/PowerShellEditorServices/pull/1118) - + Isolate PSES dependencies from PowerShell on load + make PSES a pure binary module. +- ✨ 📟 [PowerShellEditorServices #1108](https://github.com/PowerShell/PowerShellEditorServices/pull/1108) - + Clear the terminal via the LSP message `editor/clearTerminal`. +- 🔍 🐛 [vscode-powershell #2319](https://github.com/PowerShell/PowerShellEditorServices/pull/1117) - + Run one invocation per SetBreakpoints request. (Thanks @SeeminglyScience!) +- 🐛 [PowerShellEditorServices #1114](https://github.com/PowerShell/PowerShellEditorServices/pull/1114) - + Fix `Import-EditorCommand -Module`. (Thanks @sk82jack!) +- 🐛 🔍 [PowerShellEditorServices #1112](https://github.com/PowerShell/PowerShellEditorServices/pull/1112) - + Fix breakpoint setting deadlock. +- 🔗 🐛 [vscode-powershell #2306](https://github.com/PowerShell/PowerShellEditorServices/pull/1110) - + Fix references on Windows due to bad WorkspacePath. +- ✨ 👷 [PowerShellEditorServices #993](https://github.com/PowerShell/PowerShellEditorServices/pull/993) - + Add devcontainer support for building in container. (Thanks @bergmeister!) +- 🛫 🐛 [vscode-powershell #2311](https://github.com/PowerShell/PowerShellEditorServices/pull/1107) - + Protect against no RootUri (no open workspace). +- 🐛 📟 [vscode-powershell #2274](https://github.com/PowerShell/PowerShellEditorServices/pull/1092) - + Fix '@' appearing in console. +- 👮‍ 🐛 [vscode-powershell #2288](https://github.com/PowerShell/PowerShellEditorServices/pull/1094) - + Use RootUri.LocalPath for workspace path. +- 🐛 👮‍ [PowerShellEditorServices #1101](https://github.com/PowerShell/PowerShellEditorServices/pull/1101) - + Add `PSAvoidAssignmentToAutomaticVariable` to the default set of PSSA rules. (Thanks @bergmeister!) +- 👮‍ 🔗 🐛 [vscode-powershell #2290](https://github.com/PowerShell/PowerShellEditorServices/pull/1098) - + Fix diagnostics not showing in untitled files and now also show CodeLens. +- 🔍 🐛 [vscode-powershell #1850](https://github.com/PowerShell/PowerShellEditorServices/pull/1097) - + Fixes no prompt showing up when debugging. +- 🚂 📺 🐛 [vscode-powershell #2284](https://github.com/PowerShell/PowerShellEditorServices/pull/1096) - + Fix running indicator by ignoring PSRL aborts. + +## v2019.11.0 +### Friday, November 1, 2019 + +#### Special Note +In this release of the preview extension, +we've merged significant architectural work into PowerShell Editor Services. +After several months of work, PSES now uses the Omnisharp LSP library +to handle Language Server Protocol interaction instead of rolling its own, +allowing PSES to concentrate on being a good PowerShell backend. +We hope you'll see increased performance and stability in this release. +As always, [please let us know if you find any issues](https://github.com/PowerShell/vscode-powershell/issues/new/choose). + +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🔧 [vscode-PowerShell #2262](https://github.com/PowerShell/vscode-PowerShell/pull/2262) - + Introduce `powershell.integratedConsole.useLegacyReadline` setting disable PSReadLine. +- 🛫🐛[vscode-powershell #2217](https://github.com/PowerShell/vscode-PowerShell/pull/2238) - + Discover new PowerShell installations, fix startup issue with Windows PowerShell. +- 📺 [vscode-PowerShell #2225](https://github.com/PowerShell/vscode-PowerShell/pull/2225) - + Surface `InvokeRegisteredEditorCommand` in the Command Palette. (Thanks @jpogran!) +- 📺 [vscode-PowerShell #2224](https://github.com/PowerShell/vscode-PowerShell/pull/2224) - + Provide Run Selection button in editor title menu. (Thanks @jpogran!) +- 👷 [vscode-powershell #2229](https://github.com/PowerShell/vscode-PowerShell/pull/2232) - + Fix version check in Install-VSCode.ps1. +- 🚂 [vscode-PowerShell #2226](https://github.com/PowerShell/vscode-PowerShell/pull/2226) - + Changes needed for Omnisharp migration of PowerShellEditorServices. +- 🔍 [vscode-powershell #2144](https://github.com/PowerShell/vscode-PowerShell/pull/2223) - + Fix debugging restart capability by ensuring the session file is not deleted. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 [PowerShellEditorServices #1080](https://github.com/PowerShell/PowerShellEditorServices/pull/1080) - + Remove extra newline in GetComment feature. +- 🐛 [PowerShellEditorServices #1079](https://github.com/PowerShell/PowerShellEditorServices/pull/1079) - + Fix duplicate diagnostics caused by DidChange handler. +- 🔧 [PowerShellEditorServices #1076](https://github.com/PowerShell/PowerShellEditorServices/pull/1076) - + Graduate PSReadLine feature and add UseLegacyReadLine. +- ⚙️ [PowerShellEditorServices #1075](https://github.com/PowerShell/PowerShellEditorServices/pull/1075) - + Lock OmniSharp dependencies to v0.14.0. (Thanks @mholo65!) +- 📟 [PowerShellEditorServices #1064](https://github.com/PowerShell/PowerShellEditorServices/pull/1064) - + Add support for terminal error color settings in PS7. +- 🐛 [PowerShellEditorServices #1073](https://github.com/PowerShell/PowerShellEditorServices/pull/1073) - + Fix prerelease version discovery and fix omnisharp change. +- 🐛 [PowerShellEditorServices #1065](https://github.com/PowerShell/PowerShellEditorServices/pull/1065) - + Fix TEMP debugging. +- 🐛 [vscode-powershell #1753](https://github.com/PowerShell/PowerShellEditorServices/pull/1072) - + Override PSRL ReadKey on Windows as well. +- 🚂 [PowerShellEditorServices #1056](https://github.com/PowerShell/PowerShellEditorServices/pull/1056) - + Re-architect PowerShell Editor Services to use the Omnisharp LSP platform. +- 🐛 [vscode-powershell #2116](https://github.com/PowerShell/PowerShellEditorServices/pull/1044) - + Fix UNC intellisense backslash. + +## v2019.9.0 +### Monday, September 23, 2019 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 👷 [vscode-powershell #1961](https://github.com/PowerShell/vscode-powershell/pull/1961) - + Changelog tools. +- 🐛 [vscode-powershell #2141](https://github.com/PowerShell/vscode-powershell/pull/2141) - + Null check on activeTerminal to workaround vscode behavior. +- ✨ [vscode-powershell #2105](https://github.com/PowerShell/vscode-powershell/pull/2105) - + Prompt to update PowerShell version. +- 🔎 [vscode-powershell #2165](https://github.com/PowerShell/vscode-powershell/pull/2165) - + Add powershell.codeFormatting.autoCorrectAliases setting to add support for optionally correcting aliases as well (added in PSSA 1.18.2). Disabled by default.. (Thanks @bergmeister!) +- ✨ [vscode-powershell #2160](https://github.com/PowerShell/vscode-powershell/pull/2160) - + Added functionality to install the User variant of Stable Edition. (Thanks @Lothindir!) +- ✨ [vscode-powershell #2156](https://github.com/PowerShell/vscode-powershell) - + Default to PowerShell Core on Windows if it's installed. (Thanks @SydneyhSmith!) +- ✨ [vscode-powershell #2084](https://github.com/PowerShell/vscode-powershell/pull/2084) - + Implement #1611 - provide dynamic debug config. (Thanks @rkeithhill!) +- ✨ [vscode-powershell #2024](https://github.com/PowerShell/vscode-powershell/pull/2039) - + Add machine scope per VS Code team request. +- ✨ [vscode-powershell #2081](https://github.com/PowerShell/vscode-powershell/pull/2081) - + Add param-block snippet. (Thanks @AspenForester!) +- 🧹 [vscode-powershell #2062](https://github.com/PowerShell/vscode-powershell/pull/2062) - + Remove redundant snippets. (Thanks @travis-c-lagrone!) +- ✨ [vscode-powershell #1974](https://github.com/PowerShell/vscode-powershell/pull/1974) - + Add #Requires snippets. (Thanks @travis-c-lagrone!) +- 🧹 [vscode-powershell #2063](https://github.com/PowerShell/vscode-powershell/pull/2063) - + Remove redundant community snippets. (Thanks @travis-c-lagrone!) +- 👷 [vscode-powershell #2065](https://github.com/PowerShell/vscode-powershell/pull/2065) - + Update '.vscode/settings.json' to identify snippet files as 'JSON with Comments'. (Thanks @travis-c-lagrone!) +- 📔 [vscode-powershell #2065](https://github.com/PowerShell/vscode-powershell) - + Docs updates. (Thanks @SydneyhSmith!) +- 👷 [vscode-powershell #2038](https://github.com/PowerShell/vscode-powershell/pull/2038) - + Add ADS insiders gallery file to update script. +- 🔎 [vscode-powershell #2037](https://github.com/PowerShell/vscode-powershell/pull/2037) - + Update PSScriptAnalyzer docs Url to point to master branch because master is now the default branch. (Thanks @bergmeister!) +- 🐛 [vscode-powershell #2035](https://github.com/PowerShell/vscode-powershell/pull/2035) - + #1019: Get format settings from document editor instead of global. (Thanks @tillig!) +- 👷 [vscode-powershell #2025](https://github.com/PowerShell/vscode-powershell/pull/2025) - + Fix node version detect logic to handle node v10. (Thanks @rkeithhill!) +- ✨ [vscode-powershell #1946](https://github.com/PowerShell/vscode-powershell/pull/1946) - + Add ArgumentCompleter snippets. (Thanks @travis-c-lagrone!) +- 🧹 [vscode-powershell #2015](https://github.com/PowerShell/vscode-powershell/pull/2015) - + Fix node types version. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 [PowerShellEditorServices #1022](https://github.com/PowerShell/PowerShellEditorServices/pull/1022) - + Catch stream exceptions for some Debug Adapter stability. +- 🔎 [PowerShellEditorServices #1021](https://github.com/PowerShell/PowerShellEditorServices/pull/1021) - + Add AutoCorrectAliases setting (PR to be made in VS-Code repo as well) to add support for optionally correcting aliases as well (added in PSSA 1.18.2). (Thanks @bergmeister!). +- 🐛 [vscode-powershell #1994](https://github.com/PowerShell/PowerShellEditorServices/pull/1000) - + Fix crash when setBreakpoint from VSCode sends a git:/ URI. +- 🧹 [PowerShellEditorServices #988](https://github.com/PowerShell/PowerShellEditorServices/pull/988) - + Remove consoleecho lib for PowerShell 7. +- 📔 [PowerShellEditorServices #986](https://github.com/PowerShell/PowerShellEditorServices) - + Documentation updates. (Thanks @SydneyhSmith!) +- ⚙️ [PowerShellEditorServices #981](https://github.com/PowerShell/PowerShellEditorServices/pull/981) - + Update NewtonSoft.Json dependency from 10.0.3 to 11.02 since PS 6.0 has been deprecated. (Thanks @bergmeister!) +- 🐛 [vscode-powershell #2007](https://github.com/PowerShell/PowerShellEditorServices/pull/974) - + Defend against crash when no PSScriptAnalyzer is found. +- 👷 [PowerShellEditorServices #978](https://github.com/PowerShell/PowerShellEditorServices/pull/977) - + Delete stale WebSocket code. + +## v2019.5.0 +### Wednesday, May 22, 2019 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨ [vscode-PowerShell #1880](https://github.com/PowerShell/vscode-powershell/pull/1911) - + Move to date-based versioning +- ✨ [vscode-PowerShell #1954](https://github.com/PowerShell/vscode-PowerShell/pull/1954) - + Allow passing runspace name +- ✨ [vscode-PowerShell #1945](https://github.com/PowerShell/vscode-PowerShell/pull/1945) - + Edit snippets to support $TM_SELECTED_TEXT (Thanks @travis-c-lagrone!) +- 👷 [vscode-PowerShell #1942](https://github.com/PowerShell/vscode-PowerShell/pull/1942) - + Stop supporting 6.0 +- ✨ [vscode-PowerShell #1928](https://github.com/PowerShell/vscode-PowerShell/pull/1928) - + Add RunCode command for CodeLens providers +- 🐛 [vscode-PowerShell #1927](https://github.com/PowerShell/vscode-PowerShell/pull/1927) - + Fix change session by moving to async/await promise +- 🐛 [vscode-PowerShell #1931](https://github.com/PowerShell/vscode-PowerShell/pull/1931) - + Fix upload bug report +- 🐛 [vscode-PowerShell #1925](https://github.com/PowerShell/vscode-PowerShell/pull/1925) - + Fix error in HtmlContentView.ShowContent when no JS/CSS provided (Thanks @rkeithhill!) +- 🐛 [vscode-PowerShell #1919](https://github.com/PowerShell/vscode-PowerShell/pull/1919) - + Fix CustomViews by switching to WebViews +- 🐛 [vscode-PowerShell #1922](https://github.com/PowerShell/vscode-PowerShell/pull/1922) - + Fix small typo in Function-Inline description (Thanks @V-ed!) +- ✨ [vscode-PowerShell #1908](https://github.com/PowerShell/vscode-PowerShell/pull/1908) - + Add PowerShell version telemetry +- 📖 [vscode-PowerShell #1900](https://github.com/PowerShell/vscode-PowerShell/pull/1900) - + Small update to Azure Data Studio marketplace README (Thanks @SQLvariant!) +- 💻 [vscode-PowerShell #1871](https://github.com/PowerShell/vscode-PowerShell/pull/1871) - + Change CI to use Azure Pipelines +- 🐛 [vscode-PowerShell #1867](https://github.com/PowerShell/vscode-PowerShell/pull/1867) - + Change whitespace settings to camelCase +- 🐛 [vscode-PowerShell #1852](https://github.com/PowerShell/vscode-PowerShell/pull/1852) - + Turn `powershell.codeformatting.useCorrectCasing` setting off by default until PSScriptAnalyzer issues are fixed (Thanks @bergmeister!) +- 🐛 [vscode-powershell #1822](https://github.com/PowerShell/vscode-PowerShell/pull/1838) - + Set featureFlag default to null so that it can be resolved by settings +- 💻 [vscode-PowerShell #1839](https://github.com/PowerShell/vscode-PowerShell/pull/1839) - + Add initial credscan config ymls for CI +- 🐛 [vscode-PowerShell #1837](https://github.com/PowerShell/vscode-PowerShell/pull/1837) - + Don't use -EncodedCommand to start PowerShell on Windows +- 🐛 [vscode-PowerShell #1825](https://github.com/PowerShell/vscode-PowerShell/pull/1825) - + Switch to current lowercase names for powershell and mdlint extensions (Thanks @rkeithhill!) +- 👷 [vscode-PowerShell #1823](https://github.com/PowerShell/vscode-PowerShell/pull/1823) - + Update to official TSLint extension in extensions.json, old version deprecated (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- ✨ [PowerShellEditorServices #951](https://github.com/PowerShell/PowerShellEditorServices/pull/951) - + Allow passing RunspaceName +- 🚨 [PowerShellEditorServices #944](https://github.com/PowerShell/PowerShellEditorServices/pull/944) - + Add integration testing module with simple tests to verify PSES starts and stops +- 🐛 [PowerShellEditorServices #954](https://github.com/PowerShell/PowerShellEditorServices/pull/955) - + Ensure NamedPipeServerStream is assigned in Windows PowerShell +- ✨ [PowerShellEditorServices #952](https://github.com/PowerShell/PowerShellEditorServices/pull/952) - + Update to PSReadLine 2.0.0-beta4 +- ✨ [PowerShellEditorServices #877](https://github.com/PowerShell/PowerShellEditorServices/pull/877) - + Add filtering for CodeLens and References (Thanks @glennsarti!) +- 🐛 [vscode-powershell #1933](https://github.com/PowerShell/PowerShellEditorServices/pull/949) - + Stop crash when workspace doesn't exist +- 👷 [PowerShellEditorServices #878](https://github.com/PowerShell/PowerShellEditorServices/pull/878) - + Remove native named pipes implementation +- 🐛 [PowerShellEditorServices #947](https://github.com/PowerShell/PowerShellEditorServices/pull/947) - + Fix silent failure in VSCode WebViews by using Id for dictionary since multiple pages could have the same title +- 🐛 [PowerShellEditorServices #946](https://github.com/PowerShell/PowerShellEditorServices/pull/946) - + Rename to use async +- 👷 [PowerShellEditorServices #943](https://github.com/PowerShell/PowerShellEditorServices/pull/943) - + Improvements to the log parsing module (Thanks @rkeithhill!) +- 💻 [PowerShellEditorServices #921](https://github.com/PowerShell/PowerShellEditorServices/pull/921) - + Set up CI with Azure Pipelines +- 🐛 [PowerShellEditorServices #908](https://github.com/PowerShell/PowerShellEditorServices/pull/908) - + Fix issue with reference code lens not working with UNC paths (Thanks @rkeithhill!) +- 🐛 [vscode-powershell #1571](https://github.com/PowerShell/PowerShellEditorServices/pull/911) - + Fix faulty netfx check +- 🐛 [PowerShellEditorServices #906](https://github.com/PowerShell/PowerShellEditorServices/pull/906) - + Fix New-EditorFile with no folder or no files open +- ✨ [vscode-powershell #1398](https://github.com/PowerShell/PowerShellEditorServices/pull/902) - + Improve path auto-completion (Thanks @rkeithhill!) +- 🐛 [PowerShellEditorServices #910](https://github.com/PowerShell/PowerShellEditorServices/pull/910) - + Fix UseCorrectCasing to be actually configurable via `powershell.codeFormatting.useCorrectCasing` (Thanks @bergmeister!) +- 👷 [PowerShellEditorServices #909](https://github.com/PowerShell/PowerShellEditorServices/pull/909) - + Use global.json to pin .Net Core SDK version and update it from 2.1.402 to 2.1.602 (Thanks @bergmeister!) +- 👷 [PowerShellEditorServices #903](https://github.com/PowerShell/PowerShellEditorServices/pull/903) - + Move temp folder into repo to avoid state that causes build errors from time to time when rebuilding locally (and packages have updated) (Thanks @bergmeister!) +- 💻 [PowerShellEditorServices #904](https://github.com/PowerShell/PowerShellEditorServices/pull/904) - + Add initial credscan configuation ymls for CI +- 🐛 [PowerShellEditorServices #901](https://github.com/PowerShell/PowerShellEditorServices/pull/901) - + Switch to current lowercase names for powershell and mdlint exts (Thanks @rkeithhill!) + +## v2.0.0-preview.3 +### Wednesday, April 10, 2019 +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1865](https://github.com/PowerShell/vscode-powershell/pull/1867) - + Change casing of `powershell.codeformatting` settings for consistency: + - `powershell.codeformatting.WhitespaceInsideBrace` is now `powershell.codeformatting.whitespaceInsideBrace` + - `powershell.codeformatting.WhitespaceAroundPipe` is now `powershell.codeformatting.whitespaceAroundPipe` +- [vscode-PowerShell #1852](https://github.com/PowerShell/vscode-PowerShell/pull/1852) - + Turn `powershell.codeformatting.useCorrectCasing` setting off by default until PSSA issues are fixed (Thanks @bergmeister!) +- [vscode-PowerShell #1838](https://github.com/PowerShell/vscode-PowerShell/pull/1838) - + Set PSReadLine featureFlag default to null so that it can be resolved by settings +- [vscode-PowerShell #1837](https://github.com/PowerShell/vscode-PowerShell/pull/1837) - + Do not use -EncodedCommand on Windows +- [vscode-PowerShell #1825](https://github.com/PowerShell/vscode-PowerShell/pull/1825) - + Switch to current lowercase names for powershell and mdlint recommended extensions (Thanks @rkeithhill!) +- [vscode-PowerShell #1823](https://github.com/PowerShell/vscode-PowerShell/pull/1823) - + Update to official TSLint ext in extensions.json, old version deprecated (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #902](https://github.com/PowerShell/PowerShellEditorServices/pull/902) - + Improve path auto-completion (Thanks @rkeithhill!) +- [PowerShellEditorServices #910](https://github.com/PowerShell/PowerShellEditorServices/pull/910) - + Fix UseCorrectCasing to be actually configurable via `powershell.codeFormatting.useCorrectCasing` (Thanks @bergmeister!) +- [PowerShellEditorServices #909](https://github.com/PowerShell/PowerShellEditorServices/pull/909) - + Use global.json to pin .Net Core SDK version and update it from 2.1.402 to 2.1.602 (Thanks @bergmeister!) +- [PowerShellEditorServices #903](https://github.com/PowerShell/PowerShellEditorServices/pull/903) - + Move temp folder into repo to avoid state that causes build errors from time to time when rebuilding locally (and packages have updated) (Thanks @bergmeister!) + +## v2.0.0-preview.2 +### Friday, March 29, 2019 + +### Highlights + +- `Write-Progress` work in the integrated console ⏰ +- Support for [PSScriptAnalyzer 1.18](https://github.com/PowerShell/PSScriptAnalyzer/releases/tag/1.18.0) 📝 +- The ability to debug any runspace in any process 🔎 +- PSReadLine enabled by default on Windows 🎨 +- (Bug fix!) You can open untitled workspaces/folders again! 🐛☠️ + +There are a lot more goodies in this version. Checkout the changelog below! + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1794](https://github.com/PowerShell/vscode-PowerShell/pull/1794) - + Make PSReadLine default on Windows +- [vscode-PowerShell #1736](https://github.com/PowerShell/vscode-PowerShell/pull/1736) - + Enable attach to process on Linux and macOS +- [vscode-PowerShell #1729](https://github.com/PowerShell/vscode-PowerShell/pull/1729) - + Handle Pester Describe block strings with single quotes inside it (Thanks @bergmeister!) +- [vscode-PowerShell #1741](https://github.com/PowerShell/vscode-PowerShell/pull/1741) - + Update build to clear node modules directory (Thanks @corbob!) +- [vscode-PowerShell #1743](https://github.com/PowerShell/vscode-PowerShell/pull/1743) - + Fix right-click help lookup not always working (Thanks @corbob!) +- [vscode-PowerShell #1746](https://github.com/PowerShell/vscode-PowerShell/pull/1746) - + Add label property to debug config, change pkg name to lowercase (Thanks @rkeithhill!) +- [vscode-PowerShell #1749](https://github.com/PowerShell/vscode-PowerShell/pull/1749) - + Add the Install-VSCode.ps1 script to signing +- [vscode-PowerShell #1747](https://github.com/PowerShell/vscode-PowerShell/pull/1747) - + Modify `powerShellDefaultVersion` description to make clearer (Thanks @rkeithhill!) +- [vscode-PowerShell #1755](https://github.com/PowerShell/vscode-PowerShell/pull/1755) - + Speed up Travis builds by skipping the .NET Core initialization (Thanks @bergmeister!) +- [vscode-PowerShell #1773](https://github.com/PowerShell/vscode-PowerShell/pull/1773) - + Change debugger type field back to `PowerShell` from `powershell` (Thanks @rkeithhill!) +- [vscode-PowerShell #1757](https://github.com/PowerShell/vscode-PowerShell/pull/1757) - + Match Install-VSCode.ps1 script url with the one from master branch (Thanks @rafaltra!) +- [vscode-PowerShell #1774](https://github.com/PowerShell/vscode-PowerShell/pull/1774) - + Switch to `EncodedCommand` for script execution +- [vscode-PowerShell #1764](https://github.com/PowerShell/vscode-PowerShell/pull/1764) - + Added Pester, ShouldProcess and Calculated Property PS Snippets (Thanks @brettmillerb!) +- [vscode-PowerShell #1776](https://github.com/PowerShell/vscode-PowerShell/pull/1776) - + Migrate Pester version detection into an InovkePester stub script (Thanks @rkeithhill!) +- [vscode-PowerShell #1781](https://github.com/PowerShell/vscode-PowerShell/pull/1781) - + Fix initial launch config casing +- [vscode-PowerShell #1775](https://github.com/PowerShell/vscode-PowerShell/pull/1775) - + Support `-CustomPipeName`, allowing configuration of custom namedpipes for LSP transport +- [vscode-PowerShell #1787](https://github.com/PowerShell/vscode-PowerShell/pull/1787) - + Added SQL PowerShell Examples (Thanks @SQLvariant!) +- [vscode-PowerShell #1782](https://github.com/PowerShell/vscode-PowerShell/pull/1782) - + Add Debug Runspace command (Thanks @adamdriscoll!) +- [vscode-PowerShell #1800](https://github.com/PowerShell/vscode-PowerShell/pull/1800) - + Include current runspace and runspace ID 1 in the PSHostProcess picker dialog +- [vscode-PowerShell #1687](https://github.com/PowerShell/vscode-PowerShell/pull/1687) - + Add new `powershell.useCorrectCasingsettings` for new rule in PSSA 1.18: PSUseCorrectCasing (Thanks @bergmeister!) +- [vscode-PowerShell #1668](https://github.com/PowerShell/vscode-PowerShell/pull/1668) - + Add new `powershell.codeFormatting` settings for new options in PSSA 1.18: WhitespaceInsideBrace and WhitespaceAroundPipe (Thanks @bergmeister!) +- [vscode-PowerShell #1669](https://github.com/PowerShell/vscode-PowerShell/pull/1669) - + Add new `powershell.codeFormatting` settings for new options in PSSA 1.18: PipelineIndentationStyle (Thanks @bergmeister!) +- [vscode-PowerShell #1738](https://github.com/PowerShell/vscode-PowerShell/pull/1738) - + Set CommandExplorer exclusion filter to be empty array by default (Thanks @adilio!) +- [vscode-PowerShell #1686](https://github.com/PowerShell/vscode-PowerShell/pull/1686) - + Add an exclusion filter to the Command Explorer (Thanks @corbob!) +- [vscode-PowerShell #1816](https://github.com/PowerShell/vscode-PowerShell/pull/1816) - + Workaround PSSA #1187 by defaulting to NoIndentation + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #895](https://github.com/PowerShell/PowerShellEditorServices/pull/895) - + Add warning to parameter validation set (Thanks @Benny1007!) +- [PowerShellEditorServices #897](https://github.com/PowerShell/PowerShellEditorServices/pull/897) - + Clean up and pop dead runspaces when using 'attach' debugging +- [PowerShellEditorServices #888](https://github.com/PowerShell/PowerShellEditorServices/pull/888) - + Add new ParseError level to ScriptFileMarkerLevel and filter out PSSA parse errors +- [PowerShellEditorServices #858](https://github.com/PowerShell/PowerShellEditorServices/pull/858) - + Fix XUnit warnings that better assertion operators should be used. (Thanks @bergmeister!) +- [PowerShellEditorServices #854](https://github.com/PowerShell/PowerShellEditorServices/pull/854) - + Reinstate test filtering (Thanks @glennsarti!) +- [PowerShellEditorServices #866](https://github.com/PowerShell/PowerShellEditorServices/pull/866) - + Catch NotSupportedException which can be thrown by FileStream constructor (Thanks @rkeithhill!) +- [PowerShellEditorServices #868](https://github.com/PowerShell/PowerShellEditorServices/pull/868) - + Speed up Travis builds by skipping the .NET Core initialization (Thanks @bergmeister!) +- [PowerShellEditorServices #869](https://github.com/PowerShell/PowerShellEditorServices/pull/869) - + Added `AsNewFile` switch to Out-CurrentFile (Thanks @dfinke!) +- [PowerShellEditorServices #873](https://github.com/PowerShell/PowerShellEditorServices/pull/873) - + Return the start line number for Describe block (Thanks @rkeithhill!) +- [PowerShellEditorServices #876](https://github.com/PowerShell/PowerShellEditorServices/pull/876) - + Temporarily disable deemphasized stack frames to fix VSCode issue 1750 (Thanks @rkeithhill!) +- [PowerShellEditorServices #871](https://github.com/PowerShell/PowerShellEditorServices/pull/871) - + Support -CustomPipeName, allowing configuration of custom namedpipes for LSP transport +- [PowerShellEditorServices #872](https://github.com/PowerShell/PowerShellEditorServices/pull/872) - + Fix unable to open files in problems/peek windows issue (Thanks @rkeithhill!) +- [PowerShellEditorServices #875](https://github.com/PowerShell/PowerShellEditorServices/pull/875) - + Add attach to local runspace. (Thanks @adamdriscoll!) +- [PowerShellEditorServices #881](https://github.com/PowerShell/PowerShellEditorServices/pull/881) - + Use `NamedPipeConnectionInfo` to connect to remote runspaces instead of Enter-PSHostProcess +- [PowerShellEditorServices #845](https://github.com/PowerShell/PowerShellEditorServices/pull/845) - + Enable UseCorrectCasing as a default rule (Thanks @bergmeister!) +- [PowerShellEditorServices #835](https://github.com/PowerShell/PowerShellEditorServices/pull/835) - + Map new `powershell.codeformatting` settings WhitespaceInsideBrace and WhitespaceAroundPipe to PSSA settings hashtable (Thanks @bergmeister!) +- [PowerShellEditorServices #836](https://github.com/PowerShell/PowerShellEditorServices/pull/836) - + Add PipelineIndentationStyle configuration mapping (Thanks @bergmeister!) +- [PowerShellEditorServices #887](https://github.com/PowerShell/PowerShellEditorServices/pull/887) - + Cherry pick PR 1750 merge commit to legacy/v1.x, has additional fixes (Thanks @rkeithhill!) +- [PowerShellEditorServices #874](https://github.com/PowerShell/PowerShellEditorServices/pull/874) - + Use public `InternalHost` from origin runspace (Thanks @SeeminglyScience!) +- [PowerShellEditorServices #889](https://github.com/PowerShell/PowerShellEditorServices/pull/889) - + Enhance Get-PsesRpcNotificationMessage/MessageResponseTimes to allow filtering by message name (Thanks @rkeithhill!) +- [PowerShellEditorServices #859](https://github.com/PowerShell/PowerShellEditorServices/pull/859) - + Upgrade PowerShellStandard.Library, PowerShell.SDK, NET.Test.SDK and Serilog NuGet packages to latest released version and enable AppVeyor build on any branch (Thanks @bergmeister!) +- [PowerShellEditorServices #862](https://github.com/PowerShell/PowerShellEditorServices/pull/862) - + Handle arbitrary exceptions when recursing workspace + +## v2.0.0-preview.1 +### Wednesday, January 23, 2019 + +#### Preview builds of the PowerShell extension are now available in VSCode + +We are excited to announce the PowerShell Preview extension in the VSCode marketplace! +The PowerShell Preview extension allows users on Windows PowerShell 5.1 and PowerShell Core 6 to get and test the latest updates +to the PowerShell extension and comes with some exciting features. + +The PowerShell Preview extension is a substitute for the PowerShell extension so +both the PowerShell extension and the PowerShell Preview extension should not be enabled at the same time. + +By having a preview channel, in addition to our existing stable channel, we can get new features out faster and get feedback faster from you, the users. + +##### How to Get/Use the PowerShell Preview extension + +If you dont already have VSCode, start [here](https://code.visualstudio.com/Docs/setup/setup-overview). + +Once you have VSCode open, click `Clt+Shift+X` to open the extensions marketplace. +Next, type `PowerShell Preview` in the search bar. +Click `Install` on the `PowerShell Preview` page. +Finally, click `Reload` in order to refresh VSCode. + +If you already have the PowerShell extension, please disable it to use the Powershell Preview extension. +To disable the PowerShell extension, find it in the Extensions sidebar view, specifically under the list of Enabled extensions, +Right-click on the PowerShell extension and select `Disable`. +Please note that it is important to only have either the PowerShell extension or the PowerShell Preview extension enabled at one time. +![How to Disable](https://github.com/PowerShell/powershell.github.io/blob/master/PowerShell-Blog/Images/disable-extension.jpg) + +#### What the first preview contains + +The v2.0.0-preview.1 version of the extension is built on .NET Standard +(enabling support for both Windows PowerShell and PowerShell Core from one assembly) + +It also contains PSReadLine support in the integrated console for Windows behind a feature flag. +PSReadLine provides a consistent and rich interactive experience, +including syntax coloring and multi-line editing and history, in the PowerShell console, in Cloud Shell, +and now in VSCode terminal. For more information on the benefits of PSReadLine, +check out their [documentation](https://docs.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline?view=powershell-6). + +To enable PSReadLine support in the Preview version on Windows, please add the following to your user settings: + +```json +"powershell.developer.featureFlags": [ "PSReadLine" ] +``` + +HUGE thanks to @SeeminglyScience for all his amazing work getting PSReadLine working in PowerShell Editor Services! + +#### Breaking Changes + +As stated above, this version of the PowerShell extension only works with Windows PowerShell versions 5.1 and PowerShell Core 6. + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1587](https://github.com/PowerShell/vscode-PowerShell/pull/1587) - + Removed ShowOnlineHelp Command (Thanks @corbob!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #792](https://github.com/PowerShell/PowerShellEditorServices/pull/792) - + Add Async suffix to async methods (Thanks @dee-see!) +- [PowerShellEditorServices #775](https://github.com/PowerShell/PowerShellEditorServices/pull/775) - + Removed ShowOnlineHelp Message (Thanks @corbob!) +- [PowerShellEditorServices #769](https://github.com/PowerShell/PowerShellEditorServices/pull/769) - + Set Runspaces to use STA when running in Windows PowerShell +- [PowerShellEditorServices #741](https://github.com/PowerShell/PowerShellEditorServices/pull/741) - + Migrate to netstandard2.0 and PSStandard +- [PowerShellEditorServices #672](https://github.com/PowerShell/PowerShellEditorServices/pull/672) - + PSReadLine integration (Thanks @SeeminglyScience!) + +## v1.10.2 +### Tuesday, December 18, 2018 + +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- [vscode-PowerShell #1632](https://github.com/PowerShell/vscode-powershell/pull/1632) - + Started [a document for ISE-like configuration of VSCode](https://github.com/PowerShell/vscode-powershell/blob/main/docs/ise_compatibility.md). + Please help us build it out by [contirbuting an edit](https://github.com/PowerShell/vscode-powershell/edit/main/docs/ise_compatibility.md). + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- [PowerShellEditorServices #811](https://github.com/PowerShell/PowerShellEditorServices/pull/805) - + Fix token-based folding (thanks @glennsarti!) +- [PowerShellEditorServices #823](https://github.com/PowerShell/PowerShellEditorServices/pull/823) - + Fix case-sensitivity of Pester CodeLens (thanks @bergmeister!) +- [PowerShellEditorServices #815](https://github.com/PowerShell/PowerShellEditorServices/pull/815) - + Fix crash when untitled files opened as PowerShell +- [PowerShellEditorServices #826](https://github.com/PowerShell/PowerShellEditorServices/pull/826) - + Fix crash when duplicate references are present in the same file + +## v1.10.1 +### Friday, December 7, 2018 + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- [PowerShellEditorServices #808](https://github.com/PowerShell/PowerShellEditorServices/pull/808) - + Fix startup crash on Windows 7 +- [PowerShellEditorServices #807](https://github.com/PowerShell/PowerShellEditorServices/pull/807) - + Fix deadlock occurring while connecting to named pipes + +## v1.10.0 +### Monday, December 3, 2018 +#### [vscode-powershell](https://github.com/PowerShell/vscode-powershell) + +- [vscode-PowerShell #1610](https://github.com/PowerShell/vscode-powershell/pull/1610) - + Remove client-side syntax folding provider in favor of server-side provider (thanks @glennsarti!) +- [vscode-PowerShell #1616](https://github.com/PowerShell/vscode-powershell/pull/1616) - + Make `Restart Current Session` always available in the session quick pick +- [vscode-PowerShell #1406](https://github.com/PowerShell/vscode-powershell/pull/1406) - + Add a Show-Command explorer (thanks @corbob!) +- [vscode-PowerShell #1615](https://github.com/PowerShell/vscode-powershell/pull/1615) - + Fix Pester CodeLens not working for running/debugging tests (thanks @rkeithhill!) +- [vscode-PowerShell #1600](https://github.com/PowerShell/vscode-powershell/pull/1608) - + Add CodeAction support to show PSSA rule documentation (thanks @rkeithhill!) +- [vscode-PowerShell #1606](https://github.com/PowerShell/vscode-powershell/pull/1606) - + Add Ctrl+Alt+J (Cmd+Alt+J on macOS) + keybinding to open up list of available snippets +- [vscode-PowerShell #1597](https://github.com/PowerShell/vscode-powershell/pull/1597) - + Make `Install-VSCode.ps1` work on macOS and Linux. Get the script [here](https://github.com/PowerShell/vscode-powershell/blob/main/scripts/Install-VSCode.ps1) +- [vscode-PowerShell #1580](https://github.com/PowerShell/vscode-powershell/pull/1580) - + `New-EditorFile` works on non-PowerShell untitled files +- [vscode-PowerShell #1557](https://github.com/PowerShell/vscode-powershell/pull/1557) - + Default to showing the last line in folded regions. Unset with `"powershell.codeFolding.showLastLine": false` + (thanks @glennsarti!) +- [vscode-PowerShell #1567](https://github.com/PowerShell/vscode-powershell/pull/1567) - + New snippet: Exchange Online connection (thanks @vmsilvamolina!) +- [vscode-PowerShell #1567](https://github.com/PowerShell/vscode-powershell/pull/1567) - + New snippet: HTML header (thanks @vmsilvamolina!) +- [vscode-PowerShell #1555](https://github.com/PowerShell/vscode-powershell/pull/1555) - + Log when language client not loaded during initialization (thanks @corbob!) +- [vscode-PowerShell #1554](https://github.com/PowerShell/vscode-powershell/pull/1554) - + Fix spacing in parameters when starting the extension (thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- [PowerShellEditorServices #786](https://github.com/PowerShell/PowerShellEditorServices/pull/786) - + Fix #17: Add go to definition support for dot sourced file paths (Thanks @dee-see!) +- [PowerShellEditorServices #767](https://github.com/PowerShell/PowerShellEditorServices/pull/767) - + Change unhandled messages to warnings instead of errors +- [PowerShellEditorServices #765](https://github.com/PowerShell/PowerShellEditorServices/pull/765) - + Fix PowerShell wildcard escaping in debug paths +- [PowerShellEditorServices #778](https://github.com/PowerShell/PowerShellEditorServices/pull/778) - + Fix multiple occurrences of the same typo (Thanks @dee-see!) +- [PowerShellEditorServices #782](https://github.com/PowerShell/PowerShellEditorServices/pull/782) - + Fix #779: NRE on Dispose in ExecutionTimer (Thanks @dee-see!) +- [PowerShellEditorServices #772](https://github.com/PowerShell/PowerShellEditorServices/pull/772) - + Log build info +- [PowerShellEditorServices #774](https://github.com/PowerShell/PowerShellEditorServices/pull/774) - + New-EditorFile works on non-powershell untitled files +- [PowerShellEditorServices #787](https://github.com/PowerShell/PowerShellEditorServices/pull/787) - + Fix descion/decision typo in visitors (Thanks @dee-see!) +- [PowerShellEditorServices #784](https://github.com/PowerShell/PowerShellEditorServices/pull/784) - + Replace bad StringReader usage with String.Split() +- [PowerShellEditorServices #768](https://github.com/PowerShell/PowerShellEditorServices/pull/768) - + Make pipeline runtime exceptions warnings in log +- [PowerShellEditorServices #790](https://github.com/PowerShell/PowerShellEditorServices/pull/790) - + Add managed thread id to log output to add debugging threading issues (Thanks @rkeithhill!) +- [PowerShellEditorServices #794](https://github.com/PowerShell/PowerShellEditorServices/pull/794) - + Fix Pester CodeLens run/debug by not quoting params/already quoted args (Thanks @rkeithhill!) +- [PowerShellEditorServices #785](https://github.com/PowerShell/PowerShellEditorServices/pull/785) - + Adds ability to use separate pipes for reading and writing (Thanks @ant-druha!) +- [PowerShellEditorServices #796](https://github.com/PowerShell/PowerShellEditorServices/pull/796) - + Code cleanup of the start script and ESHost.cs file (Thanks @rkeithhill!) +- [PowerShellEditorServices #795](https://github.com/PowerShell/PowerShellEditorServices/pull/795) - + Fix file recursion overflow problems +- [PowerShellEditorServices #697](https://github.com/PowerShell/PowerShellEditorServices/pull/697) - + Add functionality to allow a Show-Command like panel in VS Code (Thanks @corbob!) +- [PowerShellEditorServices #777](https://github.com/PowerShell/PowerShellEditorServices/pull/777) - + Add syntax folding (Thanks @glennsarti!) +- [PowerShellEditorServices #801](https://github.com/PowerShell/PowerShellEditorServices/pull/801) - + Fix local remoting +- [PowerShellEditorServices #797](https://github.com/PowerShell/PowerShellEditorServices/pull/797) - + Start of a PSES log file analyzer (Thanks @rkeithhill!) +- [PowerShellEditorServices #789](https://github.com/PowerShell/PowerShellEditorServices/pull/789) - + Add support for a "Show Documentation" quick fix menu entry (Thanks @rkeithhill!) +- [PowerShellEditorServices #760](https://github.com/PowerShell/PowerShellEditorServices/pull/760) - + Fix exception when remoting from Windows to non-Windows (Thanks @SeeminglyScience!) + +## v1.9.0 +### Thursday, September 27, 2018 +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1548](https://github.com/PowerShell/vscode-PowerShell/pull/1548) - + Explicitly return `undefined` from resolveDbgConfig when session not started (Thanks @rkeithhill!) +- [vscode-PowerShell #1516](https://github.com/PowerShell/vscode-PowerShell/pull/1516) - + Change "Get Online Help" menu item label to "Get Help" (Thanks @corbob!) +- [vscode-PowerShell #1525](https://github.com/PowerShell/vscode-PowerShell/pull/1525) - + Remove duplicate/overlapping folding regions (Thanks @glennsarti!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #750](https://github.com/PowerShell/PowerShellEditorServices/pull/750) - + Fix issue where # in path causes the path to resolve incorrectly +- [PowerShellEditorServices #721](https://github.com/PowerShell/PowerShellEditorServices/pull/721) - + Change Get-Help behavior to return local help when online help can't be displayed (Thanks @corbob!) +- [PowerShellEditorServices #748](https://github.com/PowerShell/PowerShellEditorServices/pull/748) - + Fix index out-of-range exception when deleting script files +- [PowerShellEditorServices #749](https://github.com/PowerShell/PowerShellEditorServices/pull/749) - + Fix crash for finding symbols on bad paths +- [PowerShellEditorServices #740](https://github.com/PowerShell/PowerShellEditorServices/pull/740) - + Fix inner help completion +- [PowerShellEditorServices #736](https://github.com/PowerShell/PowerShellEditorServices/pull/736) - + Cache the reflection call done for completions +- [PowerShellEditorServices #737](https://github.com/PowerShell/PowerShellEditorServices/pull/737) - + Remove LINQ usage in language service methods +- [PowerShellEditorServices #743](https://github.com/PowerShell/PowerShellEditorServices/pull/743) - + Remove unnecessary LINQ calls from LanguageServer + +## v1.8.4 +### Friday, August 31, 2018 +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1489](https://github.com/PowerShell/vscode-PowerShell/pull/1489) - + Use asynchronous logic for help completions +- [vscode-PowerShell #1477](https://github.com/PowerShell/vscode-PowerShell/pull/1477) - + Add BitsTransfer & user switch to install latest user profile insiders edition with Install-VSCode.ps1 script (Thanks @tabs-not-spaces!) +- [vscode-PowerShell #1485](https://github.com/PowerShell/vscode-PowerShell/pull/1485) - + Increase connection timeout + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #728](https://github.com/PowerShell/PowerShellEditorServices/pull/728) - + Fix formatter crash when script contains parse errors +- [PowerShellEditorServices #730](https://github.com/PowerShell/PowerShellEditorServices/pull/730) - + Fix crash where lines appended to end of script file causes out of bounds exception +- [PowerShellEditorServices #732](https://github.com/PowerShell/PowerShellEditorServices/pull/732) - + Fix CodeLens crash when a file cannot be opened, stop unnecessary file reads in CodeLens +- [PowerShellEditorServices #729](https://github.com/PowerShell/PowerShellEditorServices/pull/729) - + Fix a null dereference when an invalid cast exception has no inner exception +- [PowerShellEditorServices #719](https://github.com/PowerShell/PowerShellEditorServices/pull/719) - + Reduce allocations in the CodeLens providers +- [PowerShellEditorServices #725](https://github.com/PowerShell/PowerShellEditorServices/pull/725) - + Fix null dereference when debugging untitlted filesj +- [PowerShellEditorServices #726](https://github.com/PowerShell/PowerShellEditorServices/pull/726) - + Fix comment-based help snippet + +## v1.8.3 +### Wednesday, August 15, 2018 + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [PowerShell/vscode-powershell #1480](https://github.com/PowerShell/vscode-powershell/pull/1480) - + Use PowerShell signing script in VSTS builds +- [PowerShell/vscode-powershell #1460](https://github.com/PowerShell/vscode-powershell/pull/1460) - + Use newer version for preleases +- [PowerShell/vscode-powershell #1475](https://github.com/PowerShell/vscode-powershell/pull/1475) - + Change resourceLangId to editorLangId so right-click works properly with unsaved files (Thanks @corbob!) +- [PowerShell/vscode-powershell #1467](https://github.com/PowerShell/vscode-powershell/pull/1467) - + Remove region folding from non-region areas (Thanks @glennsarti!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShell/PowerShellEditorServices #722](https://github.com/PowerShell/PowerShellEditorServices/pull/722) - + Add VSTS signing step +- [PowerShell/PowerShellEditorServices #717](https://github.com/PowerShell/PowerShellEditorServices/pull/717) - + Increment version for prerelease +- [PowerShell/PowerShellEditorServices #715](https://github.com/PowerShell/PowerShellEditorServices/pull/715) - + Reduce allocations when parsing files (Thanks @mattpwhite!) + +## v1.8.2 +### Thursday, July 26, 2018 + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [PowerShell/vscode-powershell #1438](https://github.com/PowerShell/vscode-powershell/pull/1438) - + Fix detecting contiguous comment blocks and regions (Thanks @glennsarti!) +- [PowerShell/vscode-powershell #1436](https://github.com/PowerShell/vscode-powershell/pull/1436) - + First approach to fix issue with dbg/run start before PSES running (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShell/PowerShellEditorServices #712](https://github.com/PowerShell/PowerShellEditorServices/pull/712) - + workaround to support inmemory:// +- [PowerShell/PowerShellEditorServices #706](https://github.com/PowerShell/PowerShellEditorServices/pull/706) - + Go To Definition works with different Ast types +- [PowerShell/PowerShellEditorServices #707](https://github.com/PowerShell/PowerShellEditorServices/pull/707) - + fix stdio passing +- [PowerShell/PowerShellEditorServices #709](https://github.com/PowerShell/PowerShellEditorServices/pull/709) - + Stop Diagnostic logging from logging to stdio when the communication protocol is set to stdio +- [PowerShell/PowerShellEditorServices #710](https://github.com/PowerShell/PowerShellEditorServices/pull/710) - + stdio should only launch language service not debug +- [PowerShell/PowerShellEditorServices #705](https://github.com/PowerShell/PowerShellEditorServices/pull/705) - + Fix load order of PSSA modules +- [PowerShell/PowerShellEditorServices #704](https://github.com/PowerShell/PowerShellEditorServices/pull/704) - + Do not enable PSAvoidTrailingWhitespace rule by default as it currenly flags whitespace-only lines as well (Thanks @bergmeister!) + +## v1.8.1 +### Wednesday, July 11, 2018 + +- [PowerShell/vscode-powershell #1418](https://github.com/PowerShell/vscode-powershell/pull/1418) - + Fix code folding in documents using CRLF newlines. (Thanks @glennsarti!) + +## v1.8.0 +### Tuesday, July 10, 2018 + +- [PowerShell/vscode-powershell #1238](https://github.com/PowerShell/vscode-powershell/pull/1238) - + Added functionality to install the VSCode context menus. (Thanks @detlefs!) +- [PowerShell/vscode-powershell #1354](https://github.com/PowerShell/vscode-powershell/pull/1354) - + Edit snippet to fix issue #1353 (Thanks @kilasuit!) +- [PowerShell/vscode-powershell #1362](https://github.com/PowerShell/vscode-powershell/pull/1362) - + Updated Pester Problem Matcher (Thanks @awickham10!) +- [PowerShell/vscode-powershell #1359](https://github.com/PowerShell/vscode-powershell/pull/1359) - + (maint) Add visual ruler for line length (Thanks @glennsarti!) +- [PowerShell/vscode-powershell #1344](https://github.com/PowerShell/vscode-powershell/pull/1344) - + Update to TypeScript 2.9.x (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1323](https://github.com/PowerShell/vscode-powershell/pull/1323) - + SpecProcId - interactive var replacement supports only string type (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1327](https://github.com/PowerShell/vscode-powershell/pull/1327) - + Switch to named pipes +- [PowerShell/vscode-powershell #1321](https://github.com/PowerShell/vscode-powershell/pull/1321) - + GitHub issue template tweaks and add PSSA template (Thanks @bergmeister!) +- [PowerShell/vscode-powershell #1320](https://github.com/PowerShell/vscode-powershell/pull/1320) - + Take advantage of multiple issue templates (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1317](https://github.com/PowerShell/vscode-powershell/pull/1317) - + Change SpecifyScriptArgs command to only return string - not string[] (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1318](https://github.com/PowerShell/vscode-powershell/pull/1318) - + Update package veresion in lock file, format package.json file. (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1312](https://github.com/PowerShell/vscode-powershell/pull/1312) - + Updates to Examples PSSA settings file to include more rule config (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1305](https://github.com/PowerShell/vscode-powershell/pull/1305) - + Make SaveAs work for untitled files +- [PowerShell/vscode-powershell #1307](https://github.com/PowerShell/vscode-powershell/pull/1307) - + Added Columns, Improved readability for ToC. (Thanks @st0le!) +- [PowerShell/vscode-powershell #1368](https://github.com/PowerShell/vscode-powershell/pull/1368) - + Add new snippet for #region (#1368) (Thanks @lipkau!) +- [PowerShell/vscode-powershell #1416](https://github.com/PowerShell/vscode-powershell/pull/1416) - + (GH-1413) Resolve promise correctly in Folding feature (Thanks @glennsarti!) +- [PowerShell/vscode-powershell #1412](https://github.com/PowerShell/vscode-powershell/pull/1412) - + Set the extension's log level based on settings value (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1411](https://github.com/PowerShell/vscode-powershell/pull/1411) - + Escape paths w/single quotes before passing to powershell in single-quoted strings (#1411) (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1409](https://github.com/PowerShell/vscode-powershell/pull/1409) - + Rename file to match type name (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1408](https://github.com/PowerShell/vscode-powershell/pull/1408) - + Restore ability to start debug session when script run in PSIC hits breakpoint (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1407](https://github.com/PowerShell/vscode-powershell/pull/1407) - + Scroll the terminal to bottom for F8 executionPartial fix #1257 (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1414](https://github.com/PowerShell/vscode-powershell/pull/1414) - + Update grammar parsing for vscode-textmate v4 module (Thanks @glennsarti!) +- [PowerShell/vscode-powershell #1397](https://github.com/PowerShell/vscode-powershell/pull/1397) - + Allow debugging in interactive session with no dir change (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1402](https://github.com/PowerShell/vscode-powershell/pull/1402) - + Move lint directive after the file-header to fix lint error (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1366](https://github.com/PowerShell/vscode-powershell/pull/1366) - + Add support for side-by-side PS Core preview on Linux/macOS (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1391](https://github.com/PowerShell/vscode-powershell/pull/1391) - + Add PowerShell Online Help lookup to context menu (Thanks @corbob!) +- [PowerShell/vscode-powershell #1396](https://github.com/PowerShell/vscode-powershell/pull/1396) - + Add tslint rule file-header to enforce copyright in TS files (Thanks @rkeithhill!) +- [PowerShell/vscode-powershell #1355](https://github.com/PowerShell/vscode-powershell/pull/1355) - + Add syntax aware folding provider (Thanks @glennsarti!) +- [PowerShell/vscode-powershell #1395](https://github.com/PowerShell/vscode-powershell/pull/1395) - + Update community_snippets.md (Thanks @fullenw1!) +- [PowerShell/vscode-powershell #1382](https://github.com/PowerShell/vscode-powershell/pull/1382) - + Fix markdown syntax (Thanks @lipkau!) +- [PowerShell/vscode-powershell #1369](https://github.com/PowerShell/vscode-powershell/pull/1369) - + Update README.md with kbds and what to do if you find a vulnerability +- [PowerShell/vscode-powershell #1297](https://github.com/PowerShell/vscode-powershell/pull/1297) - + Added some snippets (#1297) (Thanks @SQLDBAWithABeard!) + +## 1.7.0 +### Wednesday, April 25, 2018 + +- [PowerShell/vscode-powershell #1285](https://github.com/PowerShell/vscode-powershell/pull/1285) - + Add a community snippet for date-annotated `Write-Verbose` messages. + +- [PowerShell/vscode-powershell #1228](https://github.com/PowerShell/vscode-powershell/issues/1228) - + Make comment-based help trigger always be `##` with a new setting `powershell.helpCompletion` to + allow you to select between help comment styles: `BlockComment` (default) or `LineComment`. + You can also specify Disabled to disable this functionality. + +- [PowerShell/vscode-powershell #603](https://github.com/PowerShell/vscode-powershell/issues/603) - + Fix PowerShell crashing on machines with IPv6 disabled. + +- [PowerShell/vscode-powershell #1243](https://github.com/PowerShell/vscode-powershell/issues/1243) - + Support custom PowerShell executable paths in user configuration which can be selected (via name) + in either user or workspace configuration. + +- [PowerShell/vscode-powershell #1264](https://github.com/PowerShell/vscode-powershell/pull/1264) - + Add support for [Visual Studio Live Share](https://code.visualstudio.com/visual-studio-live-share). + +- [PowerShell/vscode-powershell #1261](https://github.com/PowerShell/vscode-powershell/pull/1261) - + Add support for `$psEditor.GetEditorContext.CurrentFile.SaveAs("NewFileName.ps1")`. + +- [PowerShell/vscode-powershell #1252](https://github.com/PowerShell/vscode-powershell/pull/1252) - + Change the way the extension builds and runs, so that PowerShellEditorServices is self-contained. + +- [PowerShell/vscode-powershell #1248](https://github.com/PowerShell/vscode-powershell/pull/1248) - + Replace `$global:IsOSX` with `$global:IsMacOS`. + +- [PowerShell/vscode-powershell #1246](https://github.com/PowerShell/vscode-powershell/pull/1246) - + Create [community_snippets.md](./docs/community_snippets.md) for user created snippets. + +- [PowerShell/vscode-powershell #1155](https://github.com/PowerShell/vscode-powershell/issues/1155) - + Fix PSES crashes caused by running "Set PSScriptAnalyzer Rules" on an untitled file. + +- [PowerShell/vscode-powershell #1236](https://github.com/PowerShell/vscode-powershell/pull/1236) - + Stop an error occurring when VSCode trims trailing whitespace and sends document update messages. + +- [PowerShell/vscode-powershell #996](https://github.com/PowerShell/vscode-powershell/issues/996) - + Fix `Install-PSCode.ps1` crashing due to `$IsLinux` variable in older PowerShell versions. + +- [PowerShell/vscode-powershell #1234](https://github.com/PowerShell/vscode-powershell/pull/1234) - + Add snippets for Hashtable and PSCustomObject. + +- [PowerShell/vscode-powershell #1233](https://github.com/PowerShell/vscode-powershell/pull/1233) - + Add a keybinding for Show Addtional Commands to Shift-Alt-S. + +- [PowerShell/vscode-powershell #1227](https://github.com/PowerShell/vscode-powershell/pull/1227) - + Add an indicator for when PowerShell is running in the status bar. + +- [PowerShell/vscode-powershell #1225](https://github.com/PowerShell/vscode-powershell/pull/1225) - + Fix launch config not using temporary integrated console setting. + +- [PowerShell/vscode-powershell #1208](https://github.com/PowerShell/vscode-powershell/issues/1208) - + Stop configured temporary windows closing after running Pester tests. + +## 1.6.0 +### Thursday, February 22, 2018 + +#### Fixes and Improvements + +- [PowerShell/vscode-powershell #907](https://github.com/PowerShell/vscode-powershell/issues/907) - + Persist temp console debug session. + +- [PowerShell/vscode-powershell #1198](https://github.com/PowerShell/vscode-powershell/pull/1198) - + Enhance Start-EditorServices.ps1 for better logging and fix bugs. + +- [PowerShell/PowerShellEditorServices #413](https://github.com/PowerShell/PowerShellEditorServices/issues/413) - + Allow opening files as not previews to allow Open-EditorFile to open multiple files passed in. + +- [PowerShell/vscode-powershell #1177](https://github.com/PowerShell/vscode-powershell/issues/1177) - + Add function-advanced snippet. Thanks to [Benny1007](https://github.com/Benny1007)! + +- [PowerShell/vscode-powershell #1179](https://github.com/PowerShell/vscode-powershell/issues/1179) - + Switch onDebug to onDebugResolve:type for better debugging perf. + +- [PowerShell/vscode-powershell #1086](https://github.com/PowerShell/vscode-powershell/issues/1086) - + Add tslint to vscode-powershell and address all issues. + +- [PowerShell/vscode-powershell #1153](https://github.com/PowerShell/vscode-powershell/issues/1153) - + Add docs for ps remoting in vscode. + +- [PowerShell/vscode-powershell #1161](https://github.com/PowerShell/vscode-powershell/pull/1161) - + Check for the expected version of the PowerShell Editor Services module fails because of the wrong function parameters. Thanks to [ant-druha](https://github.com/ant-druha)! + +- [PowerShell/vscode-powershell #1141](https://github.com/PowerShell/vscode-powershell/pull/1141) - + Updated install script minified URL. Thanks to [tabs-not-spaces](https://github.com/tabs-not-spaces)! + +- [PowerShell/PowerShellEditorServices #258](https://github.com/PowerShell/PowerShellEditorServices/issues/258) - + add .Save() to FileContext API. + +- [PowerShell/vscode-powershell #1137](https://github.com/PowerShell/vscode-powershell/pull/1137) - + Added 64bit support & vscode-insiders install support. Thanks to [tabs-not-spaces](https://github.com/tabs-not-spaces)! + +- [PowerShell/vscode-powershell #1115](https://github.com/PowerShell/vscode-powershell/issues/1115) - + Fixed "Open in ISE" keyboard shortcut from overwriting basic editing keyboard shortcut. + +- [PowerShell/vscode-powershell #1111](https://github.com/PowerShell/vscode-powershell/issues/1111) - + Update examples tasks.json for 2.0.0 schema. + +## 1.5.1 +### Tuesday, November 14, 2017 + +- [PowerShell/vscode-powershell #1100](https://github.com/PowerShell/vscode-powershell/issues/1100) - + Fixed CodeLens on Pester test invocation fails with "Error: command 'vscode.startDebug' not found". + +- [PowerShell/vscode-powershell #1091](https://github.com/PowerShell/vscode-powershell/issues/1091) - + Fixed crash when editing remote file using psedit. + +- [PowerShell/vscode-powershell #1084](https://github.com/PowerShell/vscode-powershell/issues/1084) - + Fixed authenticode signature 'HashMismatch' on Start-EditorServices.ps1. + +- [PowerShell/vscode-powershell #1078](https://github.com/PowerShell/vscode-powershell/issues/1078) - + Fixed debug adapter process terminating when setting breakpoint in an Untitled file or in a Git diff window. + +- Update download.sh to remove macOS OpenSSL check since PowerShell Core Beta and higher no longer depend on OpenSSL. Thanks to [elovelan](https://github.com/elovelan)! + +- Get-Help -ShowWindow will no longer error in the PowerShell Integrated Console. The help window will appear but at the moment, it will appear behind VSCode. + +- Fix language server crash when processing a deep directory structure that exceeds max path. + +## 1.5.0 +### Friday, October 27, 2017 + +#### Fixes and Improvements + +- [PowerShell/vscode-powershell #820](https://github.com/PowerShell/vscode-powershell/issues/820) - + Added new "Upload Bug Report to GitHub" command to make it easy to post an issue to the vscode-powershell GitHub repo. Thanks to [Mark Schill](https://github.com/PowerSchill)! + +- [PowerShell/vscode-powershell #910](https://github.com/PowerShell/vscode-powershell/issues/910) - + Set-VSCodeHtmlContentView cmdlet now exposes `JavaScriptPaths` and `StyleSheetPaths` parameters to allow using JavaScript code and CSS stylesheets in VS Code HTML preview views. + +- [PowerShell/vscode-powershell #909](https://github.com/PowerShell/vscode-powershell/issues/909) - + Write-VSCodeHtmlContentView's AppendBodyContent now accepts input from the pipeline + +- [PowerShell/vscode-powershell #1071](https://github.com/PowerShell/vscode-powershell/pull/1071) - + Updated session menu to find PowerShell Core installs with the new pwsh.exe path + +- [PowerShell/vscode-powershell #842](https://github.com/PowerShell/vscode-powershell/issues/842) - + psedit can now open empty files in remote sessions + +- [PowerShell/vscode-powershell #1040](https://github.com/PowerShell/vscode-powershell/issues/1040) - + Non-PowerShell files opened in remote sessions using psedit can now be saved back to the remote server + +- [PowerShell/vscode-powershell #660](https://github.com/PowerShell/vscode-powershell/issues/660) - + Set/Enable/Disable/Remove-PSBreakpoint commands now cause the VS Code breakpoint UI to be updated while the debugger is active + +- [PowerShell/vscode-powershell #625](https://github.com/PowerShell/vscode-powershell/issues/625) - + Breakpoints are now cleared from the session when the debugger starts so that stale breakpoints from previous sessions are not hit + +- [PowerShell/vscode-powershell #1004](https://github.com/PowerShell/vscode-powershell/issues/1004) - + Handle exception case when finding references of a symbol + +- [PowerShell/vscode-powershell #942](https://github.com/PowerShell/vscode-powershell/issues/942) - + Temporary debugging session now does not stop responding when running "PowerShell Interactive Session" debugging configuration + +- [PowerShell/vscode-powershell #917](https://github.com/PowerShell/vscode-powershell/issues/917) - + Added PowerShell.InvokeRegisteredEditorCommand command to be used from HTML preview views for invoking editor commands registered in PowerShell. Thanks to [Kamil Kosek](https://github.com/kamilkosek)! + +- [PowerShell/vscode-powershell #872](https://github.com/PowerShell/vscode-powershell/issues/872) - + Watch variables with children are now expandable + +- [PowerShell/vscode-powershell #1060](https://github.com/PowerShell/vscode-powershell/issues/1060) - + $psEditor.Workspace.NewFile() now works again in VSC 1.18.0 Insiders builds + +- [PowerShell/vscode-powershell #1046](https://github.com/PowerShell/vscode-powershell/issues/1046) - + Debugging now works again in VSC 1.18.0 Insiders builds + +- [PowerShell/PowerShellEditorServices #342](https://github.com/PowerShell/PowerShellEditorServices/issues/342) - + Unexpected file URI schemes are now handled more reliably + +- [PowerShell/PowerShellEditorServices #396](https://github.com/PowerShell/PowerShellEditorServices/issues/396) - + Resolved errors being written to Integrated Console when running native applications while transcription is turned on + +- [PowerShell/PowerShellEditorServices #529](https://github.com/PowerShell/PowerShellEditorServices/issues/529) - + Fixed an issue with loading the PowerShellEditorServices module in PowerShell Core 6.0.0-beta3 + +- [PowerShell/PowerShellEditorServices #533](https://github.com/PowerShell/PowerShellEditorServices/pull/533) - + Added new $psEditor.GetCommand() method for getting all registered editor commands. Thanks to [Kamil Kosek](https://github.com/kamilkosek)! + +- [PowerShell/PowerShellEditorServices #535](https://github.com/PowerShell/PowerShellEditorServices/pull/535) - + Type information is now exposed on hover for variables in the Variables view + +## 1.4.3 +### Wednesday, September 13, 2017 + +- [#1016](https://github.com/PowerShell/vscode-powershell/issues/1016) - + Fixed a conflict with the "Azure Resource Manager for Visual Studio + Code" extension which prevented the PowerShell extension from loading + successfully. + +## 1.4.2 +### Tuesday, September 5, 2017 + +- [#993](https://github.com/PowerShell/vscode-powershell/issues/993) - + `powershell.powerShellExePath` using Sysnative path should be automatically + corrected when using 64-bit Visual Studio Code +- [#1008](https://github.com/PowerShell/vscode-powershell/issues/1008) - + Windows PowerShell versions (x64 and x86) are not enumerated correctly + when using 64-bit Visual Studio Code +- [#1009](https://github.com/PowerShell/vscode-powershell/issues/1009) - + PowerShell version indicator in status bar is missing tooltip +- [#1020](https://github.com/PowerShell/vscode-powershell/issues/1020) - + "Show Session Menu", "Show Integrated Console", and "Restart Current Session" + commands should cause PowerShell extension to be activated + +## 1.4.1 +### Thursday, June 22, 2017 + +- [PowerShell/PowerShellEditorServices#529](https://github.com/PowerShell/PowerShellEditorServices/issues/529) - + Fixed an issue with loading the extension with in PowerShell Core 6.0.0-beta3 + +## 1.4.0 +### Wednesday, June 21, 2017 + +#### New HTML content view commands enabling custom UI tabs + +You can now show editor tabs with custom HTML-based UI by using the +new HTML content view commands! This is the first step toward UI +extensions for VS Code written in PowerShell. + +Here's an example: + +```powershell +$view = New-VSCodeHtmlContentView -Title "My Custom View" -ShowInColumn One +Set-VSCodeHtmlContentView -View $view -Content "

Hello world!

" +Write-VSCodeHtmlContentView $view -Content "I'm adding new content!
" +``` + +And here's the result: + +![HTML view demo](https://user-images.githubusercontent.com/79405/27394133-f96c38cc-565f-11e7-8102-a3727014ea5a.GIF) + +Check out the cmdlet help for the following commands to learn more: + +- `New-VSCodeHtmlContentView` +- `Show-VSCodeHtmlContentView` +- `Close-VSCodeHtmlContentView` +- `Set-VSCodeHtmlContentView` +- `Write-VSCodeHtmlContentView` + +Since this is a first release, we've restricted the use of JavaScript +inside of the HTML. We will add this capability in a future release! + +#### Code formatting setting presets for common styles + +We've now added code formatting presets for the most common code style +conventions used in the PowerShell community: + +- **[OTBS](https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS_.28OTBS.29)** - + Known as the "One True Brace Style". Causes `else`, `catch`, and other + keywords to be "cuddled", keeping them on the same line as the previous + closing brace: + + ```powershell + if ($var -eq $true) { + # Do the thing + } else { + # Do something else + } + ``` + +- **[Stroustrup](https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup)** - + Causes beginning curly braces to be placed on the same line as the statement: + + ```powershell + if ($var -eq $true) { + # Do the thing + } + else { + # Do something else + } + ``` + +- **[Allman](https://en.wikipedia.org/wiki/Indent_style#Allman_style)** - All curly braces are preceded by a newline: + + ```powershell + if ($var -eq $true) + { + # Do the thing + } + else + { + # Do something else + } + ``` + +- **Custom** - Allows full customization of the code formatting settings. + +In addition, code formatting now respects your `editor.insertSpaces` and +`editor.tabSize` settings! + +#### Debugging in a temporary PowerShell Integrated Console + +We've added the ability to debug your PowerShell code in a temporary +PowerShell Integrated Console so that you have a fresh runspace and +PowerShell process each time you hit F5! + +This setting is necessary if you are developing with PowerShell 5 +classes or modules using .NET assemblies because .NET types cannot +be reloaded inside of the same PowerShell process. This new setting +saves you from reloading your PowerShell session each time you debug +your code! + +You can configure this behavior in two ways: + +- Use the `launch.json` configuration parameter `createTemporaryIntegratedConsole`: + + ```json + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch Current File in Temporary Console", + "script": "${file}", + "args": [], + "cwd": "${file}", + "createTemporaryIntegratedConsole": true + }, + ``` + +- Configure the setting `powershell.debugging.createTemporaryIntegratedConsole`: + + ```json + "powershell.debugging.createTemporaryIntegratedConsole": true, + ``` + +The default value for these settings is `false`, meaning that the temporary +console behavior is **opt-in**. + +Configuring the user or workspace setting will cause all debugging sessions +to be run in a temporary Integrated Console so it's useful if you would prefer +this to be the default behavior. The `launch.json` setting overrides the user +setting so you can always customize the behavior for a specific launch +configuration. + +#### NewFile() API and Out-CurrentFile command + +You can now create a new untitled file from within the Integrated Console +by using the `$psEditor.Workspace.NewFile()` command! Also, you can send +the formatted output of any PowerShell command to the current file by using +the `Out-CurrentFile` command: + +```powershell +Get-Process | Out-CurrentFile +``` + +Special thanks to [Doug Finke](https://github.com/dfinke) for the contribution! + +#### Other fixes and improvements + +- [#881](https://github.com/PowerShell/vscode-powershell/pull/881) - + When you select a different PowerShell version in the session menu, your choice + is persisted to the `powershell.powerShellExePath` setting. + +- [#891](https://github.com/PowerShell/vscode-powershell/issues/891) - + Pester CodeLenses now run tests without string interpolation of test names + +## 1.3.2 +### Monday, June 12, 2017 + +- [PowerShell/vscode-powershell#864](https://github.com/PowerShell/vscode-powershell/issues/864) - Improved the visibility of hyphen characters on the currently edited line in the PowerShell ISE theme (thanks [Stefan Stranger](https://github.com/stefanstranger)!) + +- [PowerShell/vscode-powershell#857](https://github.com/PowerShell/vscode-powershell/issues/855) - Typing a new function into a file no longer causes the language server to crash + +- [PowerShell/vscode-powershell#855](https://github.com/PowerShell/vscode-powershell/issues/855) - "Format Document" no longer hangs indefinitely + +- [PowerShell/vscode-powershell#859](https://github.com/PowerShell/vscode-powershell/issues/859) - Language server no longer hangs when opening a Pester test file containing dot-sourced script references + +- [PowerShell/vscode-powershell#856](https://github.com/PowerShell/vscode-powershell/issues/856) - CodeLenses for function definitions no longer count the definition itself as a reference and shows "0 references" when there are no uses of that function + +- [PowerShell/vscode-powershell#838](https://github.com/PowerShell/vscode-powershell/issues/838) - Right-clicking a debugger variable and selecting "Add to Watch" now has the desired result + +- [PowerShell/vscode-powershell#837](https://github.com/PowerShell/vscode-powershell/issues/837) - Debugger call stack now navigates correctly to the user's selected stack frame + +- [PowerShell/vscode-powershell#862](https://github.com/PowerShell/vscode-powershell/issues/862) - Terminating errors in the language server now close the Integrated Console immediately and prompt the user to restart the session + +- [PowerShell/PowerShellEditorServices#505](https://github.com/PowerShell/PowerShellEditorServices/issues/505) - Added improved cmdlet help in the PowerShellEditorServices.Commands module + +- [PowerShell/PowerShellEditorServices#509](https://github.com/PowerShell/PowerShellEditorServices/issues/509) - Importing the PowerShellEditorServices.Commands module no longer causes errors to be written about missing help languages + +## 1.3.1 +### Friday, June 9, 2017 + +#### Fixes and improvements + +- [#850](https://github.com/PowerShell/vscode-powershell/issues/850) - + Fixed an issue where lower-cased "describe" blocks were not identified by + the CodeLens feature. + +- [#851](https://github.com/PowerShell/vscode-powershell/issues/851) - + Fixed an issue where the language server would stop responding when typing out a describe + block. + +- [#852](https://github.com/PowerShell/vscode-powershell/issues/852) - + Fixed an issue where Pester test names would not be detected correctly when + other arguments like -Tags were being used on a Describe block. + +## 1.3.0 +### Friday, June 9, 2017 + +#### CodeLens for running and debugging Pester tests + +We've added two new CodeLens actions that show up above Describe blocks in +your Pester tests, "Run tests" and "Debug tests". By clicking one of these +CodeLenses, your tests will be executed in the Integrated Console with +the debugger attached. You can now set breakpoints and quickly debug a portion +of your test script: + +![Pester CodeLens](https://user-images.githubusercontent.com/79405/26988706-3c054ed0-4d05-11e7-87f0-5bbf16ee73ef.GIF) + +#### CodeLens support for finding references of a function or cmdlet + +We've also added CodeLenses for showing the number of references for a function or +cmdlet that is defined in a script. If you click this CodeLens, the references +pane will appear so that you can navigate through all of the references: + +![References CodeLens](https://user-images.githubusercontent.com/79405/26989245-384a4866-4d07-11e7-9c1e-076dbd7d6eb4.GIF) + +We will add CodeLens support for PowerShell 5+ classes and class methods in a future +update! + +#### Document symbol support for Pester tests + +We've also added document symbol support for Pester tests so that you can easily +navigate among the Describe, Context, and It blocks in large Pester script files: + +![Pester symbols](https://user-images.githubusercontent.com/79405/26989077-91e7a306-4d06-11e7-8e26-916bb78720f8.GIF) + +#### New PowerShell ISE theme + +We now include a new color theme that tries to provide a faithful interpretation +of the PowerShell ISE's style, including a blue console background! To use this +theme open the Command Palette (Ctrl+Shift+P), run the "Preferences: Color Theme" +command, then select "PowerShell ISE". + +![ISE theme](https://user-images.githubusercontent.com/79405/26988805-9769aea6-4d05-11e7-81fc-da79bf1ec3cb.png) + +This is a first attempt at making this happen so [give us feedback](https://git.io/v9jnL) +if you think that the colors can be improved! Super huge thanks to +[Matt McNabb](https://twitter.com/mcnabbmh) for putting this together! + +#### New cmdlets inside the Integrated Console + +Thanks to new PowerShell Editor Services co-maintainer [Patrick Meinecke](https://github.com/SeeminglyScience), +we've gained a new set of useful commands for interacting with the $psEditor APIs +within the Integrated Console: + +- [Find-Ast](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Find-Ast.md) +- [Get-Token](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Get-Token.md) +- [ConvertFrom-ScriptExtent](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/ConvertFrom-ScriptExtent.md) +- [ConvertTo-ScriptExtent](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/ConvertTo-ScriptExtent.md) +- [Set-ScriptExtent](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Set-ScriptExtent.md) +- [Join-ScriptExtent](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Join-ScriptExtent.md) +- [Test-ScriptExtent](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Test-ScriptExtent.md) +- [Import-EditorCommand](https://github.com/PowerShell/PowerShellEditorServices/blob/main/module/docs/Import-EditorCommand.md) + +This should also resolve the issues some people were seeing when we tried +to load the unsigned temporary script containing `Register-EditorCommand` +on machines with an AllSigned execution policy ([#784]([https://github.com/PowerShell/vscode-powershell/issues/784])). + +#### Fixes and improvements + +- [#827](https://github.com/PowerShell/vscode-powershell/issues/827) - + Fixed an issue where an Output panel will appear with an error when you close + the PowerShell Integrated Terminal + +## 1.2.1 +### Thursday, June 1, 2017 + +#### Fixes and improvements + +- [PowerShell/PowerShellEditorServices#478](https://github.com/PowerShell/PowerShellEditorServices/issues/478) - + Dynamic comment help snippets now generate parameter fields correctly + when `<#` is typed above a `param()` block. + +- [#808](https://github.com/PowerShell/vscode-powershell/issues/808) - + An extra `PS>` is no longer being written to the Integrated Console for + some users who have custom prompt functions. + +- [#813](https://github.com/PowerShell/vscode-powershell/issues/813) - + Finding references of symbols across the workspace now properly handles + inaccessible folders and file paths + +- [#810](https://github.com/PowerShell/vscode-powershell/issues/810) - + `$psEditor.GetEditorContext()` now doesn't throw exceptions when in an + untitled file + +- [#807](https://github.com/PowerShell/vscode-powershell/issues/807) - + The users's previously selected PowerShell session type is now retained + when running the "PowerShell: Restart Current Session" command. + +- [#821](https://github.com/PowerShell/vscode-powershell/issues/821) - + Note properties on PSObjects are now visible in the debugger's Variables + view + +## 1.2.0 +### Wednesday, May 31, 2017 + +#### Dynamic comment-based help snippets now work inside functions ([#763](https://github.com/PowerShell/vscode-powershell/issues/748)) + +You asked for it, you got it! Dynamic comment-based help snippets now work +inside function definitions, both above the `param()` block and at the end +of the function body: + +![Comment help GIF](https://cloud.githubusercontent.com/assets/79405/26637844/6e76cfa6-45d5-11e7-89b8-a2d6a559536b.GIF) + +*NOTE: There is an issue where parameter sections don't get generated inside of a function +with a `[CmdletBinding()]` attribute. This is being tracked at [PowerShell/PSScriptAnalyzer#768](https://github.com/PowerShell/PSScriptAnalyzer/issues/768).* + +#### Session menu now contains entries for PowerShell Core installations on Windows ([#794](https://github.com/PowerShell/vscode-powershell/issues/794)) + +It's now much easier to switch between Windows PowerShell and PowerShell Core installs +on Windows. When you run the "PowerShell: Show Session Menu" command or click the +PowerShell version indication in the status bar you'll now see PowerShell Core entries +in the menu: + +![Session menu](https://cloud.githubusercontent.com/assets/79405/26637984/d177f5f8-45d5-11e7-9def-705b3fa68953.png) + +#### Improved PSScriptAnalyzer marker display and suppression snippets ([#781](https://github.com/PowerShell/vscode-powershell/issues/781)) and ([#783](https://github.com/PowerShell/vscode-powershell/issues/783)) + +The green squiggle markers you receive from PSScriptAnalyzer now include the +name of the corresponding rule in their description: + +![Rule name](https://cloud.githubusercontent.com/assets/79405/26638073/15aaaaae-45d6-11e7-93a0-cf6d5397553e.png) + +This is really helpful with the new rule suppression snippets contributed by +[Jos Verlinde](https://github.com/Josverl)! You can access them by typing +`suppress-` and selecting one of the suppression snippet options: + +![Suppress rule](https://cloud.githubusercontent.com/assets/79405/26638390/d8c42164-45d6-11e7-8844-a34a314654a5.GIF) + +#### New built-in Pester problem matcher ([#798](https://github.com/PowerShell/vscode-powershell/issues/798)) + +We now include a built-in [problem matcher](https://code.visualstudio.com/Docs/editor/tasks#_defining-a-problem-matcher) +for Pester test output so that you don't need to define one in your `tasks.json` +file any longer! You can reference the built-in problem matcher in your test +tasks by using the name `$pester`: + +```json + { + "taskName": "Test", + "suppressTaskName": true, + "isTestCommand": true, + "showOutput": "always", + "args": [ "Invoke-Pester -PesterOption @{IncludeVSCodeMarker=$true}" ], + "problemMatcher": "$pester" + } +``` + +*NOTE: There is an issue with problem matchers when using the new `2.0.0` +version of VS Code's task runner. Pester errors may show up multiple +times in the Problems panel. This issue is being tracked at +[#797](https://github.com/PowerShell/vscode-powershell/issues/797).* + +#### Other fixes and improvements + +- [#710](https://github.com/PowerShell/vscode-powershell/issues/710) - + Variable definitions can now be found across the workspace + +- [#771](https://github.com/PowerShell/vscode-powershell/issues/771) - + Improved dynamic comment help snippet performance in scripts with many functions + +- [#786](https://github.com/PowerShell/vscode-powershell/issues/786) - + Running the "Show Integrated Console" command will now start the extension + if it isn't already started + +- [#774](https://github.com/PowerShell/vscode-powershell/issues/774) - + Pressing Enter now causes custom prompt functions to be fully evaluated + +- [#770](https://github.com/PowerShell/vscode-powershell/issues/770) - + Fixed issue where custom prompt function might be written twice when + starting the integrated console + +- [#767](https://github.com/PowerShell/vscode-powershell/issues/767) - + Fixed placeholder navigation for many built-in snippets + +- [#782](https://github.com/PowerShell/vscode-powershell/issues/782) - + Fixed extension host crash when restarting the PowerShell session + +- [#737](https://github.com/PowerShell/vscode-powershell/issues/737) - + Fixed hangs and high CPU when restarting or switching between PowerShell sessions + +- [#777](https://github.com/PowerShell/vscode-powershell/issues/777) - + Changed "Starting PowerShell" message to clearly indicate that we're in the + PowerShell Integrated Console + +## 1.1.0 +### Thursday, May 18, 2017 + +#### New dynamic snippet for adding comment-based help ([#748](https://github.com/PowerShell/vscode-powershell/issues/748)) + +We've added a really cool new feature that enables you to create comment-based +help blocks with ease! When you've defined a function in a PowerShell script +file, you can now start typing a comment block above the function definition +and it will be completed for you: + +![Help Comment GIF](https://cloud.githubusercontent.com/assets/79405/26216440/f31a47c8-3bb8-11e7-9fbc-7e3fb596c0ea.GIF) + +This comment block works like a snippet, allowing you to tab through the fields +to quickly add documentation for the parts you care about. + +This is a first pass for this feature and we plan to do more with it in the future. +Please feel free to [file feature requests](https://git.io/v9jnL) for anything else +you'd like to see! + +#### Breakpoints hit in the Integrated Console now activate the debugger UI ([#619](https://github.com/PowerShell/vscode-powershell/issues/619)) + +In previous releases it was necessary to start the "PowerShell Interactive Session" +debugging configuration before you could run a command or script from the Integrated +Console and hit breakpoints in the editor UI. We've just removed this limitation! + +Now when you set a breakpoint using `Set-PSBreakpoint` and run a script or command in the +Integrated Console, the debugger UI now gets activated: + +![Debugger Activate GIF](https://cloud.githubusercontent.com/assets/79405/26217019/d17708f2-3bba-11e7-982f-4d481c2cf533.GIF) + +Note that breakpoints set in the Integrated Console [still do not show up](https://github.com/PowerShell/vscode-powershell/issues/660) +in the editor UI; this requires [changes to VS Code](https://github.com/Microsoft/vscode/issues/8642) +that we'll be contributing for their next feature release. + +#### Improved output when loading profile scripts ([#663](https://github.com/PowerShell/vscode-powershell/issues/663) and [#689](https://github.com/PowerShell/vscode-powershell/issues/689)) + +We now write the errors and Write-Output calls that occur while loading profile +scripts so that it's easier to diagnose issues with your profile scripts. This +fix will help us identify the things missing from the Integrated Console which +cause your profile scripts to fail (like the current lack of a [PrivateData object for setting console colors](https://github.com/PowerShell/vscode-powershell/issues/571)). + +Please feel free to [file issues](https://git.io/v9jnL) for anything that causes +your profile scripts to throw errors when they get loaded! + +#### Other fixes and improvements + +- [#751](https://github.com/PowerShell/vscode-powershell/issues/751) - + Removed keybinding for the "Find PowerShell Modules from the Gallery" command + because it conflicts with VS Code's default "Format Selection" keybinding. + +- [#739](https://github.com/PowerShell/vscode-powershell/issues/739) - + Fixed wording of PowerShell extension commands to have consistent capitalization. + Thanks to [@AndySchneiderDev](https://github.com/AndySchneiderDev) for the + contribution! + +## 1.0.0 +### Wednesday, May 10, 2017 + +We are excited to announce that we've reached version 1.0! For more information, +please see the [official announcement](https://blogs.msdn.microsoft.com/powershell/2017/05/10/announcing-powershell-for-visual-studio-code-1-0/) +on the PowerShell Team Blog. + +#### New script argument UI when debugging ([#705](https://github.com/PowerShell/vscode-powershell/issues/705)) + +You can now set PowerShell debugger configurations to prompt for arguments to be +passed to your script when it is executed. This is configured using the new +`${command:SpecifyScriptArgs}` configuration variable in `launch.json`: + +```json + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch DebugTest.ps1 w/Args Prompt", + "script": "${workspaceRoot}/DebugTest.ps1", + "args": [ "${command:SpecifyScriptArgs}" ], + "cwd": "${file}" + } +``` + +When you launch this configuration you will see a UI popup asking for arguments: + +![image](https://cloud.githubusercontent.com/assets/5177512/25560503/e60e9822-2d12-11e7-9837-29464d077082.png) + +You can type your arguments to the script as you would in PowerShell: + +```powershell +-Count 5 +``` + +In future executions of this configuration, you will be presented with the arguments +you typed the last time you ran it so that you can easily edit them and test variations! + +#### New hash table alignment formatting rule ([#672](https://github.com/PowerShell/vscode-powershell/issues/672)) + +We've added a new code formatting rule that automatically aligns the equal sign +in assignments of keys in hash tables or DSC configurations. It also works with +nested hash tables! Here's a simple example: + +##### Before + +```powershell +$formatTest = @{ + Apple = 4 + Tangerine = @{ + Orange = 2 + CornflowerBlue = 6 + } + Banana = 3 +} +``` + +##### After + +```powershell + +$formatTest = @{ + Apple = 4 + Tangerine = @{ + Orange = 2 + CornflowerBlue = 6 + } + Banana = 3 +} +``` + +This formatting rule is enabled by default but can be disabled with the following +setting: + +```json +"powershell.codeFormatting.alignPropertyValuePairs": false +``` + +#### Added basic module-wide function references support + +In the past, finding the references or definition of a function in `FileA.ps1` only +worked if `FileA.ps1` had an explicit dot-source invocation of `FileB.ps1`. We have +removed this limitation so that you can now find definitions and references of any +function across all the script files in your project folder! This is especially +useful if you write PowerShell modules where all of the source files are dot-sourced +inside of the .psm1 file. + +This new implementation is very basic and may give unexpected results, so please [file +an issue on GitHub](https://github.com/PowerShell/vscode-powershell/issues) if you get +a result you did not expect! + +#### Other integrated console and debugger improvements + +- Fixed [#698](https://github.com/PowerShell/vscode-powershell/issues/698) - + When debugging scripts in the integrated console, the cursor position should now + be stable after stepping through your code! Please let us know if you see any + other cases where this issue appears. + +- Fixed [#626](https://github.com/PowerShell/vscode-powershell/issues/626) - + Fixed an issue where debugging a script in one VS Code window would cause that script's + output to be written to a different VS Code window in the same process. + +- Fixed [#618](https://github.com/PowerShell/vscode-powershell/issues/618) - + Pressing enter on an empty command line in the Integrated Console no longer adds the + empty line to the command history. + +- Fixed [#617](https://github.com/PowerShell/vscode-powershell/issues/617) - + Stopping the debugger during a prompt for a mandatory script parameter no + longer crashes the language server. + +- Fixed [PowerShellEditorServices #428](https://github.com/PowerShell/PowerShellEditorServices/issues/428) - + Debugger no longer hangs when you stop debugging while an input or choice prompt is + active in the integrated console. + +## 0.12.2 +### Friday, April 7, 2017 + +- Fixed [#662](https://github.com/PowerShell/vscode-powershell/issues/662) - + Changed usage of `$env:PSMODULEPATH` to `$env:PSModulePath` to conform to + a recent change in PowerShell 6 ([PowerShell/PowerShell#3255](https://github.com/PowerShell/PowerShell/pull/3255)) + which makes the casing of `PSModulePath` consistent between Windows and + the *NIX platforms. + + **NOTE: This is a breaking change for PowerShell extension users on Linux and macOS** + + If you are using PowerShell 6.0.0-alpha.17 or lower you **will** need to upgrade + to 6.0.0-alpha.18. + +- Fixed [#645](https://github.com/PowerShell/vscode-powershell/issues/645) - + "Go to Definition" or "Find References" now work in untitled scripts without + crashing the session +- Fixed [#632](https://github.com/PowerShell/vscode-powershell/issues/632) - + Debugger no longer hangs when launched while PowerShell session is still + initializing +- Fixed [#655](https://github.com/PowerShell/vscode-powershell/issues/655) - + Fixed an issue with current working directory being set incorrectly when + debugging untitled script files +- Fixed [PowerShellEditorServices #430](https://github.com/PowerShell/PowerShellEditorServices/issues/430) - + Resolved occasional IntelliSense slowness by preventing the implicit loading + of the PowerShellGet and PackageManagement modules. This change will be reverted + once a bug in PackageManagement is fixed. +- Fixed [PowerShellEditorServices #427](https://github.com/PowerShell/PowerShellEditorServices/issues/427) - + Fixed an occasional crash when requesting editor IntelliSense while running + a script in the debugger +- Fixed [PowerShellEditorServices #416](https://github.com/PowerShell/PowerShellEditorServices/issues/416) - + Cleaned up errors that would appear in the `$Errors` variable from the use + of `Get-Command` and `Get-Help` in IntelliSense results + +## 0.12.1 +### Tuesday, April 4, 2017 + +- Fixed [#648](https://github.com/PowerShell/vscode-powershell/issues/648) - + Resolved an error when launching an untitled script file in a workspace + with no launch.json or in a window without a workspace path + +## 0.12.0 +### Tuesday, April 4, 2017 + +#### Debugging untitled files ([#555](https://github.com/PowerShell/vscode-powershell/issues/555)) + +You can now debug untitled files that are set to the PowerShell language mode. When you +create a new untitled file, use the "Change Language Mode" command (Ctrl+K M) +and choose "PowerShell" from the menu that appears. You can now press F5 to start +debugging the script file without saving it. + +In the upcoming 1.11.0 release of Visual Studio Code (or in the current VS Code Insiders +release), you can configure the new `files.defaultLanguage` setting to `powershell` in either +your User or Workspace settings to cause all untitled files to be created with the PowerShell +mode by default. This will allow you to create new PowerShell scripts and debug them +immediately without saving first! + +#### New right-click context menu for Run Selection ([#581](https://github.com/PowerShell/vscode-powershell/issues/581)) + +By user request, we've also added a new "Run Selection" item in the right-click context menu +for PowerShell script files: + +![image](https://cloud.githubusercontent.com/assets/79405/24670885/a18513fe-1924-11e7-91d3-dc14c6cbfad9.png) + +#### Debugging improvements + +- Fixed [#620](https://github.com/PowerShell/vscode-powershell/issues/620) - + PowerShell session now does not crash when a breakpoint is hit outside of + debug mode + +- Fixed [#614](https://github.com/PowerShell/vscode-powershell/issues/614) - + Auto variables are now populating correctly in the debugger. **NOTE**: There is + a known issue where all of a script's variables begin to show up in the + Auto list after running a script for the first time. This is caused by + a change in 0.11.0 where we now dot-source all debugged scripts. We will + provide an option for this behavior in the future. + +- Fixed [#641](https://github.com/PowerShell/vscode-powershell/issues/641) - + PowerShell script files with capitalized extensions (.PS1, .PSM1) can now + be launched in the debugger + +- Fixed [#616](https://github.com/PowerShell/vscode-powershell/issues/616) - + Debugger now shows column position indicators when debugging pipelines or + nested expressions: + + ![image](https://cloud.githubusercontent.com/assets/79405/24316990/2157480e-10b0-11e7-8a61-19fde63edfb7.png) + +#### Integrated console improvements + +- Fixed [PowerShell/PowerShellEditorServices#411](https://github.com/PowerShell/PowerShellEditorServices/issues/411) - + Commands run outside of the integrated console prompt now interrupt the prompt + correctly. This resolves a class of issues that appear when running commands + in the extension like "New Project from Plaster Template" or any `$psEditor` + commands added with the "Register-EditorCommand" function. Running any of + these commands will now cause the current input prompt to be cancelled so that + the command's output will be written correctly. + +#### Code formatting improvements + +- Fixed [#595](https://github.com/PowerShell/vscode-powershell/issues/595) - + High CPU usage when using formatOnType has now been resolve + +- Fixed [#559](https://github.com/PowerShell/vscode-powershell/issues/559) - + The `newLineAfterCloseBrace` behavior has been improved to respect common syntax + usages + +- Fixed[PowerShell/PowerShellEditorServices#380](https://github.com/PowerShell/PowerShellEditorServices/issues/380) - + The `whitespaceBeforeOpenBrace` behavior now leaves "magic" functions with the + correct formatting. For example: `(0 .. 10).foreach{$_}` now does not have a + whitespace inserted before the `{`. + +#### New Project with Plaster improvements + +- Fixed [#643](https://github.com/PowerShell/vscode-powershell/issues/643) - + Running Plaster using the New Project command now interrupts the command prompt + correctly + +- Fixed [#504](https://github.com/PowerShell/vscode-powershell/issues/504) - + Confirming default values in Plaster input prompts by pressing Enter now works + correctly + +#### Other fixes and improvements + +- Added [#639](https://github.com/PowerShell/vscode-powershell/pull/639) and + [#640](https://github.com/PowerShell/vscode-powershell/pull/640) - + Our configuration setting descriptions have been edited for superior clarity + thanks to [June Blender](https://github.com/juneb)! + +- Fixed [#611](https://github.com/PowerShell/vscode-powershell/pull/640) - + Example-* snippets are now displaying correctly in IntelliSense results + +- Added [#624](https://github.com/PowerShell/vscode-powershell/pull/624) - + When you update the PowerShell extension after this release, you will now see + version update indicators which offer to display the changelog in a preview + tab + +## 0.11.0 +### Wednesday, March 22, 2017 + +#### Remotely edited files can now be saved + +- Added [#583](https://github.com/PowerShell/vscode-powershell/issues/583) - + When you open files in a remote PowerShell session with the `psedit` command, + their updated contents are now saved back to the remote machine when you save + them in the editor. + +#### Integrated console improvements + +- Fixed [#533](https://github.com/PowerShell/vscode-powershell/issues/533) - + The backspace key now works in the integrated console on Linux and macOS. This + fix also resolves a few usability problems with the integrated console on all + supported OSes. + +- Fixed [542](https://github.com/PowerShell/vscode-powershell/issues/542) - + Get-Credential now hides keystrokes correctly on Linux and macOS. + +We also added some new settings ([#580](https://github.com/PowerShell/vscode-powershell/issues/580), +[#588](https://github.com/PowerShell/vscode-powershell/issues/588)) to allow fine-tuning +of the integrated console experience: + +- `powershell.startAutomatically` (default: `true`) - If true, causes PowerShell extension + features to start automatically when a PowerShell file is opened. If false, the user must + initiate startup using the 'PowerShell: Restart Current Session' command. IntelliSense, + code navigation, integrated console, code formatting, and other features will not be + enabled until the extension has been started. Most users will want to leave this + setting to `true`, though it was added to save CPU cycles if you often use new VS Code + instances to quickly view PowerShell files. + +- `powershell.integratedConsole.showOnStartup` (default: `true`) - If true, causes the + integrated console to be shown automatically when the PowerShell extension is initialized. + +- `powershell.integratedConsole.focusConsoleOnExecute` (default: `true`) - If `true`, + causes the integrated console to be focused when a script selection is run or a + script file is debugged. + +#### Interactive debugging improvements + +- Added [#540](https://github.com/PowerShell/vscode-powershell/issues/540) - + The scripts that you debug are now dot-sourced into the integrated console's + session, allowing you to experiment with the results of your last execution. + +- Added [#600](https://github.com/PowerShell/vscode-powershell/issues/600) - + Debugger commands like `stepInto`, `continue`, and `quit` are now available + in the integrated console while debugging a script. + +- Fixed [#596](https://github.com/PowerShell/vscode-powershell/issues/596) - + VS Code's Debug Console now warns the user when it is used while debugging + a script. All command evaluation now happens through the integrated console + so this message should help alleviate confusion. + +#### Other fixes and improvements + +- Fixed [#579](https://github.com/PowerShell/vscode-powershell/issues/579) - + Sorting of IntelliSense results is now consistent with the PowerShell ISE +- Fixed [#591](https://github.com/PowerShell/vscode-powershell/issues/591) - + "Editor commands" registered with the `Register-EditorCommand` function are + now sorted alphabetically by their `Name` field, causing commands to be grouped + based on their source module. +- Fixed [#575](https://github.com/PowerShell/vscode-powershell/issues/575) - + The interactive console no longer starts up with errors in the `$Error` variable. +- Fixed [#599](https://github.com/PowerShell/vscode-powershell/issues/599) - + The [SSASCMDLETS module](https://msdn.microsoft.com/en-us/library/hh213141.aspx?f=255&MSPPError=-2147217396) + from SQL Server Analytics Service should now load correctly in the integrated + console. + +## 0.10.1 +### Thursday, March 16, 2017 + +#### Fixes and improvements + +- Fixed [#566](https://github.com/PowerShell/vscode-powershell/issues/566) - + Enable editor IntelliSense while stopped at a breakpoint +- Fixed [#556](https://github.com/PowerShell/vscode-powershell/issues/556) - + Running and debugging scripts in the integrated console should not steal focus from the editor +- Fixed [#543](https://github.com/PowerShell/vscode-powershell/issues/543) - + Keyboard input using AltGr Ctrl+Alt modifiers does not work +- Fixed [#421](https://github.com/PowerShell/vscode-powershell/issues/421) - + Session startup should give a helpful error message if ConstrainedLanguage mode is turned on +- Fixed [#401](https://github.com/PowerShell/vscode-powershell/issues/401) - + Session startup should indicate if current PowerShell version is unsupported (PSv1 and v2) +- Fixed [#454](https://github.com/PowerShell/vscode-powershell/issues/454) - + ExecutionPolicy set via group policy or registry key should not cause language server to crash +- Fixed [#532](https://github.com/PowerShell/vscode-powershell/issues/532) - + DEVPATH environment variable not being set for interactive console session +- Fixed [PowerShellEditorServices #387](https://github.com/PowerShell/PowerShellEditorServices/issues/387) - + Write-(Warning, Verbose, Debug) are missing message prefixes and foreground colors +- Fixed [PowerShellEditorServices #382](https://github.com/PowerShell/PowerShellEditorServices/issues/382) - + PSHostUserInterface implementation should set SupportsVirtualTerminal to true + +## 0.10.0 +### Tuesday, March 14, 2017 + +#### New interactive console experience + +We are excited to provide you with the first release of our new interactive +console experience! When you open up a PowerShell script file, you will +be greeted with a new VS Code integrated terminal window called +"PowerShell Integrated Console" + +![integrated console screenshot](https://cloud.githubusercontent.com/assets/79405/23910661/b599f2ee-0897-11e7-9426-00af794c10b5.png) + +In this console you will have an experience that falls somewhere between +the PowerShell ISE and the PowerShell console host: + +- Tab completion of commands and their parameters +- Basic command history, accessed using the up/down arrow keys +- The `psedit` command opens existing files in an editor pane +- Pressing F8 in an editor pane runs the current line or selection in the console +- Native applications like `git` are fully supported +- Script debugging shares the same console session with the editor for + a true ISE-like debugging experience + +It even works with your fancy prompt function if configured in your +VS Code profile (`$HOME\Documents\WindowsPowerShell\Microsoft.VSCode_profile.ps1`): + +![custom prompt screenshot](https://cloud.githubusercontent.com/assets/79405/23910654/b1bca66c-0897-11e7-81b1-70eff5b97c21.png) + +The integrated console is supported on PowerShell v3 through v6 and works +on Linux and macOS with PowerShell Core. By default you don't have to +configure which PowerShell to run, we will pick an appropriate default +based on your platform. If you'd like to choose a different install +of PowerShell you can always change the `powershell.developer.powerShellExePath` +setting. + +Keep in mind that this is the first release for this feature and there are +bound to be issues and missing functionality. Please feel free to file +GitHub issues for any bugs or feature requests! + +##### Known Issues and Limitations + +- [#535](https://github.com/PowerShell/vscode-powershell/issues/535) PSReadline + is currently **not** supported in the integrated console. We will enable this + in a future release. +- [#534](https://github.com/PowerShell/vscode-powershell/issues/534) Integrated console + prompt is not restarted when you stop the debugging of a local runspace in another + process. This will be addressed soon in a patch update. +- [#533](https://github.com/PowerShell/vscode-powershell/issues/533) Backspace key + does not work in the integrated console on Linux and macOS. The workaround for now + is to use Ctrl+H instead of the Backspace key. This will be addressed + soon in a patch update. +- [#536](https://github.com/PowerShell/vscode-powershell/issues/536) Integrated console + sometimes does not have a scrollbar at startup. The workaround is to resize the width + of the VS Code window slightly and the scrollbar will appear. This will be addressed + soon in a patch update. + +#### Get-Credential and PSCredential support + +Now that we have the integrated console, we have added support for the `Get-Credential` +cmdlet, `Read-Host -AsSecureString`, and any input prompt of type `SecureString` or `PSCredential`. +When you run any of these cmdlets you will be prompted inside the integrated console: + +![credential screenshot](https://cloud.githubusercontent.com/assets/79405/23910668/bac9019c-0897-11e7-80e2-eaf1b9e507f8.png) + +#### Code formatting improvements + +We now support VS Code's `editor.formatOnType` setting so that your code gets formatted +as you type! Formatting will be triggered when you press Enter or the closing curly +brace character `}`. + +Based on your feedback, we've also added new code formatting options, all of which +are turned on by default: + +- `powershell.codeFormatting.newLineAfterCloseBrace` - Causes a newline to be inserted + after a closing brace in multi-line expressions like if/else +- `powershell.codeFormatting.whitespaceBeforeOpenBrace` - Causes whitespace to be + inserted before an open brace like `Foreach-Object {` +- `powershell.codeFormatting.whitespaceBeforeOpenParen` - Causes whitespace to be + inserted before an open parentheses like `if (` +- `powershell.codeFormatting.whitespaceAroundOperator` - Causes whitespace to be + inserted around operators like `=` or `+` +- `powershell.codeFormatting.whitespaceAfterSeparator` - Causes whitespace to be + inserted around separator characters like `;` and `,` +- `powershell.codeFormatting.ignoreOneLineBlock` - Single-line expressions, like + small if/else statements, will not be expanded to multiple lines. + +We've also made many improvements to the performance and stability of the formatter. + +#### Debugging improvements + +We've added a new configuration for debugging your Pester tests. By default it +merely runs `Invoke-Pester` at the workspace path, but you can also edit the +configuation to add additional arguments to be passed through. + +We've also added support for column breakpoints. Now you can set a breakpoint +directly within a pipeline by placing your cursor at any column on a line and +running the `Debug: Column Breakpoint` command: + +![column breakpoint screenshot](https://cloud.githubusercontent.com/assets/79405/23910649/aaef70e4-0897-11e7-93b7-0d729969a1e2.png) + +For the latest PowerShell Core release ([6.0.0-alpha.17](https://github.com/PowerShell/PowerShell/releases/tag/v6.0.0-alpha.17)), +we have also added the ability to step into ScriptBlocks that are executed on another +machine using `Invoke-Command -Computer`. + +Set a breakpoint on an `Invoke-Command` line and then once it's hit: + +![Invoke-Command screenshot](https://cloud.githubusercontent.com/assets/79405/23911032/c01b8ff6-0898-11e7-89e3-02a31d419fc5.png) + +Press `F11` and you will step into the ScriptBlock. You can now continue to use +"step in" and trace the ScriptBlock's execution on the remote machine: + +![remote script listing screenshot](https://cloud.githubusercontent.com/assets/79405/23918844/ca86cf28-08b1-11e7-8014-c689cdcccf87.png) + +Note that you cannot currently set breakpoints in the script listing file as +this code is being executed without an actual script file on the remote machine. + +#### Other fixes and improvements + +- Fixed [#427](https://github.com/PowerShell/vscode-powershell/issues/427) - + The keybinding for "Expand Alias" command has been changed to Shift+Alt+E +- Fixed [#519](https://github.com/PowerShell/vscode-powershell/issues/519) - + Debugger hangs after continuing when watch expressions are set +- Fixed [#448](https://github.com/PowerShell/vscode-powershell/issues/448) - + Code formatter should keep indentation for multi-line pipelines +- Fixed [#518](https://github.com/PowerShell/vscode-powershell/issues/518) - + Code formatter fails when dollar-paren `$()` expressions are used +- Fixed [#447](https://github.com/PowerShell/vscode-powershell/issues/447) - + Code formatter crashes when run on untitled documents + +## 0.9.0 +### Thursday, January 19, 2017 + +#### New PowerShell code formatter + +We've added a formatter for PowerShell code which allows you to format an +entire file or a selection within a file. You can access this formatter by +running VS Code's `Format Document` and `Format Selection` commands inside +of a PowerShell file. + +You can configure code formatting with the following settings: + +- `powershell.codeFormatting.openBraceOnSameLine` - Places open brace on the + same line as its associated statement. Default is `true`. +- `powershell.codeFormatting.newLineAfterOpenBrace` - Ensures that a new line + occurs after an open brace (unless in a pipeline statement on the same line). + Default is `true` +- `editor.tabSize` - Specifies the indentation width for code blocks. This + is a VS Code setting but it is respected by the code formatter. +- `editor.formatOnSave` - If true, automatically formats when they are saved. + This is a VS Code setting and may also affect non-PowerShell files. + +Please note that this is only a first pass at PowerShell code formatting, it +may not format your code perfectly in all cases. If you run into any issues, +please [file an issue](https://github.com/PowerShell/vscode-powershell/issues/new) +and give us your feedback! + +#### Streamlined debugging experience - launch.json is now optional + +**NOTE: This improvement depends on VS Code 1.9.0 which is due for release +early February!** However, you can try it out right now with the [VS Code Insiders](https://code.visualstudio.com/insiders) +release. + +Thanks to a new improvement in VS Code's debugging APIs, we are now able to +launch the PowerShell debugger on a script file without the need for a `launch.json` +file. You can even debug individual PowerShell scripts without opening a +workspace folder! Don't worry, you can still use a `launch.json` file to configure +specific debugging scenarios. + +We've also made debugger startup much more reliable. You will no longer see the +dreaded "Debug adapter terminated unexpectedly" message when you try to launch +the debugger while the language server is still starting up. + +#### Support for debugging remote and attached runspaces + +We now support remote PowerShell sessions via the [`Enter-PSSession`](https://msdn.microsoft.com/en-us/powershell/reference/5.0/microsoft.powershell.core/enter-pssession) +cmdlet. This cmdlet allows you to create a PowerShell session on another machine +so that you can run commands or debug scripts there. The full debugging +experience works with these remote sessions on PowerShell 4 and above, allowing +you to set breakpoints and see remote files be opened locally when those breakpoints +are hit. + +For PowerShell 5 and above, we also support attaching to local and remote PowerShell +host processes using the [`Enter-PSHostProcess`](https://msdn.microsoft.com/en-us/powershell/reference/5.0/microsoft.powershell.core/enter-pshostprocess) +and [`Debug-Runspace`](https://msdn.microsoft.com/en-us/powershell/reference/5.0/microsoft.powershell.utility/debug-runspace) +cmdlets. This allows you to jump into another process and then debug a script that +is already running in one of the runspaces in that process. The debugger will break +execution of the running script and then the associated script file will be opened +in the editor so that you can set breakpoints and step through its execution. + +We've also added a new `launch.json` configuration for debugging PowerShell host processes: + +![Process launch configuration screenshot](https://cloud.githubusercontent.com/assets/79405/22089468/391e8120-dda0-11e6-950c-64f81b364c35.png) + +When launched, the default "attach" configuration will prompt you with a list of +PowerShell host processes on the local machine so that you can easily select one +to be debugged: + +![Process selection UI screenshot](https://cloud.githubusercontent.com/assets/79405/22081037/c205e516-dd76-11e6-834a-66f4c38e181d.png) + +You can also edit the launch configuration to hardcode the launch parameters, even +setting a remote machine to connect to before attaching to the remote process: + +```json + { + "type": "PowerShell", + "request": "attach", + "name": "PowerShell Attach to Host Process", + "computerName": "my-remote-machine", + "processId": "12345", + "runspaceId": 1 + } +``` + +Please note that we currently do not yet support initiating remote sessions from Linux +or macOS. This will be supported in an upcoming release. + +#### Initial support for remote file opening using `psedit` + +Another nice improvement is that we now support the `psedit` command in remote and +attached sessions. This command allows you to open a file in a local or remote session +so that you can set breakpoints in it using the UI before launching it. For now these +remotely-opened files will not be saved back to the remote session when you edit and +save them. We plan to add this capability in the next feature update. + +#### New "interactive session" debugging mode + +You can now create a new launch configuration which drops you directly into the +debug console so that you can debug your scripts and modules however you wish. +You can call Set-PSBreakpoint to set any type of breakpoint and then invoke your +code through the console to see those breakpoints get hit. This mode can also be +useful for debugging remote sessions. + +![Interactive session config screenshot](https://cloud.githubusercontent.com/assets/79405/22089502/5e56b4c6-dda0-11e6-8a51-f24e29ce7988.png) + +Please note that this is NOT a replacement for a true interactive console experience. +We've added this debugging configuration to enable a few other debugging scenarios, like +debugging PowerShell modules, while we work on a true interactive console experience using +VS Code's Terminal interface. + +#### New document symbol support for PSD1 files + +We've extended our document symbol support to `.psd1` files to make it really easy to +navigate through them. When you have a `.psd1` file open, run the `Go to Symbol in File...` +command (Ctrl + Shift + O) and you'll see this popup: + +![psd1 symbol screenshot](https://cloud.githubusercontent.com/assets/79405/22094872/85c7d9a2-ddc5-11e6-9bee-5fc8c3dae097.png) + +You can type a symbol name or navigate using your arrow keys. Once you select one of the +symbol names, the editor pane will jump directly to that line. + +#### Other fixes and improvements + +- Added a new `Open Examples Folder` command to easily open the extension's + example script folder. +- Added a new setting `powershell.developer.powerShellExeIsWindowsDevBuild` + which, when true, indicates that the `powerShellExePath` points to a Windows + PowerShell development build. +- Fixed [#395](https://github.com/PowerShell/vscode-powershell/issues/395): + Quick Fix for PSAvoidUsingAliases rule replaces the entire command +- Fixed [#396](https://github.com/PowerShell/vscode-powershell/issues/396): + Extension commands loaded in PowerShell profile are not being registered +- Fixed [#391](https://github.com/PowerShell/vscode-powershell/issues/391): + DSC IntelliSense can cause the language server to crash +- Fixed [#400](https://github.com/PowerShell/vscode-powershell/issues/400): + Language server can crash when selecting PSScriptAnalyzer rules +- Fixed [#408](https://github.com/PowerShell/vscode-powershell/issues/408): + Quick fix requests meant for other extensions crash the language server +- Fixed [#401](https://github.com/PowerShell/vscode-powershell/issues/401): + Extension startup should indicate if the current PowerShell version is unsupported +- Fixed [#314](https://github.com/PowerShell/vscode-powershell/issues/314): + Errors/Warnings still show up in Problems window when file is closed +- Fixed [#388](https://github.com/PowerShell/vscode-powershell/issues/388): + Syntax errors are not reported when powershell.scriptAnalysis.enable is set to false + +## 0.8.0 +### Friday, December 16, 2016 + +#### Improved PowerShell session management + +It's now much easier to manage the active PowerShell session. We've added a +new item to the status bar to indicate the state of the session and the version +of PowerShell you're using: + +![Screenshot of status indicator](https://cloud.githubusercontent.com/assets/79405/21247551/fcf2777c-c2e4-11e6-9659-7349c35adbcd.png) + +When this status item is clicked, a new menu appears to give you some session +management options: + +![Screenshot of session menu](https://cloud.githubusercontent.com/assets/79405/21247555/009fa64c-c2e5-11e6-8171-76914d3366a0.png) + +You can restart the active session, switch between 32-bit and 64-bit PowerShell on +Windows or switch to another PowerShell process (like a 6.0 alpha build) that +you've configured with the `powershell.developer.powerShellExePath`. + +We've also improved the overall experience of loading and using the extension: + +- It will prompt to restart the PowerShell session if it crashes for any reason +- It will also prompt to restart the session if you change any relevant PowerShell + configuration setting like the aforementioned `powershell.developer.powerShellExePath`. +- You can easily access the logs of the current session by running the command + `Open PowerShell Extension Logs Folder`. + +#### Create new modules with Plaster + +In this release we've added integration with the [Plaster](https://github.com/PowerShell/Plaster) +module to provide a `Create New Project from Plaster Template` command. This command will +walk you through the experience of selecting a template and filling in all of +the project details: + +![Screenshot of Plaster template selection](https://cloud.githubusercontent.com/assets/79405/21247560/087b47a4-c2e5-11e6-86e7-ba3727b5e36d.png) + +![Screenshot of Plaster input](https://cloud.githubusercontent.com/assets/79405/21247562/0a79b130-c2e5-11e6-97e9-cfd672803f75.png) + +We include one basic project template by default and will add more in the very +near future. However, you won't need to update the PowerShell extension to get these +new templates, they will appear when you install an update to the Plaster module from +the [PowerShell Gallery](https://www.powershellgallery.com/). + +Check out [Plaster's documentation](https://github.com/PowerShell/Plaster/tree/master/docs/en-US) +for more details on how it can be used and how you can create your own templates. + +#### New "quick fix" actions for PSScriptAnalyzer rules + +The PowerShell extension now uses any "suggested corrections" which are returned with +a rule violation in your script file to provide a "quick fix" option for the affected +section of code. For example, when the `PSAvoidUsingCmdletAliases` rule finds the use +of a non-allowlisted alias, you will see a light bulb icon that gives the option to +change to the full name (right click or Ctrl+. on the marker): + +![Screenshot of PSScriptAnalyzer quick fix](https://cloud.githubusercontent.com/assets/79405/21247558/05887e86-c2e5-11e6-9c67-e4558a7e2dba.png) + +If you'd like to see more quick fixes for PowerShell code, head over to the +[PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) GitHub page and +get involved! + +#### Easily enable and disable PSScriptAnalyzer rules + +Another improvement related to PSScriptAnalyzer is the ability to change the active +PSScriptAnalyzer rules in the current editing session using a helpful selection menu: + +![Screenshot of PSScriptAnalyzer rule selection](https://cloud.githubusercontent.com/assets/79405/21247557/037888b6-c2e5-11e6-816f-6732e13cddb7.png) + +You can enable and disable active rules by running the `Select PSScriptAnalyzer Rules` +command. For now this only changes the active session but in a future release we will +modify your PSScriptAnalyzer settings file so that the changes are persisted to future +editing sessions. + +#### New "hit count" breakpoints in the debugger + +When debugging PowerShell scripts you can now set "hit count" breakpoints which +cause the debugger to stop only after the breakpoint has been encountered a specified +number of times. + +![Screenshot of a hit count breakpoint](https://cloud.githubusercontent.com/assets/79405/21247563/0c159202-c2e5-11e6-8c91-36791c4fa804.png) + +#### Other fixes and improvements + +- We now provide snippets for the `launch.json` configuration file which make it easier + to add new PowerShell debugging configurations for your project. +- In PowerShell `launch.json` configurations, the `program` parameter has now been + renamed to `script`. Configurations still using `program` will continue to work. +- Fixed #353: Cannot start PowerShell debugger on Windows when offline +- Fixed #217: PowerShell output window should be shown when F8 is pressed +- Fixed #292: Check for Homebrew's OpenSSL libraries correctly on macOS +- Fixed #384: PowerShell snippets broken in VS Code 1.8.0 + +## 0.7.2 +### Friday, September 2, 2016 + +- Fixed #243: Debug adapter process has terminated unexpectedly +- Fixed #264: Add check for OpenSSL on OS X before starting the language service +- Fixed #271: PSScriptAnalyzer settings path isn't being passed along +- Fixed #273: Debugger crashes after multiple runs +- Fixed #274: Extension crashes on Ctrl+Hover + +## 0.7.1 +### Tuesday, August 23, 2016 + +- "Auto" variable scope in debugger UI now expands by default +- Fixed #244: Extension fails to load if username contains spaces +- Fixed #246: Restore default PSScriptAnalyzer ruleset +- Fixed #248: Extension fails to load on Windows 7 with PowerShell v3 + +## 0.7.0 +### Thursday, August 18, 2016 + +#### Introducing support for Linux and macOS + +This release marks the beginning of our support for Linux and macOS via +the new [cross-platform release of PowerShell](https://github.com/PowerShell/PowerShell). +You can find installation and usage instructions at the [PowerShell GitHub repository](https://github.com/PowerShell/PowerShell). + +## 0.6.2 +### Friday, August 12, 2016 + +- Fixed #231: In VS Code 1.4.0, IntelliSense has stopped working +- Fixed #193: Typing "n" breaks intellisense +- Fixed #187: Language server sometimes crashes then $ErrorActionPreference = "Stop" + +## 0.6.1 +### Monday, May 16, 2016 + +- Fixed #180: Profile loading should be enabled by default +- Fixed #183: Language server sometimes fails to initialize preventing IntelliSense, etc from working +- Fixed #182: Using 'Run Selection' on a line without a selection only runs to the cursor position +- Fixed #184: When running a script in the debugger, $host.Version reports wrong extension version + +## 0.6.0 +### Thursday, May 12, 2016 + +#### Added a new cross-editor extensibility model + +- We've added a new extensibility model which allows you to write PowerShell + code to add new functionality to Visual Studio Code and other editors with + a single API. If you've used `$psISE` in the PowerShell ISE, you'll feel + right at home with `$psEditor`. Check out the [documentation](https://powershell.github.io/PowerShellEditorServices/guide/extensions.html) + for more details! + +#### Support for user and system-wide profiles + +- We've now introduced the `$profile` variable which contains the expected + properties that you normally see in `powershell.exe` and `powershell_ise.exe`: + - `AllUsersAllHosts` + - `AllUsersCurrentHost` + - `CurrentUserAllHosts` + - `CurrentUserCurrentHost` +- In Visual Studio Code the profile name is `Microsoft.VSCode_profile.ps1`. +- `$host.Name` now returns "Visual Studio Code Host" and `$host.Version` returns + the version of the PowerShell extension that is being used. + +#### Other improvements + +- IntelliSense for static methods and properties now works correctly. If you + type `::` after a type such as `[System.Guid]` you will now get the correct + completion results. This also works if you press `Ctrl+Space` after the `::` + characters. +- `$env` variables now have IntelliSense complete correctly. +- Added support for new VSCode command `Debug: Start Without Debugging`. Shortcut + for this command is Ctrl+F5. +- Changed the keyboard shortcut for `PowerShell: Expand Alias` from Ctrl+F5 to Ctrl+Alt+e. +- Added support for specifying a PSScriptAnalyzer settings file by + providing a full path in your User Settings for the key `powershell.scriptAnalysis.settingsPath`. + You can also configure the same setting in your project's `.vscode\settings.json` + file to contain a workspace-relative path. If present, this workspace-level setting + overrides the one in your User Settings file. See the extension's `examples\.vscode\settings.json` + file for an example. +- The debug adapter now does not crash when you attempt to add breakpoints + for files that have been moved or don't exist. +- Fixed an issue preventing output from being written in the debugger if you + don't set a breakpoint before running a script. + +#### New configuration settings + +- `powershell.scriptAnalysis.settingsPath`: Specifies the path to a PowerShell Script Analyzer settings file. Use either an absolute path (to override the default settings for all projects) or use a path relative to your workspace. + +## 0.5.0 +### Thursday, March 10, 2016 + +#### Support for PowerShell v3 and v4 + +- Support for PowerShell v3 and v4 is now complete! Note that for this release, + Script Analyzer support has been disabled for PS v3 and v4 until we implement + a better strategy for integrating it as a module dependency + +#### Debugging improvements + +- Added support for command breakpoints. + + Hover over the Debug workspace's 'Breakpoints' list header and click the 'Add' + button then type a command name (like `Write-Output`) in the new text box that + appears in the list. + +- Added support for conditional breakpoints. + + Right click in the breakpoint margin to the left of the code editor and click + 'Add conditional breakpoint' then enter a PowerShell expression in the text box + that appears in the editor. + +#### Other improvements + +- Added a preview of a possible project template for PowerShell Gallery modules in + the `examples` folder. Includes a PSake build script with Pester test, clean, + build, and publish tasks. See the `examples\README.md` file for instructions. + Check it out and give your feedback on GitHub! +- `using 'module'` now resolves relative paths correctly, removing a syntax error that + previously appeared when relative paths were used +- Calling `Read-Host -AsSecureString` or `Get-Credential` from the console now shows an + appropriate "not supported" error message instead of crashing the language service. + Support for these commands will be added in a later release. + +#### New configuration settings + +- `powershell.useX86Host`: If true, causes the 32-bit language service to be used on 64-bit Windows. On 32-bit Windows this setting has no effect. + +## 0.4.1 +### Wednesday, February 17, 2016 + +- Updated PSScriptAnalyzer 1.4.0 for improved rule marker extents +- Added example Pester task for running tests in the examples folder +- Fixed #94: Scripts fail to launch in the debugger if the working directory path contains spaces + +## 0.4.0 +### Tuesday, February 9, 2016 + +#### Debugging improvements + +[@rkeithhill](https://github.com/rkeithhill) spent a lot of time polishing the script debugging experience for this release: + +- You can now pass arguments to scripts in the debugger with the `args` parameter in launch.json +- You can also run your script with the 32-bit debugger by changing the `type` parameter in launch.json to "PowerShell x86" (also thanks to [@adamdriscoll](https://github.com/adamdriscoll)!) +- The new default PowerShell debugger configuration now launches the active file in the editor +- You can also set the working directory where the script is run by setting the `cwd` parameter in launch.json to an absolute path. If you need a workspace relative path, use ${workspaceRoot} to create an absolute path e.g. `"${workspaceRoot}/modules/foo.psm1"`. + +We recommend deleting any existing `launch.json` file you're using so that a new one will +be generated with the new defaults. + +#### Console improvements + +- Improved PowerShell console output formatting and performance + - The console prompt is now displayed after a command is executed + - Command execution errors are now displayed correctly in more cases + - Console output now wraps at 120 characters instead of 80 characters + +- Added choice and input prompt support + - When executing code using the 'Run Selection' command, choice and input prompts appear as VS Code UI popups + - When executing code in the debugger, choice and input prompts appear in the Debug Console + +#### New commands + +- "Find/Install PowerShell modules from the gallery" (`Ctrl+K Ctrl+F`): Enables you to find and install modules from the PowerShell Gallery (thanks [@dfinke](https://github.com/dfinke)!) +- "Open current file in PowerShell ISE" (`Ctrl+Shift+i`): Opens the current file in the PowerShell ISE (thanks [@janegilring](https://github.com/janegilring)!) + +#### Editor improvements + +- Path auto-completion lists show just the current directory's contents instead of the full path (which had resulted in clipped text) +- Parameter auto-completion lists are now sorted in the same order as they are in PowerShell ISE where command-specific parameters preceed the common parameters +- Parameter auto-completion lists show the parameter type +- Command auto-completion lists show the resolved command for aliases and the path for executables +- Many improvements to the PowerShell snippets, more clearly separating functional and example snippets (all of the latter are prefixed with `ex-`) +- Added some additional example script files in the `examples` folder + +#### New configuration settings + +- `powershell.developer.editorServicesLogLevel`: configures the logging verbosity for PowerShell Editor Services. The default log level will now write less logs, improving overall performance + +## 0.3.1 +### Thursday, December 17, 2015 + +- Fix issue #49, Debug Console does not receive script output + +## 0.3.0 +### Tuesday, December 15, 2015 + +- Major improvements in variables retrieved from the debugging service: + - Global and script scope variables are now accessible + - New "Auto" scope which shows only the variables defined within the current scope + - Greatly improved representation of variable values, especially for dictionaries and + objects that implement the ToString() method +- Added new "Expand Alias" command which resolves command aliases used in a file or + selection and updates the source text with the resolved command names +- Reduced default Script Analyzer rules to a minimal list +- Fixed a wide array of completion text replacement bugs +- Improved extension upgrade experience + +## 0.2.0 +### Monday, November 23, 2015 + +- (Experimental) Added a new "Run selection" (F8) command which executes the current code selection and displays the output +- Added a new online help command! Press Ctrl+F1 to get help for the symbol under the cursor. +- Enabled PowerShell language features for untitled and in-memory (e.g. in Git diff viewer) PowerShell files +- Added `powershell.scriptAnalysis.enable` configuration variable to allow disabling script analysis for performance (issue #11) +- Fixed issue where user's custom PowerShell snippets did not show up +- Fixed high CPU usage when completing or hovering over an application path + +## 0.1.0 +### Wednesday, November 18, 2015 + +Initial release with the following features: + +- Syntax highlighting +- Code snippets +- IntelliSense for cmdlets and more +- Rule-based analysis provided by PowerShell Script Analyzer +- Go to Definition of cmdlets and variables +- Find References of cmdlets and variables +- Document and workspace symbol discovery +- Local script debugging and basic interactive console support diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..686e5e7a09 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,10 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns +- Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..193280892b --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + true + + diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000000..38021b41e3 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,5 @@ + + + + + diff --git a/LICENSE.txt b/LICENSE.txt index bf0b4af39d..b2f52a2bad 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,13 +1,21 @@ -Windows PowerShell for Visual Studio Code 0.1.0 -Copyright (c) Microsoft Corporation - -All rights reserved. +Copyright (c) Microsoft Corporation. MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000000..0b3f68dbc3 --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,814 @@ +NOTICES AND INFORMATION +Do Not Translate or Localize + +This software incorporates material from third parties. +Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, +or you may send a check or money order for US $5.00, including the product name, +the open source component name, platform, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the extent +required to debug changes to any libraries licensed under the GNU Lesser General Public License. + +--------------------------------------------------------- + +webidl-conversions 3.0.1 - BSD-2-Clause +https://github.com/jsdom/webidl-conversions#readme + +Copyright (c) 2014, Domenic Denicola + +# The BSD 2-Clause License + +Copyright (c) 2014, Domenic Denicola +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +lru-cache 6.0.0 - ISC +https://github.com/isaacs/node-lru-cache#readme + +Copyright (c) Isaac Z. Schlueter and Contributors + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +minimatch 5.1.6 - ISC +https://github.com/isaacs/minimatch#readme + +Copyright (c) 2011-2023 Isaac Z. Schlueter and Contributors + +The ISC License + +Copyright (c) 2011-2023 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +semver 7.6.0 - ISC +https://github.com/npm/node-semver#readme + +Copyright Isaac Z. Schlueter +Copyright (c) Isaac Z. Schlueter and Contributors + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +yallist 4.0.0 - ISC +https://github.com/isaacs/yallist#readme + +Copyright (c) Isaac Z. Schlueter and Contributors + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/1ds-core-js 4.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +copyright Microsoft 2018 +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/1ds-post-js 4.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +copyright Microsoft 2018 +copyright Microsoft 2020 +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +copyright Microsoft 2018-2020 +copyright Microsoft 2022 Simple +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/applicationinsights-channel-js 3.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/applicationinsights-common 3.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/applicationinsights-core-js 3.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/applicationinsights-shims 3.0.1 - MIT +https://github.com/microsoft/ApplicationInsights-JS/tree/main/tools/shims + +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/applicationinsights-web-basic 3.1.2 - MIT +https://github.com/microsoft/ApplicationInsights-JS#readme + +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@microsoft/dynamicproto-js 2.0.3 - MIT +https://github.com/microsoft/DynamicProto-JS#readme + +Copyright (c) 2022 Nevware21 +Copyright (c) Microsoft Corporation +Copyright (c) Microsoft and contributors + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@nevware21/ts-async 0.5.0 - MIT +https://github.com/nevware21/ts-async + +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) NevWare21 and contributors + +MIT License + +Copyright (c) 2022 Nevware21 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@nevware21/ts-utils 0.11.1 - MIT +https://github.com/nevware21/ts-utils + +Copyright (c) 2022 NevWare21 +Copyright (c) 2022 Nevware21 +Copyright (c) 2023 Nevware21 +Copyright (c) 2024 Nevware21 +Copyright (c) NevWare21 and contributors + +MIT License + +Copyright (c) 2022 NevWare21 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +@vscode/extension-telemetry 0.9.6 - MIT +https://github.com/Microsoft/vscode-extension-telemetry#readme + +Copyright (c) Microsoft Corporation + +vscode-extension-telemetry + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +balanced-match 1.0.2 - MIT +https://github.com/juliangruber/balanced-match + +Copyright (c) 2013 Julian Gruber + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +brace-expansion 2.0.1 - MIT +https://github.com/juliangruber/brace-expansion + +Copyright (c) 2013 Julian Gruber + +MIT License + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +node-fetch 2.7.0 - MIT +https://github.com/bitinn/node-fetch + +Copyright (c) 2016 David Frank + +The MIT License (MIT) + +Copyright (c) 2016 David Frank + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +tr46 0.0.3 - MIT +https://github.com/Sebmaster/tr46.js#readme + + +MIT License + +Copyright (c) Sebastian Mayr + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +untildify 4.0.0 - MIT +https://github.com/sindresorhus/untildify#readme + +(c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) Sindre Sorhus (sindresorhus.com) + +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +uuid 9.0.1 - MIT +https://github.com/uuidjs/uuid#readme + +Copyright 2011, Sebastian Tschan https://blueimp.net +Copyright (c) 2010-2020 Robert Kieffer and other contributors +Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet + +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +vscode-jsonrpc 8.2.0 - MIT +https://github.com/Microsoft/vscode-languageserver-node#readme + +Copyright (c) Microsoft Corporation + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +vscode-languageclient 9.0.1 - MIT +https://github.com/Microsoft/vscode-languageserver-node#readme + +Copyright (c) Microsoft Corporation + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +vscode-languageserver-protocol 3.17.5 - MIT +https://github.com/Microsoft/vscode-languageserver-node#readme + +Copyright (c) Microsoft Corporation +Copyright (c) TypeFox, Microsoft and others + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +vscode-languageserver-types 3.17.5 - MIT +https://github.com/Microsoft/vscode-languageserver-node#readme + +Copyright (c) Microsoft Corporation + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +whatwg-url 5.0.0 - MIT +https://github.com/jsdom/whatwg-url#readme + +(c) extraPathPercentEncodeSet.has +Copyright (c) 2015-2016 Sebastian Mayr + +The MIT License (MIT) + +Copyright (c) 2015–2016 Sebastian Mayr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +--------------------------------------------------------- diff --git a/README.md b/README.md index f83a85d0cd..70f7df3726 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,133 @@ -# PowerShell Language Support for Visual Studio Code +# PowerShell for Visual Studio Code -This extension provides rich PowerShell language support for Visual Studio Code. -Now you write and debug PowerShell scripts using the excellent IDE-like interface +[![CI Tests](https://github.com/PowerShell/vscode-powershell/actions/workflows/ci-test.yml/badge.svg)](https://github.com/PowerShell/vscode-powershell/actions/workflows/ci-test.yml) +[![Version](https://img.shields.io/visual-studio-marketplace/v/ms-vscode.PowerShell)](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/ms-vscode.PowerShell)](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell) +[![Join the chat on Discord](https://img.shields.io/discord/180528040881815552.svg?label=%23vscode&logo=discord&logoColor=white)](https://aka.ms/powershell-vscode-discord) + +This extension provides rich [PowerShell][] language support for [Visual Studio Code][] (VS Code). +Now you can write and debug PowerShell scripts using the excellent IDE-like interface that VS Code provides. -## Features +This repository, `vscode-powershell`, is the [Language Server Protocol][] client for VS +Code and [`PowerShellEditorServices`][] is the server (also used by other editors, such as +Emacs and Vim). + +[PowerShell]: https://github.com/PowerShell/PowerShell +[Visual Studio Code]: https://github.com/Microsoft/vscode +[`PowerShellEditorServices`]: https://github.com/PowerShell/PowerShellEditorServices +[Language Server Protocol]: https://microsoft.github.io/language-server-protocol/ + +## Available Features + +- [Syntax highlighting][] +- Advanced built-in [code snippets][] +- [IntelliSense][] for cmdlets and more +- [Problems][] reported by [PowerShell Script Analyzer][] +- [Go to Definition][] of cmdlets, variables, classes and more +- [Find References][] of cmdlets, variables, classes and more +- Document and Workspace [Symbol Navigation][] +- Symbol-based [Outline View][] +- Run selected PowerShell code in current terminal using F8 +- Launch online help for the symbol under the cursor using Ctrl+F1 +- PowerShell [Debugger][] integration +- An Extension Terminal that can interact with the debugger (try `Set-PSBreakpoint`!) +- PowerShell ISE theme findable in the [theme picker][] +- Also try ISE Mode with the **Toggle ISE Mode** command + +Bundled with the extension is the PowerShell ISE theme. It is not activated by default, +but after installing this extension either click **Set Color Theme** or use the [theme +picker][] and select **PowerShell ISE**. + +[Syntax highlighting]: https://github.com/PowerShell/EditorSyntax +[code snippets]: https://code.visualstudio.com/docs/editor/userdefinedsnippets +[IntelliSense]: https://code.visualstudio.com/docs/editor/intellisense +[Problems]: https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_errors-and-warnings +[PowerShell Script Analyzer]: http://github.com/PowerShell/PSScriptAnalyzer +[Go to Definition]: https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition +[Find References]: https://code.visualstudio.com/docs/editor/editingevolved#_reference-information +[Symbol Navigation]: https://code.visualstudio.com/docs/editor/editingevolved#_open-symbol-by-name +[Outline View]: https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view +[Debugger]: https://learn.microsoft.com/powershell/scripting/dev-cross-plat/vscode/using-vscode#debugging-with-visual-studio-code +[theme picker]: https://code.visualstudio.com/docs/getstarted/themes + +## Platform Support + +The extension should work everywhere [Visual Studio Code](https://code.visualstudio.com/docs/supporting/requirements) is supported using [PowerShell 7+ currently supported versions][]. + +> [!IMPORTANT] +> For Windows PowerShell, only version 5.1 is supported and only on a best-effort basis. [.NET Framework 4.8][dotnet-framework] or higher is required. + +> [!IMPORTANT] +> [Visual Studio Code for the Web](https://code.visualstudio.com/docs/editor/vscode-web) is only supported for limited functionality such as basic syntax highlighting, as the PowerShell engine cannot run in this environment currently. + +[VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview) Environments, including [Github Codespaces](https://github.com/features/codespaces) and [VS Code Server](https://code.visualstudio.com/docs/remote/vscode-server) are supported. + +We actively test the following configurations [in Github Actions on every commit](https://github.com/PowerShell/vscode-powershell/actions/workflows/ci-test.yml): +- **Windows Server 2022** with Windows PowerShell 5.1 and PowerShell 7+ +- **macOS 14.7** with PowerShell 7+ +- **Ubuntu 24.04** with PowerShell 7+ + +On Windows, we also test with and without Constrained Language Mode enabled. -- Syntax highlighting -- Code snippets -- IntelliSense for cmdlets and more -- Rule-based analysis provided by [PowerShell Script Analyzer](http://github.com/PowerShell/PSScriptAnalyzer) -- Go to Definition of cmdlets and variables -- Find References of cmdlets and variables -- Document and workspace symbol discovery -- Local script debugging and basic interactive console support! +Read the [installation instructions][] +to get more details on how to use the extension on these platforms. -## Example Scripts +[PowerShell 7+ currently supported versions]: https://docs.microsoft.com/en-us/powershell/scripting/powershell-support-lifecycle +[installation instructions]: https://docs.microsoft.com/en-us/powershell/scripting/components/vscode/using-vscode +[dotnet-framework]: https://dotnet.microsoft.com/en-us/download/dotnet-framework -There are some example scripts in the extension's `examples` folder that you can -use to discover PowerShell editing and debugging functionality. Please -check out the included [README.md](examples/README.md) file to learn more about -how to use them. +## Installing the Extension -This folder can be found at the following path: +The PowerShell extension can be installed from the Visual Studio Code Marketplace by +clicking the [**Install Button**][]. You can also install the PowerShell extension from +within VS Code by opening the **Extensions** view with keyboard shortcut +Ctrl+Shift+X, typing PowerShell, and selecting the extension. -``` -c:\Users\\.vscode\extensions\daviwil.PowerShell\examples -``` +We would encourage you to try the _pre-release_ version whenever possible. When a +_Pre-Release_ is available, it can be installed from the marketplace using the +**Switch to Pre-Release Version** button. You can switch back to the stable version of the +extension by using the **Switch to Release Version** button that will appear. You can also +downgrade to other versions of the extension using the arrow next to the **Uninstall** +button and choosing **Install Another Version**. + +[**Install Button**]: vscode:extension/ms-vscode.PowerShell + +## Getting Help + +Please our [support](SUPPORT.md) document. + +## Code of Conduct + +Please see our [Code of Conduct](CODE_OF_CONDUCT.md) before participating in this project. ## Contributing to the Code Check out the [development documentation](docs/development.md) for more details on how to contribute to this extension! +## Security Note + +For any security issues, please see [here](SECURITY.md). + +## Maintainers + +### Current + +- Andy Jordan - [@andyleejordan](https://github.com/andyleejordan) +- Patrick Meinecke - [@SeeminglyScience](https://github.com/SeeminglyScience) +- Sydney Smith - [@SydneyhSmith](https://github.com/SydneyhSmith) +- Justin Grote - [@JustinGrote](https://github.com/JustinGrote) + +### Emeriti + +- Keith Hill - [@rkeithhill](https://github.com/rkeithhill) +- Rob Holt - [@rjmholt](https://github.com/rjmholt) +- Tyler Leonhardt - [@TylerLeonhardt](https://github.com/TylerLeonhardt) +- David Wilson - [@daviwil](https://github.com/daviwil) + ## License -This extension is [licensed under the MIT License](LICENSE.txt). Please see the -[third-party notices](Third Party Notices.txt) file for details on the third-party +This extension is [licensed under the MIT License](LICENSE.txt). Please see the +[third-party notices](NOTICE.txt) file for details on the third-party binaries that we include with releases of this project. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..f941d308b1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin) and [PowerShell](https://github.com/PowerShell). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). + + diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000000..973f76643f --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,18 @@ +# Support + +## How to file issues and get help + +If you experience any problems with the PowerShell Extension, see the +[troubleshooting docs](docs/troubleshooting.md) for common issues. + +If you find a bug, please [open an issue][] so we can fix it. + +Don't forget to check out the official guide on +[Using VS Code for PowerShell Development][]. + +[Using VS Code for PowerShell Development]: https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/using-vscode +[open an issue]: https://github.com/PowerShell/vscode-powershell/issues/new/choose + +## Microsoft Support Policy + +Support for this project is limited to the resources listed above. diff --git a/Third Party Notices.txt b/Third Party Notices.txt deleted file mode 100644 index 7071e9fc23..0000000000 --- a/Third Party Notices.txt +++ /dev/null @@ -1,31 +0,0 @@ -This file is based on or incorporates material from the projects listed below (Third Party IP). The original copyright notice and the license under which Microsoft received such Third Party IP, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party IP to you under the licensing terms for the Microsoft product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. - ---- - -Json.NET - -Copyright (c) 2007 James Newton-King - Provided for Informational Purposes Only - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---- - -AsyncEx - -Copyright (c) 2014 StephenCleary - Provided for Informational Purposes Only - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000000..ddf9f1c019 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,121 @@ +#!/usr/bin/env pwsh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +[CmdletBinding(DefaultParameterSetName = "Build")] +param( + [Parameter(ParameterSetName="Bootstrap")] + [switch] + $Bootstrap, + + [Parameter(ParameterSetName="Build")] + [switch] + $Clean, + + [Parameter(ParameterSetName="Build")] + [switch] + $Test +) + +$NeededTools = @{ + VSCode = "Visual Studio Code" + NodeJS = "Node.js 6.0 or higher" + PowerShellGet = "PowerShellGet latest" + InvokeBuild = "InvokeBuild latest" +} + +function needsVSCode () { + try { + $vscodeVersion = (code -v) + if (-not $vscodeVersion) { + Throw + } + } catch { + try { + $vscodeInsidersVersion = (code-insiders -v) + if (-not $vscodeInsidersVersion) { + Throw + } + } catch { + return $true + } + } + return $false +} + +function needsNodeJS () { + try { + $nodeJSVersion = node -v + } catch { + return $true + } + + if ($nodeJSVersion -notmatch 'v(\d+\.\d+\.\d+)') { + return $true + } + + $nodeVer = [System.Version]$matches[1] + return ($nodeVer.Major -lt 6) +} + +function needsPowerShellGet () { + if (Get-Module -ListAvailable -Name PowerShellGet) { + return $false + } + return $true +} + +function needsInvokeBuild () { + if (Get-Module -ListAvailable -Name InvokeBuild) { + return $false + } + return $true +} + +function getMissingTools () { + $missingTools = @() + + if (needsVSCode) { + $missingTools += $NeededTools.VSCode + } + if (needsNodeJS) { + $missingTools += $NeededTools.NodeJS + } + if (needsPowerShellGet) { + $missingTools += $NeededTools.PowerShellGet + } + if (needsInvokeBuild) { + $missingTools += $NeededTools.InvokeBuild + } + + return $missingTools +} + +function hasMissingTools () { + return ((getMissingTools).Count -gt 0) +} + +if ($Bootstrap) { + $string = "Here is what your environment is missing:`n" + $missingTools = getMissingTools + if (($missingTools).Count -eq 0) { + $string += "* nothing!`n`n Run this script without a flag to build or a -Clean to clean." + } else { + $missingTools | ForEach-Object {$string += "* $_`n"} + $string += "`nAll instructions for installing these tools can be found on VSCode PowerShell's Github:`n" ` + + "https://github.com/PowerShell/vscode-powershell/blob/main/docs/development.md" + } + Write-Host "`n$string`n" +} elseif(hasMissingTools) { + Write-Host "You are missing needed tools. Run './build.ps1 -Bootstrap' to see what they are." +} else { + if($Clean) { + Invoke-Build Clean + } + + Invoke-Build Build + + if($Test) { + Invoke-Build Test + } +} diff --git a/build/InstallPreview.ps1 b/build/InstallPreview.ps1 deleted file mode 100644 index 1f22a031bb..0000000000 --- a/build/InstallPreview.ps1 +++ /dev/null @@ -1,35 +0,0 @@ - -# Make sure VS Code isn't running first -$ErrorActionPreference = "SilentlyContinue" -if ((Get-Process -Name "Code").Count -gt 0) -{ - Write-Warning "Visual Studio Code is currently running. You must close all VS Code windows before continuing." -} -else -{ - # Fail fast on future errors - $ErrorActionPreference = "Stop" - - $destPath = "$env:USERPROFILE\.vscode\extensions\vscode-powershell\" - - if (Test-Path $destPath) - { - Remove-Item $destPath -Recurse - } - - Write-Output "Installing to $destPath" - Expand-Archive -Path ".\vscode-powershell.zip" -DestinationPath $destPath - - if ($?) - { - Write-Output "Installation complete!" - Write-Output "" - Write-Output "Launching Visual Studio Code..." - - & "${env:ProgramFiles(x86)}\Microsoft VS Code\Code.exe" "$destPath\examples\" "$destPath\examples\README.md" 2>&1 | Out-Null - } - else - { - Write-Output "Installation failed!" - } -} diff --git a/build/PackagePreviewRelease.ps1 b/build/PackagePreviewRelease.ps1 deleted file mode 100644 index 554288cc2b..0000000000 --- a/build/PackagePreviewRelease.ps1 +++ /dev/null @@ -1,43 +0,0 @@ -param([string]$EditorServicesRepoPath = "") - -$ErrorActionPreference = "Stop" - -# Simple test to make sure we're in the root folder -if (!(Test-Path "package.json")) -{ - throw "This script must be run from the root vscode-powershell folder (contains package.json)." -} - -if ([string]::IsNullOrEmpty($EditorServicesRepoPath) -or !(Test-Path $EditorServicesRepoPath)) -{ - throw "Must provide path to a PowerShell Editor Services Git repository" -} - -$hostBinPath = Join-Path $EditorServicesRepoPath "src\PowerShellEditorServices.Host\bin\Debug" - -if (!(Test-Path $hostBinPath)) -{ - throw "The path '$hostBinPath' was not found. Has the Editor Services solution been compiled?" -} - -Remove-Item -Path ".\bin\*" -Copy-Item -Path "$hostBinPath\*" -Include ("*.exe", "*.dll", "*.pdb", "*.xml") -Exclude ("*.vshost.exe") -Destination ".\bin" - -$packageFiles = @( - "out", - "bin", - #"LICENSE", - "package.json", - #"README.md", - "Third Party Notices.txt", - "snippets", - "examples" -) - -# Build the extension files package -Compress-Archive -DestinationPath "vscode-powershell.zip" -Path $packageFiles -Force - -# Build the release package -Compress-Archive -DestinationPath "vscps-preview.zip" -Path @(".\build\InstallPreview.ps1", "vscode-powershell.zip") -Force - -Write-Output "Packaging complete." diff --git a/docs/azure_data_studio/README.md b/docs/azure_data_studio/README.md new file mode 100644 index 0000000000..7af74b25fe --- /dev/null +++ b/docs/azure_data_studio/README.md @@ -0,0 +1,10 @@ +# Azure Data Studio Docs + +[Azure Data Studio](https://github.com/Microsoft/azuredatastudio) is a VSCode-like IDE primarily targeted at database administrators and is a fork of VSCode. Since it's a fork of VSCode, many extensions "just work" including the PowerShell extension. + +This folder contains any docs for PowerShell extension support in Azure Data Studio. + +Table of Contents: + +* `README.md` - This file. It's purely for information about this folder and shouldn't be used elsewhere. +* `README_FOR_MARKETPLACE.md` - The markdown file that will be shown when you look at the PowerShell extension in the Azure Data Studio marketplace. diff --git a/docs/azure_data_studio/README_FOR_MARKETPLACE.md b/docs/azure_data_studio/README_FOR_MARKETPLACE.md new file mode 100644 index 0000000000..7ecea003f9 --- /dev/null +++ b/docs/azure_data_studio/README_FOR_MARKETPLACE.md @@ -0,0 +1,208 @@ +# PowerShell for Azure Data Studio + +[![Build Status](https://dev.azure.com/powershell/vscode-powershell/_apis/build/status/PowerShell.vscode-powershell?branchName=main)](https://dev.azure.com/powershell/vscode-powershell/_build/latest?definitionId=51&branchName=main) +[![Version](https://vsmarketplacebadge.apphb.com/version/ms-vscode.PowerShell.svg)](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell) +[![Installs](https://vsmarketplacebadge.apphb.com/installs-short/ms-vscode.PowerShell.svg)](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell) +[![Join the chat on Discord](https://img.shields.io/discord/180528040881815552.svg?label=%23vscode&logo=discord&logoColor=white)](https://aka.ms/powershell-vscode-discord) +[![Join the chat on Gitter](https://badges.gitter.im/PowerShell/vscode-powershell.svg)](https://gitter.im/PowerShell/vscode-powershell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +This extension provides rich PowerShell language support for [Azure Data Studio](https://github.com/Microsoft/azuredatastudio) (ADS). +Now you can write and run PowerShell scripts using the excellent IDE-like interface +that ADS provides. + +This extension is powered by the PowerShell language server, +[PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices). +This leverages the +[Language Server Protocol](https://microsoft.github.io/language-server-protocol/) +where `PowerShellEditorServices` is the server and `vscode-powershell` is the client. + +Also included in this extension is the PowerShell ISE theme for Visual Studio Code. It is +not activated by default, but after installing this extension either click "Set Color +Theme" or use the [theme picker](https://code.visualstudio.com/docs/getstarted/themes) and +select "PowerShell ISE" for a fun and familiar experience. + +## Platform Support + +The extension _should_ work anywhere ADS itself and PowerShell Core 7.2 or higher is +[supported][]. For Windows PowerShell, only version 5.1 is supported. Please note that +PowerShell Core 6 is end-of-life and so not supported. Our test matrix includes the +following: + +- **Windows Server 2022** with Windows PowerShell 5.1 and PowerShell Core 7.2.7 +- **Windows Server 2019** with Windows PowerShell 5.1 and PowerShell Core 7.2.7 +- **macOS 11** with PowerShell Core 7.2.7 +- **Ubuntu 20.04** with PowerShell Core 7.2.7 + +[supported]: https://docs.microsoft.com/en-us/powershell/scripting/powershell-support-lifecycle?view=powershell-7.1#supported-platforms + +Read the [installation instructions](https://docs.microsoft.com/en-us/powershell/scripting/components/vscode/using-vscode) +to get more details on how to use the extension on these platforms. + +**Read the [troubleshooting guide](./docs/troubleshooting.md) for answers to common questions.** + +## Features + +- Syntax highlighting +- Code snippets +- IntelliSense for cmdlets and more +- Rule-based analysis provided by [PowerShell Script Analyzer](http://github.com/PowerShell/PSScriptAnalyzer) +- Go to Definition of cmdlets and variables +- Find References of cmdlets and variables +- Document and workspace symbol discovery +- Run selected selection of PowerShell code using F8 +- Launch online help for the symbol under the cursor using Ctrl+F1 +- Local script debugging +- Extension Terminal support +- PowerShell ISE color theme + +## Installing the Extension + +You can install the official release of the PowerShell extension by following the steps +in the [Azure Data Studio documentation](https://docs.microsoft.com/en-us/sql/azure-data-studio/extensions). +In the Extensions pane, search for "PowerShell" extension and install it there. You will +get notified automatically about any future extension updates! + +You can also install a VSIX package from our [releases page](https://github.com/PowerShell/vscode-powershell/releases) by following the +[Install from a VSIX](https://code.visualstudio.com/docs/editor/extension-gallery#_install-from-a-vsix) +instructions. The easiest way is through the command line: + +```powershell +azuredatastudio --install-extension powershell-.vsix +``` + +## Reporting Problems + +If you experience any problems with the PowerShell Extension, see +[the troubleshooting docs](./docs/troubleshooting.md) for information +on diagnosing and reporting issues. + +## Security Note + +For any security issues, please see [here](./SECURITY.md). + +## Example Scripts + +There are some example scripts in the extension's `examples` folder that you can +use to discover PowerShell editing and debugging functionality. Please +check out the included [README.md](examples/README.md) file to learn more about +how to use them. + +This folder can be found at the following path: + +```powershell +$HOME/.azuredatastudio/extensions/ms-vscode.powershell-/examples +``` + +To open/view the extension's examples in Azure Data Studio, run the following from your +PowerShell session: + +```powershell +azuredatastudio (Get-ChildItem $HOME/.azuredatastudio/extensions/ms-vscode.powershell-*/examples)[-1] +``` + +### SQL PowerShell Examples + +In order to use these examples (below), you need to install the SqlServer module from the +[PowerShell Gallery](https://www.powershellgallery.com/packages/SqlServer). + +```powershell +Install-Module -Name SqlServer +``` + +> NOTE: With version `21.1.18102` and up, the `SqlServer` module supports [PowerShell Core](https://github.com/PowerShell/PowerShell) 6.2 and up, in addion to Windows PowerShell. + +In this example, we use the `Get-SqlInstance` cmdlet to Get the Server SMO objects for +ServerA and ServerB. The default output for this command will include the Instance name, +version, Service Pack, and CU Update Level of the instances. + +```powershell +Get-SqlInstance -ServerInstance ServerA, ServerB +``` + +Here is a sample of what that output will look like: + +```powershell +Instance Name Version ProductLevel UpdateLevel HostPlatform HostDistribution +------------- ------- ------------ ----------- ------------ ---------------- +ServerA 13.0.5233 SP2 CU4 Windows Windows Server 2016 Datacenter +ServerB 14.0.3045 RTM CU12 Linux Ubuntu +``` + +In the following example, we will do a `dir` (alias for `Get-ChildItem`) to get the list of all SQL Server instances listed in your Registered Servers file, and then use the `Get-SqlDatabase` cmdlet to get a list of Databases for each of those instances. + +```powershell +dir 'SQLSERVER:\SQLRegistration\Database Engine Server Group' -Recurse | +WHERE { $_.Mode -ne 'd' } | +FOREACH { + Get-SqlDatabase -ServerInstance $_.Name +} +``` + +Here is a sample of what that output will look like: + +```powershell +Name Status Size Space Recovery Compat. Owner + Available Model Level +---- ------ ---- ---------- -------- ------- ----- +AdventureWorks2017 Normal 336.00 MB 57.01 MB Simple 140 sa +main Normal 6.00 MB 368.00 KB Simple 140 sa +model Normal 16.00 MB 5.53 MB Full 140 sa +msdb Normal 48.44 MB 1.70 MB Simple 140 sa +PBIRS Normal 144.00 MB 55.95 MB Full 140 sa +PBIRSTempDB Normal 16.00 MB 4.20 MB Simple 140 sa +SSISDB Normal 325.06 MB 26.21 MB Full 140 sa +tempdb Normal 72.00 MB 61.25 MB Simple 140 sa +WideWorldImporters Normal 3.2 GB 2.6 GB Simple 130 sa +``` + +This example uses the `Get-SqlDatabase` cmdlet to retrieve a list of all databases on the ServerB instance, then presents a grid/table (using the `Out-GridView` cmdlet) to select which databases should be backed up. Once the user clicks on the "OK" button, only the highlighted databases will be backed up. + +```powershell +Get-SqlDatabase -ServerInstance ServerB | +Out-GridView -PassThru | +Backup-SqlDatabase -CompressionOption On +``` + +This example, again, gets list of all SQL Server instances listed in your Registered Servers file, then calls the `Get-SqlAgentJobHistory` which reports every failed SQL Agent Job since Midnight, for each SQL Server instances listed. + +```powershell +dir 'SQLSERVER:\SQLRegistration\Database Engine Server Group' -Recurse | +WHERE {$_.Mode -ne 'd' } | +FOREACH { + Get-SqlAgentJobHistory -ServerInstance $_.Name -Since Midnight -OutcomesType Failed +} +``` + +## Contributing to the Code + +Check out the [development documentation](docs/development.md) for more details +on how to contribute to this extension! + +## Maintainers + +- Patrick Meinecke - [@SeeminglyScience](https://github.com/SeeminglyScience) +- Andy Jordan - [@andschwa](https://github.com/andschwa) +- Sydney Smith - [@SydneyhSmith](https://github.com/SydneyhSmith) + +### Emeriti + +- Keith Hill - [@rkeithhill](https://github.com/rkeithhill) +- Rob Holt - [@rjmholt](https://github.com/rjmholt) +- Tyler Leonhardt - [@TylerLeonhardt](https://github.com/TylerLeonhardt) +- David Wilson - [@daviwil](https://github.com/daviwil) + +## License + +This extension is [licensed under the MIT License](LICENSE.txt). Please see the +[third-party notices](Third%20Party%20Notices.txt) file for details on the third-party +binaries that we include with releases of this project. + +## [Code of Conduct][conduct-md] + +This project has adopted the [Microsoft Open Source Code of Conduct][conduct-code]. +For more information see the [Code of Conduct FAQ][conduct-FAQ] or contact [opencode@microsoft.com][conduct-email] with any additional questions or comments. + +[conduct-code]: http://opensource.microsoft.com/codeofconduct/ +[conduct-FAQ]: http://opensource.microsoft.com/codeofconduct/faq/ +[conduct-email]: mailto:opencode@microsoft.com +[conduct-md]: https://github.com/PowerShell/vscode-powershell/blob/main/CODE_OF_CONDUCT.md diff --git a/docs/azure_data_studio/Server-Creation-With-Docker-Notebook.ipynb b/docs/azure_data_studio/Server-Creation-With-Docker-Notebook.ipynb new file mode 100644 index 0000000000..be3134e634 --- /dev/null +++ b/docs/azure_data_studio/Server-Creation-With-Docker-Notebook.ipynb @@ -0,0 +1,29 @@ +{ + "metadata": { + "kernelspec": { + "name": "SQL", + "display_name": "SQL", + "language": "sql" + }, + "language_info": { + "name": "sql", + "version": "" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "markdown", + "source": "## Creating a SQL Server in a Linux Container [Using PowerShell]\r\n\r\n|Module|Link|\r\n|------------|---------------------------------------|\r\n|SqlServer|https://www.powershellgallery.com/packages/SqlServer/|\r\n|ReportingServicesTools|https://www.powershellgallery.com/packages/ReportingServicesTools/|\r\n|MicrosoftPowerBIMgmt|https://www.powershellgallery.com/packages/MicrosoftPowerBIMgmt/|\r\n|SqlServerDsc|https://www.powershellgallery.com/packages/SqlServerDsc/|\r\n|Az.Sql|https://www.powershellgallery.com/packages/Az.Sql/|\r\n\r\n
\r\nIf you don't already have a terminal window open, you need to first: Open the terminal  \r\n
\r\n
 \r\nYou probably don't have this directory on your machine, so run this: mkdir C:/SQLData/Docker/SQLDev63 \r\n
\r\n
\r\nSpin up a Docker Container with Invoke-Expression (Invoke-WebRequest https://gist.githubusercontent.com/SQLvariant)  Just click enter after the command is placed into the terminal. Just click enter after the command is placed into the terminal.  When prompted, the sa password is Test1234, but you can obviously change this.\r\n
\r\n
 \r\nView the PowerShell Script with PSEdit \r\n
\r\n", + "metadata": {} + }, + { + "cell_type": "code", + "source": "SELECT name, create_date\r\nFROM sys.databases", + "metadata": {}, + "outputs": [], + "execution_count": 0 + } + ] +} diff --git a/docs/community_snippets.md b/docs/community_snippets.md new file mode 100644 index 0000000000..39ac2195a1 --- /dev/null +++ b/docs/community_snippets.md @@ -0,0 +1,894 @@ +# Awesome VSCode Snippets for PowerShell + +> A curated list of awesome vscode snippets for PowerShell. + +_Inspired by the [awesome](https://github.com/sindresorhus/awesome) lists, focusing on PowerShell snippets in VSCode_ + +[![Awesome](https://awesome.re/badge.svg)](https://awesome.re) + +## What are snippets + +Code snippets are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements. +The list of snippets below is not integrated into the extension. However, instead, users can add them to their own, custom snippets file. +Check out the [VSCode documentation on snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets). It provides an overview and instructions on how to author snippets. It's really simple - just a little bit of JSON. + +_To contribute, check out our [guide here](#contributing)._ + +## Table of contents + +| Snippet name | Description | +| --------- | ---------| +| [AssertMock](#assertmock) | _Creates assert mock Pester test_ | +| [AWSRegionDynamicParameter](#awsregiondynamicparameter) | _Creates a dynamic parameter of current AWS regions by @jbruett_ | +| [DataTable](#datatable) | _Creates a DataTable_ | +| [DateTimeWriteVerbose](#datetimewriteverbose) | _Write-Verbose with the time and date pre-pended to your message by @ThmsRynr_ | +| [DSC](#dsc) | __DSC snippets previously bundled in extension__ | +| [Examples](#examples) | __Examples previously bundled in extension__ | +| [Error-Terminating](#error-terminating) | _Create a full terminating error by @omniomi_ | +| [Exchange Online Connection](#exchange-online-connection) | _Create a connection to Exchange Online by @vmsilvamolina_ | +| [HTML header](#html-header) | _Add HTML header with the style tag by @vmsilvamolina_ | +| [MaxColumnLengthinDataTable](#maxcolumnlengthindatatable) | _Gets the max length of string columns in datatables_ | +| [New Azure Resource Group](#new-azure-resource-group) | _Create an Azure Resource group by @vmsilvamolina_ | +| [Parameter-Credential](#parameter-credential) | _Add a standard credential parameter to your function by @omniomi_ | +| [Pester](#pester) | __Pester snippets previously bundled in extension__ | +| [PesterTestForMandatoryParameter](#pestertestformandatoryparameter) | _Create Pester test for a mandatory parameter_ | +| [PesterTestForParameter](#pestertestforparameter) | _Create Pester test for parameter_ | +| [Send-MailMessage](#send-mailmessage) | _Send an mail message with the most common parameters by @fullenw1_ | + +## Snippets + +### AssertMock + +Creates Assert Mock for Pester Tests by @SQLDBAWithABeard. + +#### Snippet + +```json +"AssertMock": { + "prefix": "AssertMock", + "body": [ + "$$assertMockParams = @{", + "\t'CommandName' = '${1:Command}'", + "\t'Times' = ${2:1}", + "\t'Exactly' = $$true", + "}", + "Assert-MockCalled @assertMockParams" + ], + "description": "AssertMock snippet for Pestering" +} +``` + +### AWSRegionDynamicParameter + +Creates a dynamic parameter of the current AWS regions. Includes parameter validation. + +#### Snippet + +```json +"AWSRegionDynamicParam": { + "prefix": "aws_region", + "body": [ + "DynamicParam {", + "\t$ParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary", + "\t$CR_ParamName = 'Region'", + "\t$CR_AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]", + "\t$CR_Attribute = New-Object System.Management.Automation.ParameterAttribute", + "\t$CR_Attribute.HelpMessage = 'List all the regions to be included in the document'", + "\t$CR_Attribute.Mandatory = $true", + "\t$CR_Attribute.ValueFromPipelineByPropertyName = $true", + "\t$CR_AttributeCollection.add($CR_Attribute)", + "\t$CR_intRegions = Get-AWSRegion -IncludeChina | Select-Object -ExpandProperty Region", + "\t$CR_intRegions += Get-AWSRegion -IncludeGovCloud | Select-Object -ExpandProperty Region", + "\t$CR_intRegions = $CR_intRegions | Select-Object -Unique", + "\t$CR_ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($CR_intRegions)", + "\t$CR_AttributeCollection.add($CR_ValidateSetAttribute)", + "\t$CR_Param = New-Object System.Management.Automation.RuntimeDefinedParameter($CR_ParamName, [String[]],$CR_AttributeCollection)", + "\t$ParamDictionary.Add($CR_ParamName, $CR_Param)", + "\treturn $paramDictionary", + "\t}" + ], + "description": "A dynamic parameter that builds a list of AWS regions" +} +``` + +### DataTable + +Quickly create a Data Table object by @SQLDBAWithABeard. + +#### Snippet + +```json +"DataTable": { + "prefix": "DataTable", + "body": [ + "# Create DataTable Object", + "$$table = New-Object system.Data.DataTable $$TableName", + + "\r# Create Columns", + "$$col1 = New-Object system.Data.DataColumn NAME1,([string])", + "$$col2 = New-Object system.Data.DataColumn NAME2,([decimal])", + + "\r#Add the Columns to the table", + "$$table.columns.add($$col1)", + "$$table.columns.add($$col2)", + + "\r# Create a new Row", + "$$row = $$table.NewRow() ", + + "\r# Add values to new row", + "$$row.Name1 = 'VALUE'", + "$$row.NAME2 = 'VALUE'", + + "\r#Add new row to table", + "$$table.Rows.Add($$row)" + ], + "description": "Creates a Data Table Object" +} +``` + +### DateTimeWriteVerbose + +Quickly add a `Write-Verbose` with the current date and time inserted before the message you're going to write to the verbose stream, by @ThmsRynr. + +#### Snippet + +```json +"DateTimeWriteVerbose": { + "prefix": "dtwv", + "body": [ + "Write-Verbose \"[$(Get-Date -format G)] ${1:message}\"$0" + ], + "description": "Pre-pend datetime for Write-Verbose" +} +``` + +### DSC + +DSC snippets migrated from the extension. + +```json +{ + "DSC Ensure Enum": { + "prefix": "DSC Ensure enum", + "description": "DSC Ensure enum definition snippet", + "body": [ + "enum Ensure {", + "\tAbsent", + "\tPresent", + "}", + "$0" + ] + }, + "DSC Resource Provider (class-based)": { + "prefix": "DSC resource provider (class-based)", + "description": "Class-based DSC resource provider snippet", + "body": [ + "[DscResource()]", + "class ${ResourceName:NameOfResource} {", + "\t[DscProperty(Key)]", + "\t[string] $${PropertyName:KeyName}", + "\t", + "\t# Gets the resource's current state.", + "\t[${ResourceName:NameOfResource}] Get() {", + "\t\t${0:$TM_SELECTED_TEXT}", + "\t\treturn \\$this", + "\t}", + "\t", + "\t# Sets the desired state of the resource.", + "\t[void] Set() {", + "\t\t", + "\t}", + "\t", + "\t# Tests if the resource is in the desired state.", + "\t[bool] Test() {", + "\t\t", + "\t}", + "}" + ] + }, + "DSC Resource Provider (function-based)": { + "prefix": "DSC resource provider (function-based)", + "description": "Function-based DSC resource provider snippet", + "body": [ + "function Get-TargetResource {", + "\tparam (", + "\t)", + "\t", + "\t${0:$TM_SELECTED_TEXT}", + "}", + "function Set-TargetResource {", + "\tparam (", + "\t)", + "\t", + "}", + "function Test-TargetResource {", + "\tparam (", + "\t)", + "\t", + "}" + ] + }, +} +``` + +### Examples + +Example snippets migrated from the extension. + +```json +{ + "Example-Class": { + "prefix": "ex-class", + "description": "Example: class snippet with a constructor, property and a method", + "body": [ + "class ${1:MyClass} {", + "\t# Property: Holds name", + "\t[String] \\$Name", + "", + "\t# Constructor: Creates a new MyClass object, with the specified name", + "\t${1:MyClass}([String] \\$NewName) {", + "\t\t# Set name for ${1:MyClass}", + "\t\t\\$this.Name = \\$NewName", + "\t}", + "", + "\t# Method: Method that changes \\$Name to the default name", + "\t[void] ChangeNameToDefault() {", + "\t\t\\$this.Name = \"DefaultName\"", + "\t}", + "}" + ] + }, + "Example-Cmdlet": { + "prefix": "ex-cmdlet", + "description": "Example: script cmdlet snippet with all attributes and inline help fields", + "body": [ + "<#", + ".SYNOPSIS", + "\tShort description", + ".DESCRIPTION", + "\tLong description", + ".EXAMPLE", + "\tExample of how to use this cmdlet", + ".EXAMPLE", + "\tAnother example of how to use this cmdlet", + ".INPUTS", + "\tInputs to this cmdlet (if any)", + ".OUTPUTS", + "\tOutput from this cmdlet (if any)", + ".NOTES", + "\tGeneral notes", + ".COMPONENT", + "\tThe component this cmdlet belongs to", + ".ROLE", + "\tThe role this cmdlet belongs to", + ".FUNCTIONALITY", + "\tThe functionality that best describes this cmdlet", + "#>", + "function ${name:Verb-Noun} {", + "\t[CmdletBinding(DefaultParameterSetName='Parameter Set 1',", + "\t SupportsShouldProcess=\\$true,", + "\t PositionalBinding=\\$false,", + "\t HelpUri = 'http://www.microsoft.com/',", + "\t ConfirmImpact='Medium')]", + "\t[Alias()]", + "\t[OutputType([String])]", + "\tParam (", + "\t\t# Param1 help description", + "\t\t[Parameter(Mandatory=\\$true,", + "\t\t Position=0,", + "\t\t ValueFromPipeline=\\$true,", + "\t\t ValueFromPipelineByPropertyName=\\$true,", + "\t\t ValueFromRemainingArguments=\\$false, ", + "\t\t ParameterSetName='Parameter Set 1')]", + "\t\t[ValidateNotNull()]", + "\t\t[ValidateNotNullOrEmpty()]", + "\t\t[ValidateCount(0,5)]", + "\t\t[ValidateSet(\"sun\", \"moon\", \"earth\")]", + "\t\t[Alias(\"p1\")] ", + "\t\t\\$Param1,", + "\t\t", + "\t\t# Param2 help description", + "\t\t[Parameter(ParameterSetName='Parameter Set 1')]", + "\t\t[AllowNull()]", + "\t\t[AllowEmptyCollection()]", + "\t\t[AllowEmptyString()]", + "\t\t[ValidateScript({\\$true})]", + "\t\t[ValidateRange(0,5)]", + "\t\t[int]", + "\t\t\\$Param2,", + "\t\t", + "\t\t# Param3 help description", + "\t\t[Parameter(ParameterSetName='Another Parameter Set')]", + "\t\t[ValidatePattern(\"[a-z]*\")]", + "\t\t[ValidateLength(0,15)]", + "\t\t[String]", + "\t\t\\$Param3", + "\t)", + "\t", + "\tbegin {", + "\t}", + "\t", + "\tprocess {", + "\t\tif (\\$pscmdlet.ShouldProcess(\"Target\", \"Operation\")) {", + "\t\t\t$0", + "\t\t}", + "\t}", + "\t", + "\tend {", + "\t}", + "}" + ] + }, + "Example-DSC Configuration": { + "prefix": "ex-DSC config", + "description": "Example: DSC configuration snippet that uses built-in resource providers", + "body": [ + "configuration Name {", + "\t# One can evaluate expressions to get the node list", + "\t# E.g: \\$AllNodes.Where(\"Role -eq Web\").NodeName", + "\tnode (\"Node1\",\"Node2\",\"Node3\")", + "\t{", + "\t\t# Call Resource Provider", + "\t\t# E.g: WindowsFeature, File", + "\t\tWindowsFeature FriendlyName", + "\t\t{", + "\t\t\tEnsure = \"Present\"", + "\t\t\tName = \"Feature Name\"", + "\t\t}", + "", + "\t\tFile FriendlyName", + "\t\t{", + "\t\t\tEnsure = \"Present\"", + "\t\t\tSourcePath = \\$SourcePath", + "\t\t\tDestinationPath = \\$DestinationPath", + "\t\t\tType = \"Directory\"", + "\t\t\tDependsOn = \"[WindowsFeature]FriendlyName\"", + "\t\t}", + "\t}", + "}" + ] + }, + "Example-DSC Resource Provider (class-based)": { + "prefix": "ex-DSC resource provider (class-based)", + "description": "Example: class-based DSC resource provider snippet", + "body": [ + "# Defines the values for the resource's Ensure property.", + "enum Ensure {", + "\t# The resource must be absent.", + "\tAbsent", + "\t# The resource must be present.", + "\tPresent", + "}", + "", + "# [DscResource()] indicates the class is a DSC resource.", + "[DscResource()]", + "class NameOfResource {", + "\t# A DSC resource must define at least one key property.", + "\t[DscProperty(Key)]", + "\t[string] \\$P1", + "\t", + "\t# Mandatory indicates the property is required and DSC will guarantee it is set.", + "\t[DscProperty(Mandatory)]", + "\t[Ensure] \\$P2", + "\t", + "\t# NotConfigurable properties return additional information about the state of the resource.", + "\t# For example, a Get() method might return the date a resource was last modified.", + "\t# NOTE: These properties are only used by the Get() method and cannot be set in configuration.", + "\t[DscProperty(NotConfigurable)]", + "\t[Nullable[datetime]] \\$P3", + "\t", + "\t[DscProperty()]", + "\t[ValidateSet(\"val1\", \"val2\")]", + "\t[string] \\$P4", + "\t", + "\t# Gets the resource's current state.", + "\t[NameOfResource] Get() {", + "\t\t# NotConfigurable properties are set in the Get method.", + "\t\t\\$this.P3 = something", + "\t\t# Return this instance or construct a new instance.", + "\t\treturn \\$this", + "\t}", + "\t", + "\t# Sets the desired state of the resource.", + "\t[void] Set() {", + "\t}", + "\t", + "\t# Tests if the resource is in the desired state.", + "\t[bool] Test() {", + "\t\t return \\$true", + "\t}", + "}" + ] + }, + "Example-DSC Resource Provider (function based)": { + "prefix": "ex-DSC resource provider (function based)", + "description": "Example: function-based DSC resource provider snippet", + "body": [ + "function Get-TargetResource {", + "\t# TODO: Add parameters here", + "\t# Make sure to use the same parameters for", + "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", + "\tparam (", + "\t)", + "}", + "function Set-TargetResource {", + "\t# TODO: Add parameters here", + "\t# Make sure to use the same parameters for", + "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", + "\tparam (", + "\t)", + "}", + "function Test-TargetResource {", + "\t# TODO: Add parameters here", + "\t# Make sure to use the same parameters for", + "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", + "\tparam (", + "\t)", + "}" + ] + }, + "Example-Path Processing for No Wildcards Allowed": { + "prefix": "ex-path processing for no wildcards allowed", + "description": "Example: processing non-wildcard paths that must exist (for use in process block). See parameter-path snippets.", + "body": [ + "# Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=\\$true)]", + "\\$paths = @()", + "foreach (\\$aPath in \\$Path) {", + "\tif (!(Test-Path -LiteralPath \\$aPath)) {", + "\t\t\\$ex = New-Object System.Management.Automation.ItemNotFoundException \"Cannot find path '\\$aPath' because it does not exist.\"", + "\t\t\\$category = [System.Management.Automation.ErrorCategory]::ObjectNotFound", + "\t\t\\$errRecord = New-Object System.Management.Automation.ErrorRecord \\$ex,'PathNotFound',\\$category,\\$aPath", + "\t\t\\$psCmdlet.WriteError(\\$errRecord)", + "\t\tcontinue", + "\t}", + "", + "\t# Resolve any relative paths", + "\t\\$paths += \\$psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\\$aPath)", + "}", + "", + "foreach (\\$aPath in \\$paths) {", + "\tif (\\$pscmdlet.ShouldProcess(\\$aPath, 'Operation')) {", + "\t\t# Process each path", + "\t\t$0", + "\t}", + "}" + ] + }, + "Example-Path Processing for Non-Existing Paths": { + "prefix": "ex-path processing for non-existing paths", + "description": "Example: processing non-existing paths typically used in New-* commands (for use in process block). See parameter-path snippet.", + "body": [ + "# Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=\\$true)]", + "\\$paths = @()", + "foreach (\\$aPath in \\$Path) {", + "\t# Resolve any relative paths", + "\t\\$paths += \\$psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\\$aPath)", + "}", + "", + "foreach (\\$aPath in \\$paths) {", + "\tif (\\$pscmdlet.ShouldProcess(\\$aPath, 'Operation')) {", + "\t\t# Process each path", + "\t\t$0", + "\t}", + "}" + ] + }, + "Example-Path Processing for Wildcards Allowed": { + "prefix": "ex-path processing for wildcards allowed", + "description": "Example: processing wildcard paths that must exist (for use in process block). See parameter-path-wildcards and parameter-literalpath snippets.", + "body": [ + "# Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=\\$true, DefaultParameterSetName='Path')]", + "\\$paths = @()", + "if (\\$psCmdlet.ParameterSetName -eq 'Path') {", + "\tforeach (\\$aPath in \\$Path) {", + "\t\tif (!(Test-Path -Path \\$aPath)) {", + "\t\t\t\\$ex = New-Object System.Management.Automation.ItemNotFoundException \"Cannot find path '\\$aPath' because it does not exist.\"", + "\t\t\t\\$category = [System.Management.Automation.ErrorCategory]::ObjectNotFound", + "\t\t\t\\$errRecord = New-Object System.Management.Automation.ErrorRecord \\$ex,'PathNotFound',\\$category,\\$aPath", + "\t\t\t\\$psCmdlet.WriteError(\\$errRecord)", + "\t\t\tcontinue", + "\t\t}", + "\t", + "\t\t# Resolve any wildcards that might be in the path", + "\t\t\\$provider = \\$null", + "\t\t\\$paths += \\$psCmdlet.SessionState.Path.GetResolvedProviderPathFromPSPath(\\$aPath, [ref]\\$provider)", + "\t}", + "}", + "else {", + "\tforeach (\\$aPath in \\$LiteralPath) {", + "\t\tif (!(Test-Path -LiteralPath \\$aPath)) {", + "\t\t\t\\$ex = New-Object System.Management.Automation.ItemNotFoundException \"Cannot find path '\\$aPath' because it does not exist.\"", + "\t\t\t\\$category = [System.Management.Automation.ErrorCategory]::ObjectNotFound", + "\t\t\t\\$errRecord = New-Object System.Management.Automation.ErrorRecord \\$ex,'PathNotFound',\\$category,\\$aPath", + "\t\t\t\\$psCmdlet.WriteError(\\$errRecord)", + "\t\t\tcontinue", + "\t\t}", + "\t", + "\t\t# Resolve any relative paths", + "\t\t\\$paths += \\$psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\\$aPath)", + "\t}", + "}", + "", + "foreach (\\$aPath in \\$paths) {", + "\tif (\\$pscmdlet.ShouldProcess(\\$aPath, 'Operation')) {", + "\t\t# Process each path", + "\t\t$0", + "\t}", + "}" + ] + }, + "Example-Splatting": { + "prefix": "ex-splat", + "description": "Example: PowerShell splatting technique snippet", + "body": [ + "\\$Params = @{", + "\tModule = '*'", + "\tVerb = 'Get'", + "}", + "Get-Command @Params" + ] + }, + "Example-Switch": { + "prefix": "ex-switch", + "description": "Example: switch statement snippet", + "body": [ + "switch (${variable:\\$x})", + "{", + "\t'${val:value1}' { $1 }", + "\t{\\$_ -in 'A','B','C'} {}", + "\t'value3' {}", + "\tDefault {}", + "}" + ] + }, +} +``` + +### Error-Terminating + +Quickly add a fully defined error record and throw. by @omniomi + +#### Snippet + +```json +"Throw Terminating Error": { + "prefix": "error-terminating", + "body": [ + "\\$Exception = New-Object ${1:System.ArgumentException} (\"${2:Invalid argument provided.}\")\r", + "\\$ErrorCategory = [System.Management.Automation.ErrorCategory]::${3:InvalidArgument}\r", + "# Exception, ErrorId as [string], Category, and TargetObject (e.g. the parameter that was invalid)\r", + "\\$ErrorRecord = New-Object System.Management.Automation.ErrorRecord(\\$Exception, '${4:InvalidArgument}', \\$ErrorCategory, ${5:\\$null})\r", + "\\$PSCmdlet.ThrowTerminatingError(\\$ErrorRecord)" + ], + "description": "Throw a full terminating error." +} +``` + + +### Exchange Online Connection + +Connect to Exchange Online, by @vmsilvamolina. + +#### Snippet + +```json +"Exchange Online Connection": { + "prefix": "ex-ExchangeOnlineConnection", + "body": [ + "#Set Execution Policy", + "Set-ExecutionPolicy RemoteSigned -Scope Process", + "#Define credential", + "\\$UserCredential = Get-Credential", + "# Create the session", + "\\$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential \\$UserCredential -Authentication Basic -AllowRedirection", + "Import-PSSession \\$Session -DisableNameChecking" + ], + "description": "Connect to Exchange Online" +} +``` + +### HTML header + +Add HTML header to a variable with the style tag (for css). + +#### Snippet + +```json +"HtML header": { + "prefix": "ex-AddHTMLheader", + "body": [ + "#HTML file and styles", + "\\$htmlHeader = @\"", + "", + "", + "", + "", + "${1:Title}", + "", + "", + "\"@" + ], + "description": "Add HTML header section" +} +``` + +### MaxColumnLengthinDataTable + +Takes a datatable object and iterates through it to get the max length of the string columns - useful for data loads into a SQL Server table with fixed column widths by @SQLDBAWithABeard. + +#### Snippet + +```json +"Max Length of Datatable": { + "prefix": "Max Length of Datatable", + "body": [ + "$$columns = ($$datatable | Get-Member -MemberType Property).Name", + "foreach($$column in $$Columns) {", + "\t$$max = 0", + "\tforeach ($$a in $$datatable){", + "\t\tif($$max -lt $$a.$$column.length){", + "\t\t\t$$max = $$a.$$column.length", + "\t\t}", + "\t}", + "\tWrite-Output \"$$column max length is $$max\"", + "}" + ], + "description": "Takes a datatable object and iterates through it to get the max length of the string columns - useful for data loads" +} +``` + +### New Azure Resource Group + +Create a Resource Group on Azure, by @vmsilvamolina. + +#### Snippet + +```json +"New Azure Resource Group": { + "prefix": "ex-New-AzureRmResourceGroup", + "body": [ + "#New Resource Group", + "New-AzureRmResourceGroup -ResourceGroupName \"${1:ResourceGroup}\" -Location \"${2:EastUS}\"" + ], + "description": "Create an Azure Resource Group" +} +``` + +### Parameter-Credential + +Add a `-Credential` parameter that supports a PSCredential object in a variable, `-Credential (Get-Credential)`, or `-Credential Username` (will prompt). Includes an empty PSCredential object as the default value but this is the first tabstop so pressing backspace after inserting the snippet removes it, by @omniomi. + +#### Snippet + +```json +"Parameter-Credential": { + "prefix": "parameter-credential", + "body": [ + "# Specifies the user account credentials to use when performing this task.\r", + "[Parameter()]\r", + "[ValidateNotNull()]\r", + "[System.Management.Automation.PSCredential]\r", + "[System.Management.Automation.Credential()]\r", + "$$Credential${1: = [System.Management.Automation.PSCredential]::Empty}" + ], + "description": "Parameter declaration snippet for a Credential parameter." +} +``` + +### Pester + +Pester snippets migrated from the extension. + +```json +{ + "PesterContext": { + "prefix": "Context-Pester", + "description": "Pester - Context block", + "body": [ + "Context \"${1:ContextName}\" {", + "\t${0:$TM_SELECTED_TEXT}", + "}" + ] + }, + "PesterContextIt": { + "prefix": "Context-It-Pester", + "description": "Pester - Context block with nested It block", + "body": [ + "Context \"${1:ContextName}\" {", + "\tIt \"${2:ItName}\" {", + "\t\t${3:${TM_SELECTED_TEXT:Assertion}}", + "\t}$0", + "}" + ] + }, + "PesterDescribeBlock": { + "prefix": "Describe-Pester", + "description": "Pester Describe block", + "body": [ + "Describe \"${1:DescribeName}\" {", + "\t${0:TM_SELECTED_TEXT}", + "}" + ] + }, + "PesterDescribeContextIt": { + "prefix": "Describe-Context-It-Pester", + "description": "Pester Describe block with nested Context & It blocks", + "body": [ + "Describe \"${1:DescribeName}\" {", + "\tContext \"${2:ContextName}\" {", + "\t\tIt \"${3:ItName}\" {", + "\t\t\t${4:${TM_SELECTED_TEXT:Assertion}}", + "\t\t}$0", + "\t}", + "}" + ] + }, + "PesterIt": { + "prefix": "It-Pester", + "description": "Pester - It block", + "body": [ + "It \"${1:ItName}\" {", + "\t${2:${TM_SELECTED_TEXT:Assertion}}", + "}$0" + ] + } +} +``` + +### PesterTestForMandatoryParameter + +Quickly create a Pester Test for existence of a mandatory parameter by @SQLDBAWithABeard. + +#### Snippet + +```json +"Pester for Mandatory Parameter": { + "prefix": "mandatoryParamPester", + "body": [ + "It \"${1:FunctionName} Should have a mandatory parameter ${2:ParameterName}\" {", + "\t(Get-Command ${1:FunctionName}).Parameters['${2:ParameterName}'].Attributes.Mandatory | Should -BeTrue", + "}" + ], + "description": "Pester Test for Parameter" +} +``` + +### PesterTestForParameter + +Quickly create a Pester Test for existence of a parameter by @SQLDBAWithABeard. + +#### Snippet + +```json +"Pester for Parameter": { + "prefix": "Param Pester", + "body": [ + "It \"${1:FunctionName} Should have a parameter ${2:ParameterName}\" {", + "\t(Get-Command ${1:FunctionName}).Parameters['${2:ParameterName}'].Count | Should -Be 1", + "}" + ], + "description": "Pester Test for Parameter" +} +``` + +### Send-MailMessage + +Add the Send-MailMessage cmdlet with the most common parameters in a hashtable for splatting, by @fullenw1. + +#### Snippet + +```json +"ex-Send-MailMessage": { + "prefix": "ex-Send-MailMessage", + "body": [ + "$$Params = @{", + " 'SmtpServer' = 'smtp.mycompany.com'", + " 'Port' = 25", + " 'Priority' = 'Normal'", + " 'From' = 'sender@mycompany.com'", + " 'To' = 'mainrecipient@mycompany.com'", + " 'Cc' = 'copyrecipient@mycompany.com'", + " 'Bcc' = 'hiddenrecipient@mycompany.com'", + " 'Subject' = 'Mail title'", + " 'Body' = 'This is the content of my mail'", + " 'BodyAsHtml' = $$false", + " 'Attachments' = 'c:\\MyFile.txt'", + "}", + "Send-MailMessage @Params" + ], + "description": "Send a mail message" +} +``` + +## Contributing + +To optimize snippet usability and discoverability for end users we will only ship snippets in the extension which we believe meet the following requirements: + +- Must be broadly applicable to most PowerShell extension users +- Must be substantially different from existing snippets or intellisense +- Must not violate any intellectual property rights + +If your snippet does not meet these requirements but would still be useful to customers we will include it in our list of [Awesome Community Snippets](https://github.com/PowerShell/vscode-powershell/blob/main/docs/community_snippets.md). Additionally, snippet creators can publish snippet libraries as standalone extensions in the [VSCode Marketplace](https://code.visualstudio.com/api/working-with-extensions/publishing-extension). + +If you'd like a snippet to be considered for addition to the list, [open a pull request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) with the following changes: + +### Table of contents + +You need to add an item to the table of contents. The addition should follow the *alpha ordering* of the list. +The ToC item template looks like this: + +```md +| [Name of snippet](link to header of your snippet) | _some short description_ | +``` + +An example looks like this (NOTE: all lowercase link): + +```md +| [PSCustomObject](#pscustomobject) | _A simple PSCustomObject_ | +``` + +which will show up in the ToC like this: + +| Snippet Name | Description | +|--------- | ---------| +| [PSCustomObject](#pscustomobject) | _A simple PSCustomObject_ | + +### Body + +You need to also add an item to the body in alpha order. The body item template looks like this: + + ### Name of snippet + + Enter your description here. It can be the same as the ToC or a longer version. + + #### Snippet + + ```json + { + "Put your":"snippet here", + "indent it":"properly" + } + ``` + +An example looks like this: + + ### PSCustomObject + + A simple PSCustomObject. + + #### Snippet + + ```json + "PSCustomObject": { + "prefix": "PSCustomObject", + "body": [ + "[PSCustomObject]@{", + "\t${1:Name} = ${2:Value}", + "}" + ], + "description": "Creates a PSCustomObject" + } + ``` + +which will show up in the body like this: + +### PSCustomObject + +A simple PSCustomObject. Note, this snippet ships with the PowerShell extension. + +#### Snippet + +```json +"PSCustomObject": { + "prefix": "PSCustomObject", + "body": [ + "[PSCustomObject]@{", + "\t${1:Name} = ${2:Value}", + "}" + ], + "description": "Creates a PSCustomObject" +} +``` diff --git a/docs/development.md b/docs/development.md index 15be7089ca..3caac3bb01 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,30 +1,185 @@ -# Working with the PowerShell extension code +# Development Instructions for the PowerShell Extension -## Building the code +## Development Setup -First, install the package dependencies: +1. [Fork and clone][fork] the [vscode-powershell repository](https://github.com/PowerShell/vscode-powershell). -``` -npm install -``` +1. [Fork and clone][fork] the [PowerShell Editor Services (PSES) repository](https://github.com/PowerShell/PowerShellEditorServices). + > The `vscode-powershell` folder and the `PowerShellEditorServices` folder should be next to each other on the file + > system. Code in `vscode-powershell` looks for PSES at `../PowerShellEditorServices` if you're building locally so + > PSES must be in that location. -Now you can compile the code: +1. Follow the [development instructions](https://github.com/PowerShell/PowerShellEditorServices#development) for + PowerShell Editor Services. **You will need to complete this step before proceeding**. -``` -npm run compile -``` +1. Install [Node.js](https://nodejs.org/en/) 18.x or higher. + +1. Install [Visual Studio Code](https://code.visualstudio.com). + Open the multi-root workspace file in this repo, `extension-dev.code-workspace`. + > This has a set of recommended extensions to install and provides tasks. + > The ESLint formatter will require you to install ESLint globally, using `npm install -g eslint`. + > Otherwise VS Code will erroneously complain that it isn't able to use it to format TypeScript files. + +1. (optional) Set `git config blame.ignoreRevsFile .git-blame-ignore-revs` to ignore formatting-related commits. + +[fork]: https://help.github.com/articles/fork-a-repo/ + +## Tracking Upstream Dependencies + +As a VS Code extension, we first rely on the `engine` field of `package.json` to +state the lowest version of VS Code we support. -After the initial compile, the source files will be watched and recompiled -when changes are saved. +When our `engine` field is updated the development dependency `@types/vscode` +must be updated to match. Note that it uses `~` (not `^`) so as to accept new +patches with `npm update` but not new minor versions. Then we check that version +of VS Code's own `package.json` file for their [`electron`][] dependency. The +major version of [Electron][] will tell us which [Node.js][] is included, which +dictates which version of Node.js the extension is eventually run with. This +lets us finally update our `@types/node` development dependency to match, our +developer machines if necessary, the CI and OneBranch pipeline tasks, and the +`.tsconfig` file. Note that the version of `@types/node` will not necessarily +exactly match the version of Node.js, but the major version should. -## Running the compiled code +[`electron`]: https://github.com/microsoft/vscode/blob/138f619c86f1199955d53b4166bef66ef252935c/package.json#L156 +[Electron]: https://releases.electronjs.org/release/v32.2.6 +[Node.js]: https://nodejs.org/en/download/package-manager -From a PowerShell or cmd.exe prompt, run the following command: +### Building the Code +#### From Visual Studio Code + +Press Ctrl+P and type `task build`. Explore the other provided tasks for helpful commands. + +#### From a PowerShell prompt + +```powershell +Invoke-Build Build ``` -code --extensionDevelopmentPath="c:\path\to\vscode-powershell" . + +Explore the `vscode-powershell.build.ps1` file for other build targets. + +### Launching the extension +First, ensure you have completed a build as instructed above, as the launch templates do not check some prerequisites for performance reasons. + +To debug the extension use one of the provided `Launch Extension` debug configurations. +1. `Launch Extension`: Launches the debugger using your personal profile settings. +2. `Temp Profile`: Launches VS Code with a temp profile that resets on every launch. Useful for "out of the box" environment testing. +3. `Isolated Profile`: Launches the debugger with a persistent debug profile specific to the extension, so you can preserve some settings or test certain prerequisites. + +All three templates use pre-launch tasks to build the code, and support automatic restart of the extension host on changes to the Extension source code. [Hot Reload](https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/) is also enabled for PowerShell Editor Services. + +> [!WARNING] +> There is a current limitation that, if you restart the extension/extension host or it is restarted due to a extension code change, the editor services attachment will be disconnected due to the PSES terminal being terminated, and you will either need to restart the debug session completely, or do a manual build of PSES and run the `Attach to Editor Services` debug launch manually. + +Try the `powershell.developer.editorServicesWaitForDebugger` setting to ensure that you are fully attached before the extension startup process continues. + +## Contributing Snippets + +For more information on contributing snippets please read our +[snippet requirements](https://github.com/PowerShell/vscode-powershell/blob/main/docs/community_snippets.md#contributing). + +## Creating a Release + +These are the current steps for creating a release for both the editor services +and the extension. Azure DevOps access is restricted to Microsoft employees and +is used to sign and validate the produced binaries before publishing on behalf +of Microsoft. Assume `origin` is GitHub and `ado` is Azure DevOps. + +```powershell +cd ./PowerShellEditorServices +git checkout -B release +./tools/updateVersion.ps1 -Version "4.0.0" -Changes "Major release!" +# Amend changelog as necessary +git push --force-with-lease origin +# Open, approve, and merge PR on GitHub +cd ../vscode-powershell +git checkout -B release +./tools/updateVersion.ps1 -Version "2024.4.0" -Changes "Major release!" +# Amend changelog as necessary +git push --force-with-lease origin +# Open, approve, and merge PR on GitHub +cd ../PowerShellEditorServices +git checkout main +git pull +git push ado HEAD:release +cd ../vscode-powershell +git checkout main +git pull +git push ado HEAD:release +# Download and test assets from draft GitHub Releases +# Publish releases, ensuring tag is at release commit in `main` +# Permit pipeline to publish to marketplace ``` - -If you allow the compiler to continue watching for file changes, you can use -the `Reload Window` command found in the command palette `(Ctrl+Shift+P)` -so that the new source files are loaded. + +If rolling from pre-release to release, do not change the version of PowerShell +Editor Services between a pre-release and the subsequent release! We only +need to release the extension. + +The Azure DevOps pipelines have to build off a PR merged to `main` for _reasons_, +hence that repo is a superset including all our commits plus signed PR merge commits. + +### Versioning + +For both our repositories we use Git tags in the form `vX.Y.Z` to mark the releases in the +codebase. We use the GitHub Release feature to create these tags. The ephemeral branch +`release` is used in the process of creating a release for each repository, primarily for +the Pull Requests and for Azure DevOps triggers. Once the release PRs are merged, the +branch is deleted until used again to prepare the next release. This branch _does not_ +mark any specific release, that is the point of the tags. + +For PowerShellEditor Services, we simply follow semantic versioning, e.g. +`vX.Y.Z`. We do not release previews frequently because this dependency is not +generally used directly: it's a library consumed by other projects which +themselves use pre-releases for beta testing. + +For the VS Code PowerShell Extension, our version follows `vYYYY.X.Z`, that is: current +year, minor version, and patch version. This is not semantic versioning because of issues +with how the VS Code marketplace and extension hosting API itself uses our version number. +We do not release on a chronological schedule: we release based on completed work. For +historical reasons we are stuck with the major version being year. + +Before releasing a stable version (a _release_) we should almost always first release a +preview of the same code, which is a _pre-release_. The exception to this is hotfix +releases where we need to push _only_ bug fixes out as soon as possible, and these should +be built off the last release's codebase (found from the Git tag). The pre-release is +uploaded to the marketplace using the `--pre-release` flag given to `vsce` (the CLI tool +used to do so). The previous separate "PowerShell Preview" extension has been deprecated +in favor of using the marketplace's support for [pre-releases][] on the one-and-only +extension. + +Because the marketplace does not actually understand Semantic Versioning pre-release tags +(the `-preview` suffix), the patch numbers need to increment continuously, but we append +`-preview` to _our_ version in the changelog and Git tags. When multiple pre-releases are +needed, the patch version is incremented (again because the marketplace ignores the +pre-release tag, we can't do `-alpha`, `-beta` etc.). The `preview` field in +the extension's manifest (the `package.json` file) is _always_ `false`, even for +pre-releases, because the marketplace takes the information from the latest release +inclusive of pre-releases, hence it was causing the one-and-only extension to look like it +was in preview. This is also why the icon no longer changes to the PowerShell Preview icon +for pre-releases. When they support pre-releases better (ideally that means supporting the +pre-release tags in full) we can revisit this. + +Furthermore, for releases, the minor version must be _even_ (like 0, 2, etc.) and for +pre-releases it must be _odd_ (like 1, 3, etc.), and an upcoming release's version must be +`n-1` of the pre-release which previews it. That is, release `v2024.0.0` is previewed in +the pre-release `v2024.1.0-preview`. This scheme is designed such that the "newest" (by version) +release is always a pre-release, so that the VS Code marketplace _always_ shows a +pre-release option. When we previously did this the other way around (incrementing the +release as `n+1` to the pre-release), every time we released, the pre-release option +(dropdown) in the marketplace would unfortunately disappear. + +[pre-releases]: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#prerelease-extensions + +For example, the date is August 23, 2023. The last release was in June, and its version +was `v2023.6.0`. Some significant work has been completed and we want to release the +extension, so the next release will be `v2023.8.0` (the minor version is `n+2` because it +must remain even, it only coincidentally matches the month). That means first we create a +pre-release with version `v2023.9.0-preview` (the minor version is `n+1` of the upcoming +release, and `-preview` was appended). After publishing, some issues were identified and +we decided we needed a second pre-release. Its version is `v2023.9.1-preview`. User +feedback hopefully indicates that the pre-release is working well, so to create a release +we will use the same code (but with an updated changelog etc.) and use version +`v2023.8.0`, the _next_ release since `v2023.6.0`. The version of PowerShell Editor +Services may update between pre-releases or releases, but must not change between a +pre-release and its subsequent release, as they should use the same code (which includes +dependencies). diff --git a/docs/preview_to_stable_changelog.md b/docs/preview_to_stable_changelog.md new file mode 100644 index 0000000000..efc73069b2 --- /dev/null +++ b/docs/preview_to_stable_changelog.md @@ -0,0 +1,363 @@ +# PowerShell Preview Extension Release History March 2020 + +This document shows the combined changes that were moved from the Preview extension to the stable extension as part of the March 2020 release. + +## Top Features + +- ✨ 📺 [vscode-PowerShell #2335](https://github.com/PowerShell/vscode-powershell/pull/2335) - + Add editor command `PowerShell: Enable/Disable ISE Mode` for ISE emulation in VS Code. +- ✨ 📟 [vscode-PowerShell #2316](https://github.com/PowerShell/vscode-PowerShell/pull/2316) - + Add `powershell.integratedConsole.forceClearScrollbackBuffer` setting to enable `Clear-Host` to clear scrollback buffer. +- 🚂 [PowerShellEditorServices #1056](https://github.com/PowerShell/PowerShellEditorServices/pull/1056) - + Re-architect PowerShell Editor Services to use the Omnisharp LSP platform. +- [PowerShellEditorServices #741](https://github.com/PowerShell/PowerShellEditorServices/pull/741) - + Migrate to netstandard2.0 and PSStandard +- [PowerShellEditorServices #672](https://github.com/PowerShell/PowerShellEditorServices/pull/672) - + PSReadLine integration (Thanks @SeeminglyScience!) + +## v2020.2.0 +### Thursday, February 20, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🐛📖 [vscode-PowerShell #2470](https://github.com/PowerShell/vscode-powershell/pull/2470) - + Fix incorrect reference to `New-ManifestModule` in documentation. (Thanks @rbleattler!) +- 🐛📺 [vscode-PowerShell #2469](https://github.com/PowerShell/vscode-powershell/pull/2469) - + Close other open pwsh instances when updating PowerShell. +- 🐛📟 [vscode-PowerShell #2434](https://github.com/powershell/vscode-powershell/pull/2437) - + Use a new VSCode API to hide the integrated terminal from the shell list + until debugging when `showOnStartup` is disabled. +- ✨🐢 [vscode-PowerShell #2445](https://github.com/PowerShell/vscode-powershell/pull/2445) - + Add `Run/Debug Pester tests` context menu options in the VSCode explorer + for Pester test files. (Thanks @bergmeister!) +- 🐛🐢 [vscode-PowerShell #2438](https://github.com/PowerShell/vscode-powershell/pull/2447/) - + Fixes test failures in Pester contexts not showing up in the Problems pane. (Thanks @tillig!) +- 🐛🔍 [vscode-PowerShell #2548](https://github.com/PowerShell/vscode-powershell/pull/2458) - + Show error message instead of hanging when temp debugging is used with an untitled file. +- 👷 [vscode-PowerShell #2465](https://github.com/PowerShell/vscode-powershell/pull/2465) - + Move macOS CI images to 10.14 (Thanks @bergmeister!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛📁 [vscode-PowerShell #2421](https://github.com/powershell/powershelleditorservices/pull/1161) - + Fix WorkspacePath so that references work with non-ASCII characters. +- 🐛📟 [vscode-PowerShell #2372](https://github.com/powershell/powershelleditorservices/pull/1162) - + Fix prompt behavior when debugging. +- 🐛🛫 [PowerShellEditorServices #1171](https://github.com/powershell/powershelleditorservices/pull/1171) - + Fix race condition where running multiple profiles caused errors. +- 🐛📟 [vscode-PowerShell #2420](https://github.com/powershell/powershelleditorservices/pull/1173) - + Fix an issue where pasting to a `Get-Credential` prompt in some Windows versions caused a crash. +- 🐛📟 [vscode-PowerShell #1790](https://github.com/powershell/powershelleditorservices/pull/1174) - + Fix an inconsistency where `Read-Host -Prompt 'prompt'` would return `$null` rather than empty string + when given no input. +- 🐛🔗 [PowerShellEditorServices #1177](https://github.com/powershell/powershelleditorservices/pull/1174) - + Fix an issue where untitled files did not work with CodeLens. +- ⚡️⏱️ [PowerShellEditorServices #1172](https://github.com/powershell/powershelleditorservices/pull/1172) - + Improve `async`/`await` and `Task` usage to reduce concurrency overhead and improve performance. +- 🐛📟 [PowerShellEditorServices #1178](https://github.com/powershell/powershelleditorservices/pull/1178) - + Improve PSReadLine experience where no new line is rendered in the console. +- ✨🔍 [PowerShellEditorServices #1119](https://github.com/powershell/powershelleditorservices/pull/1119) - + Enable new debugging APIs added in PowerShell 7, improving performance and fixing issues where + the debugger would hang or be unable to update breakpoints while scripts were running. +- 👷📟 [PowerShellEditorServices #1187](https://github.com/PowerShell/PowerShellEditorServices/pull/1187) - + Upgrade built-in PSReadLine to 2.0.0 GA. +- 🐛👮 [PowerShellEditorServices #1179](https://github.com/PowerShell/PowerShellEditorServices/pull/1179) - + Improve integration with PSScriptAnalyzer, improving performance, + fixing an error when PSScriptAnalyzer is not available, fix CodeActions not appearing on Windows, + fix an issue where the PSModulePath is reset by PSScriptAnalyzer opening new runspaces. +- 🚂 [PowerShellEditorServices #1183](https://github.com/PowerShell/PowerShellEditorServices/pull/1183) - + Close over public APIs not intended for external use and replace with new, async-friendly APIs. + +## v2020.1.0 +### Monday, January 13, 2020 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🛫 ✨ [vscode-powershell #2384](https://github.com/PowerShell/vscode-PowerShell/pull/2400) - + Add -Login startup option. +- 🛫 🐛 [vscode-powershell #2380](https://github.com/PowerShell/vscode-PowerShell/pull/2399) - + Make PowerShell names case insensitive for configuration. +- 🛫 📺 ✨ [vscode-powershell #2370](https://github.com/PowerShell/vscode-PowerShell/pull/2398) - + Add configuration to enable/disable banner. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 📺 [vscode-powershell #2405](https://github.com/PowerShell/PowerShellEditorServices/pull/1152) - + Add tooltip to completions ParameterValue. +- 🛫 🐛 [vscode-powershell #2393](https://github.com/PowerShell/PowerShellEditorServices/pull/1151) - + Probe netfx dir for deps. +- 🚂 ⏱️ 🐛 [vscode-powershell #2352](https://github.com/PowerShell/PowerShellEditorServices/pull/1149) - + Fix lock up that occurs when WinForms is executed on the pipeline thread. +- 💭 🐛 [vscode-powershell #2402](https://github.com/PowerShell/PowerShellEditorServices/pull/1150) - + Fix temp debugging after it broke bringing in $psEditor. +- 🧠 🐛 [vscode-powershell #2324](https://github.com/PowerShell/PowerShellEditorServices/pull/1143) - + Fix unicode character uri bug. +- 🛫 📺 ✨ [vscode-powershell #2370](https://github.com/PowerShell/PowerShellEditorServices/pull/1141) - + Make startup banner simpler. +- [vscode-powershell #2386](https://github.com/PowerShell/PowerShellEditorServices/pull/1140) - + Fix uncaught exception when SafeToString returns null. (Thanks @jborean93!) +- 🔗 🐛 [vscode-powershell #2374](https://github.com/PowerShell/PowerShellEditorServices/pull/1139) - + Simplify logic of determining Reference definition. +- 🛫 🐛 [vscode-powershell #2379](https://github.com/PowerShell/PowerShellEditorServices/pull/1138) - + Use -Option AllScope to fix Windows PowerShell error. + +## v2019.12.0 + +### Wednesday, December 11, 2019 + +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨ 📺 [vscode-PowerShell #2335](https://github.com/PowerShell/vscode-powershell/pull/2335) - + Add editor command `PowerShell: Enable/Disable ISE Mode` for ISE emulation in VS Code. +- ⚡️ 🛫 [vscode-PowerShell #2348](https://github.com/PowerShell/vscode-PowerShell/pull/2348) - + Start EditorServices without start script. +- ✨ 📟 [vscode-PowerShell #2316](https://github.com/PowerShell/vscode-PowerShell/pull/2316) - + Add `powershell.integratedConsole.forceClearScrollbackBuffer` setting to enable `Clear-Host` to clear scrollback buffer. +- 🐛 📺 [vscode-PowerShell #2325](https://github.com/PowerShell/vscode-PowerShell/pull/2325) - + Fix update PowerShell feature on windows. +- 🔧 📁 🐛 [vscode-powershell #2099](https://github.com/PowerShell/vscode-PowerShell/pull/2304) - + Use `powerShellDefaultVersion` everywhere and stop using `powerShellExePath`. +- 🐛 📺 [vscode-PowerShell #2294](https://github.com/PowerShell/vscode-PowerShell/pull/2294) - + Buttons show up for untitled files. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 👷 📟 [PowerShellEditorServices #1129](https://github.com/PowerShell/PowerShellEditorServices/pull/1129) - + Update PSReadLine to 2.0.0-rc1 in modules.json. +- 🛫 🐛 ⚡️ [vscode-powershell #2292](https://github.com/PowerShell/PowerShellEditorServices/pull/1118) - + Isolate PSES dependencies from PowerShell on load + make PSES a pure binary module. +- ✨ 📟 [PowerShellEditorServices #1108](https://github.com/PowerShell/PowerShellEditorServices/pull/1108) - + Clear the terminal via the LSP message `editor/clearTerminal`. +- 🔍 🐛 [vscode-powershell #2319](https://github.com/PowerShell/PowerShellEditorServices/pull/1117) - + Run one invocation per SetBreakpoints request. (Thanks @SeeminglyScience!) +- 🐛 [PowerShellEditorServices #1114](https://github.com/PowerShell/PowerShellEditorServices/pull/1114) - + Fix `Import-EditorCommand -Module`. (Thanks @sk82jack!) +- 🐛 🔍 [PowerShellEditorServices #1112](https://github.com/PowerShell/PowerShellEditorServices/pull/1112) - + Fix breakpoint setting deadlock. +- 🔗 🐛 [vscode-powershell #2306](https://github.com/PowerShell/PowerShellEditorServices/pull/1110) - + Fix references on Windows due to bad WorkspacePath. +- ✨ 👷 [PowerShellEditorServices #993](https://github.com/PowerShell/PowerShellEditorServices/pull/993) - + Add devcontainer support for building in container. (Thanks @bergmeister!) +- 🛫 🐛 [vscode-powershell #2311](https://github.com/PowerShell/PowerShellEditorServices/pull/1107) - + Protect against no RootUri (no open workspace). +- 🐛 📟 [vscode-powershell #2274](https://github.com/PowerShell/PowerShellEditorServices/pull/1092) - + Fix '@' appearing in console. +- 👮‍ 🐛 [vscode-powershell #2288](https://github.com/PowerShell/PowerShellEditorServices/pull/1094) - + Use RootUri.LocalPath for workspace path. +- 👮‍ 🔗 🐛 [vscode-powershell #2290](https://github.com/PowerShell/PowerShellEditorServices/pull/1098) - + Fix diagnostics not showing in untitled files and now also show CodeLens. +- 🔍 🐛 [vscode-powershell #1850](https://github.com/PowerShell/PowerShellEditorServices/pull/1097) - + Fixes no prompt showing up when debugging. +- 🚂 📺 🐛 [vscode-powershell #2284](https://github.com/PowerShell/PowerShellEditorServices/pull/1096) - + Fix running indicator by ignoring PSRL aborts. + +## v2019.11.0 +### Friday, November 1, 2019 + +##### Special Note +In this release of the preview extension, +we've merged significant architectural work into PowerShell Editor Services. +After several months of work, PSES now uses the Omnisharp LSP library +to handle Language Server Protocol interaction instead of rolling its own, +allowing PSES to concentrate on being a good PowerShell backend. +We hope you'll see increased performance and stability in this release. +As always, [please let us know if you find any issues](https://github.com/PowerShell/vscode-powershell/issues/new/choose). + +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- 🔧 [vscode-PowerShell #2262](https://github.com/PowerShell/vscode-PowerShell/pull/2262) - + Introduce `powershell.integratedConsole.useLegacyReadline` setting disable PSReadLine. +- 🚂 [vscode-PowerShell #2226](https://github.com/PowerShell/vscode-PowerShell/pull/2226) - + Changes needed for Omnisharp migration of PowerShellEditorServices. + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🐛 [PowerShellEditorServices #1080](https://github.com/PowerShell/PowerShellEditorServices/pull/1080) - + Remove extra newline in GetComment feature. +- 🐛 [PowerShellEditorServices #1079](https://github.com/PowerShell/PowerShellEditorServices/pull/1079) - + Fix duplicate diagnostics caused by DidChange handler. +- 🔧 [PowerShellEditorServices #1076](https://github.com/PowerShell/PowerShellEditorServices/pull/1076) - + Graduate PSReadLine feature and add UseLegacyReadLine. +- ⚙️ [PowerShellEditorServices #1075](https://github.com/PowerShell/PowerShellEditorServices/pull/1075) - + Lock OmniSharp dependencies to v0.14.0. (Thanks @mholo65!) +- 🐛 [PowerShellEditorServices #1073](https://github.com/PowerShell/PowerShellEditorServices/pull/1073) - + Fix prerelease version discovery and fix omnisharp change. +- 🐛 [PowerShellEditorServices #1065](https://github.com/PowerShell/PowerShellEditorServices/pull/1065) - + Fix TEMP debugging. +- 🐛 [vscode-powershell #1753](https://github.com/PowerShell/PowerShellEditorServices/pull/1072) - + Override PSRL ReadKey on Windows as well. +- 🚂 [PowerShellEditorServices #1056](https://github.com/PowerShell/PowerShellEditorServices/pull/1056) - + Re-architect PowerShell Editor Services to use the Omnisharp LSP platform. + +## v2019.5.0 +### Wednesday, May 22, 2019 +#### [vscode-PowerShell](https://github.com/PowerShell/vscode-PowerShell) + +- ✨ [vscode-PowerShell #1945](https://github.com/PowerShell/vscode-PowerShell/pull/1945) - + Edit snippets to support $TM_SELECTED_TEXT (Thanks @travis-c-lagrone!) +- 👷 [vscode-PowerShell #1942](https://github.com/PowerShell/vscode-PowerShell/pull/1942) - + Stop supporting 6.0 +- ✨ [vscode-PowerShell #1928](https://github.com/PowerShell/vscode-PowerShell/pull/1928) - + Add RunCode command for CodeLens providers +- 🐛 [vscode-PowerShell #1927](https://github.com/PowerShell/vscode-PowerShell/pull/1927) - + Fix change session by moving to async/await promise +- 🐛 [vscode-PowerShell #1925](https://github.com/PowerShell/vscode-PowerShell/pull/1925) - + Fix error in HtmlContentView.ShowContent when no JS/CSS provided (Thanks @rkeithhill!) +- 📖 [vscode-PowerShell #1900](https://github.com/PowerShell/vscode-PowerShell/pull/1900) - + Small update to Azure Data Studio marketplace README (Thanks @SQLvariant!) +- 💻 [vscode-PowerShell #1871](https://github.com/PowerShell/vscode-PowerShell/pull/1871) - + Change CI to use Azure Pipelines +- 🐛 [vscode-PowerShell #1867](https://github.com/PowerShell/vscode-PowerShell/pull/1867) - + Change whitespace settings to camelCase +- 🐛 [vscode-PowerShell #1852](https://github.com/PowerShell/vscode-PowerShell/pull/1852) - + Turn `powershell.codeformatting.useCorrectCasing` setting off by default until PSScriptAnalyzer issues are fixed (Thanks @bergmeister!) +- 🐛 [vscode-powershell #1822](https://github.com/PowerShell/vscode-PowerShell/pull/1838) - + Set featureFlag default to null so that it can be resolved by settings +- 🐛 [vscode-PowerShell #1837](https://github.com/PowerShell/vscode-PowerShell/pull/1837) - + Don't use -EncodedCommand to start PowerShell on Windows +- 🐛 [vscode-PowerShell #1825](https://github.com/PowerShell/vscode-PowerShell/pull/1825) - + Switch to current lowercase names for powershell and mdlint extensions (Thanks @rkeithhill!) +- 👷 [vscode-PowerShell #1823](https://github.com/PowerShell/vscode-PowerShell/pull/1823) - + Update to official TSLint extension in extensions.json, old version deprecated (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices) + +- 🚨 [PowerShellEditorServices #944](https://github.com/PowerShell/PowerShellEditorServices/pull/944) - + Add integration testing module with simple tests to verify PSES starts and stops +- 🐛 [PowerShellEditorServices #954](https://github.com/PowerShell/PowerShellEditorServices/pull/955) - + Ensure NamedPipeServerStream is assigned in Windows PowerShell +- ✨ [PowerShellEditorServices #952](https://github.com/PowerShell/PowerShellEditorServices/pull/952) - + Update to PSReadLine 2.0.0-beta4 +- ✨ [PowerShellEditorServices #877](https://github.com/PowerShell/PowerShellEditorServices/pull/877) - + Add filtering for CodeLens and References (Thanks @glennsarti!) +- 👷 [PowerShellEditorServices #878](https://github.com/PowerShell/PowerShellEditorServices/pull/878) - + Remove native named pipes implementation +- 🐛 [PowerShellEditorServices #946](https://github.com/PowerShell/PowerShellEditorServices/pull/946) - + Rename to use async +- 👷 [PowerShellEditorServices #943](https://github.com/PowerShell/PowerShellEditorServices/pull/943) - + Improvements to the log parsing module (Thanks @rkeithhill!) +- 🐛 [PowerShellEditorServices #908](https://github.com/PowerShell/PowerShellEditorServices/pull/908) - + Fix issue with reference code lens not working with UNC paths (Thanks @rkeithhill!) +- 🐛 [vscode-powershell #1571](https://github.com/PowerShell/PowerShellEditorServices/pull/911) - + Fix faulty netfx check +- 🐛 [PowerShellEditorServices #906](https://github.com/PowerShell/PowerShellEditorServices/pull/906) - + Fix New-EditorFile with no folder or no files open +- ✨ [vscode-powershell #1398](https://github.com/PowerShell/PowerShellEditorServices/pull/902) - + Improve path auto-completion (Thanks @rkeithhill!) +- 🐛 [PowerShellEditorServices #910](https://github.com/PowerShell/PowerShellEditorServices/pull/910) - + Fix UseCorrectCasing to be actually configurable via `powershell.codeFormatting.useCorrectCasing` (Thanks @bergmeister!) +- 👷 [PowerShellEditorServices #909](https://github.com/PowerShell/PowerShellEditorServices/pull/909) - + Use global.json to pin .Net Core SDK version and update it from 2.1.402 to 2.1.602 (Thanks @bergmeister!) +- 👷 [PowerShellEditorServices #903](https://github.com/PowerShell/PowerShellEditorServices/pull/903) - + Move temp folder into repo to avoid state that causes build errors from time to time when rebuilding locally (and packages have updated) (Thanks @bergmeister!) +- 💻 [PowerShellEditorServices #904](https://github.com/PowerShell/PowerShellEditorServices/pull/904) - + Add initial credscan configuation ymls for CI +- 🐛 [PowerShellEditorServices #901](https://github.com/PowerShell/PowerShellEditorServices/pull/901) - + Switch to current lowercase names for powershell and mdlint exts (Thanks @rkeithhill!) + +## v2.0.0-preview.3 +### Wednesday, April 10, 2019 +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1838](https://github.com/PowerShell/vscode-PowerShell/pull/1838) - + Set PSReadLine featureFlag default to null so that it can be resolved by settings +- [vscode-PowerShell #1825](https://github.com/PowerShell/vscode-PowerShell/pull/1825) - + Switch to current lowercase names for powershell and mdlint recommended extensions (Thanks @rkeithhill!) +- [vscode-PowerShell #1823](https://github.com/PowerShell/vscode-PowerShell/pull/1823) - + Update to official TSLint ext in extensions.json, old version deprecated (Thanks @rkeithhill!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #909](https://github.com/PowerShell/PowerShellEditorServices/pull/909) - + Use global.json to pin .Net Core SDK version and update it from 2.1.402 to 2.1.602 (Thanks @bergmeister!) +- [PowerShellEditorServices #903](https://github.com/PowerShell/PowerShellEditorServices/pull/903) - + Move temp folder into repo to avoid state that causes build errors from time to time when rebuilding locally (and packages have updated) (Thanks @bergmeister!) + +## v2.0.0-preview.2 +### Friday, March 29, 2019 + +### Highlights + +* `Write-Progress` work in the integrated console ⏰ +* Support for [PSScriptAnalyzer 1.18](https://github.com/PowerShell/PSScriptAnalyzer/releases/tag/1.18.0) 📝 +* The ability to debug any runspace in any process 🔎 +* PSReadLine enabled by default on Windows 🎨 +* (Bug fix!) You can open untitled workspaces/folders again! 🐛☠️ + +There are a lot more goodies in this version. Checkout the changelog below! + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1794](https://github.com/PowerShell/vscode-PowerShell/pull/1794) - + Make PSReadLine default on Windows +- [vscode-PowerShell #1741](https://github.com/PowerShell/vscode-PowerShell/pull/1741) - + Update build to clear node modules directory (Thanks @corbob!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #858](https://github.com/PowerShell/PowerShellEditorServices/pull/858) - + Fix XUnit warnings that better assertion operators should be used. (Thanks @bergmeister!) +- [PowerShellEditorServices #859](https://github.com/PowerShell/PowerShellEditorServices/pull/859) - + Upgrade PowerShellStandard.Library, PowerShell.SDK, NET.Test.SDK and Serilog NuGet packages to latest released version and enable AppVeyor build on any branch (Thanks @bergmeister!) + +## v2.0.0-preview.1 +### Wednesday, January 23, 2019 + +#### Preview builds of the PowerShell extension are now available in VSCode + +We are excited to announce the PowerShell Preview extension in the VSCode marketplace! +The PowerShell Preview extension allows users on Windows PowerShell 5.1 and PowerShell Core 6 to get and test the latest updates +to the PowerShell extension and comes with some exciting features. + +The PowerShell Preview extension is a substitute for the PowerShell extension so +both the PowerShell extension and the PowerShell Preview extension should not be enabled at the same time. + +By having a preview channel, in addition to our existing stable channel, we can get new features out faster and get feedback faster from you, the users. + +##### How to Get/Use the PowerShell Preview extension + +If you dont already have VSCode, start [here](https://code.visualstudio.com/Docs/setup/setup-overview). + +Once you have VSCode open, click `Clt+Shift+X` to open the extensions marketplace. +Next, type `PowerShell Preview` in the search bar. +Click `Install` on the `PowerShell Preview` page. +Finally, click `Reload` in order to refresh VSCode. + +If you already have the PowerShell extension, please disable it to use the Powershell Preview extension. +To disable the PowerShell extension, find it in the Extensions sidebar view, specifically under the list of Enabled extensions, +Right-click on the PowerShell extension and select `Disable`. +Please note that it is important to only have either the PowerShell extension or the PowerShell Preview extension enabled at one time. +![How to Disable](https://github.com/PowerShell/powershell.github.io/blob/master/PowerShell-Blog/Images/disable-extension.jpg) + +#### What the first preview contains + +The v2.0.0-preview.1 version of the extension is built on .NET Standard +(enabling support for both Windows PowerShell and PowerShell Core from one assembly) + +It also contains PSReadLine support in the integrated console for Windows behind a feature flag. +PSReadLine provides a consistent and rich interactive experience, +including syntax coloring and multi-line editing and history, in the PowerShell console, in Cloud Shell, +and now in VSCode terminal. For more information on the benefits of PSReadLine, +check out their [documentation](https://docs.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline?view=powershell-6). + +HUGE thanks to @SeeminglyScience for all his amazing work getting PSReadLine working in PowerShell Editor Services! + +#### Breaking Changes + +As stated above, this version of the PowerShell extension only works with Windows PowerShell versions 5.1 and PowerShell Core 6. + +#### [vscode-powershell](https://github.com/powershell/vscode-powershell) + +- [vscode-PowerShell #1587](https://github.com/PowerShell/vscode-PowerShell/pull/1587) - + Removed ShowOnlineHelp Command (Thanks @corbob!) + +#### [PowerShellEditorServices](https://github.com/powershell/PowerShellEditorServices) + +- [PowerShellEditorServices #792](https://github.com/PowerShell/PowerShellEditorServices/pull/792) - + Add Async suffix to async methods (Thanks @dee-see!) +- [PowerShellEditorServices #775](https://github.com/PowerShell/PowerShellEditorServices/pull/775) - + Removed ShowOnlineHelp Message (Thanks @corbob!) +- [PowerShellEditorServices #769](https://github.com/PowerShell/PowerShellEditorServices/pull/769) - + Set Runspaces to use STA when running in Windows PowerShell +- [PowerShellEditorServices #741](https://github.com/PowerShell/PowerShellEditorServices/pull/741) - + Migrate to netstandard2.0 and PSStandard +- [PowerShellEditorServices #672](https://github.com/PowerShell/PowerShellEditorServices/pull/672) - + PSReadLine integration (Thanks @SeeminglyScience!) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000000..4c2b6195dd --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,435 @@ +# Troubleshooting PowerShell Extension Issues + +This document contains troubleshooting steps for commonly reported issues when using the +[PowerShell Extension][] for Visual Studio Code. + +## How do I change the PowerShell version? + +Starting VS Code 1.65, extensions now use the [language status item API][] instead of +manually adding a button to the status bar. That means the PowerShell icon button in the +status bar now exists under the language status menu, which looks like: `{}`. You can then +pin the icon back to the status bar by hovering over that menu and clicking the pin +button. The PowerShell icon will show you the current session's version, and clicking it +will let you change to another session. The language status icon will only appear when the +active editor's language mode is PowerShell. + +### Using Windows PowerShell 5.1 + +While we _highly encourage_ the use of [PowerShell 7.4 LTS][], if you must use Windows +PowerShell 5.1 we attempt to support it on a best-effort basis. Unfortunately, being two +major versions behind and in maintenance mode, Windows PowerShell is missing many of the +bug fixes and APIs we use to make the extension experience great. So please, if you can, +use PowerShell Core. That said, when using Windows PowerShell on older versions of the +Windows operating system, if the extension is failing to start (e.g. [#2571][]), try +installing [WMF 5.1][] and [.NET Framework 4.8][dotnet-framework]. + +## How do I debug my PowerShell script? + +This topic is best covered in the "Debugging PowerShell Script in Visual Studio Code" +Scripting Guys blog posts (thanks community!): + +* [Part 1](https://blogs.technet.microsoft.com/heyscriptingguy/2017/02/06/debugging-powershell-script-in-visual-studio-code-part-1/) +* [Part 2](https://blogs.technet.microsoft.com/heyscriptingguy/2017/02/13/debugging-powershell-script-in-visual-studio-code-part-2/) + +## Script analysis is reporting false errors + +Script analysis is provided by the [PSScriptAnalyzer][] project on GitHub. If the warning +message starts with `[PSScriptAnalyzer]` or if you are getting faulty script diagnostics +(red and green squiggly lines under PowerShell in scripts) please [open an issue there][]. + +## Completions aren't appearing + +First, please ensure that the extension itself has properly started. Do this by opening +the PowerShell Extension Terminal and checking the value of the variable `$psEditor`, +it should return a version and other fields. If it does not, you're probably in a +different "PowerShell" terminal in VS Code, and not the PowerShell Extension Terminal. +So please open a bug about your extension failing to start instead. + +If the extension _is_ started and the Extension Terminal functional, completions should appear! Please +double-check that your `editor.suggest.showFunctions` VS Code setting is `true`, as +setting it to `false` _will_ disable completions (from all extensions). You may also want +to check other related settings under "Text Editor -> Suggestions" in VS Code. + +## Double-click isn't selecting the whole variable + +VS Code provides a default set of word separators, that is, characters that split words +and so affect double-click selections. The editor's defaults include `-`, however we +exclude `-` for PowerShell documents because unlike programming languages that use +`CamelCase` or `snake_case`, PowerShell uses a `Verb-Noun` style where dashes are part of +many symbol names (like underscores in other languages). So by excluding it we configure +VS Code to treat `Verb-Noun` as one symbol/word, which matches what the extension +semantically highlights when the cursor is placed within it. + +Users may also wish to set VS Code's integrated terminal's word separators (a separate +setting) to exclude `-` to mirror the behavior in the terminal. This will apply to _all_ +terminals, not just PowerShell terminals. + +```json +"terminal.integrated.wordSeparators": " ()[]{}',\"`─" +``` + +Different users have a variety of different preferences around these word selection +settings and you can easily configure your own [word separators][] in VS Code's settings. + +To revert this behavior, add the following entry to the VS Code's `settings.json`: + +```json +"[powershell]": { + "editor.wordSeparators": "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?" +} +``` + +This will cause `-` to register as a word boundary, meaning for example on the `G` in +`Get-Process` will only select `Get` rather than the verb and noun `Get-Process`. + +## Problems with syntax highlighting + +PowerShell syntax highlighting is performed in combination by the [PowerShell Extension][] +(semantic highlighting) and [Editor Syntax][]. Syntax highlighting for VS Code, Atom, +SublimeText and even GitHub is provided by the [Editor Syntax][] repository on GitHub. + +We introduced [Semantic Highlighting][] in [v2021.2.2][], a feature that applies tokenized +colors at a layer above [Editor Syntax][]. However, after [community feedback][#3221] and +multiple bug reports (including colors changing unexpectedly and [randomly][#3295]), we +have decided to disable it by default. + +To enable semantic highlighting and use this "experimental" feature, set: + +```json +"[powershell]": { + "editor.semanticHighlighting.enabled": true +} +``` + +If you enable it, you can customize the colors used for the various tokens. See [#3221][] +for more info and to leave suggestions. + +If it is disabled and your issue remains, then please open those syntax highlighting +issues there in [Editor Syntax][]. + +## Windows aren't appearing + +Due to a known issue in [Electron][], windows spawned by VS Code (such as those for +`Get-Credential`, `Connect-MsolService`, `Connect-AzAccount`, `Connect-AzureAd`, etc.) do +not appear above VS Code. Use Alt+Tab on Windows or +Cmd+Tab on macOS to switch to the other window. + +## Visual Studio Code is not working like the ISE + +The [PowerShell Extension][] does not aim to perfectly recreate the experience of the +PowerShell ISE. However, we do want to support compatibility whenever possible to do so +without breaking existing functionality. + +Please see the [ISE compatibility doc][] for ways to increase VS Code's similarity. + +Bear in mind that many of the UI/UX aspects of VS Code are driven by VS Code itself and +can't be changed by the extension. The VS Code maintainers are quite reasonable though, +and you can ask for new features [in their repository](https://github.com/Microsoft/vscode). + +## Known issues in the extension + +* "CorruptZip: end of central directory record signature not found" when installing the + extension, [#4474][]. + + * Unfortunately it appears that a common corporate VPN with a firewall by Palo Alto is + disrupting the download of the extension binary from the VS Code marketplace. Please + reach out to your network administrators about this. + +* "The Language Service could not be started" but it does start with the x86 version of + PowerShell. + + * Do you use Avecto / BeyondSoft? We've received reports that Avecto, BeyondSoft and + other privilege management software dramatically slow down the start up of Windows + PowerShell x64. Please give the privilege management software feedback. + +* `Write-Output` is broken in Windows PowerShell 5.1, [#3991][]. + + * We seem to have recently narrowed this down! If `Start-Transcript` has been called + within the Extension Terminal, say in your PowerShell profile, this will eventually + cause output to no longer appear. Please try removing the call to `Start-Transcript` + and restarting the extension. We are investigating a fix. + +* Variable renaming doesn't work as expected, [#261][]. + + * PowerShell's usage of [dynamic scope][] rather than [lexical scope][] makes it + [formally undecidable][] to statically rename variables correctly (the only way to + know for sure which `$x`s refer to the same variable is to run the PowerShell script). + However, like with many features, we attempt a best effort. + +* `$PSScriptRoot` is not populated when running a code block (via F8), [#633][]. + + * This is by design. The value of `$PSScriptRoot` is only populated by PowerShell when + the caller is a script. Since F8 or "Run Selection" is essentially + copy-pasting the selection into the terminal, it's behavior is the same as if you the + user pasted it. That is, it's a block of code and not a script file, and therefore + there is no relevant context to populate `$PSScriptRoot`. + +* Completions don't cycle when Tab is pressed like in the ISE, [#25][]. + + * Use the tab completion settings recommended in the [ISE compatibility doc][]. + +* My command that opens a dialog does nothing, [#410 (comment)][]. + + * Check that the dialog hasn't opened behind VS Code. This is a known issue in + [Electron][], the framework used by VS Code. + +* Document formatting takes a long time, [#984][]. + + * Document formatting is provided by [PSScriptAnalyzer][], but there may be + opportunities to improve our integration with it in the extension too. + +* PSReadLine throws an error ever so often, [#3701][]. + + * This is a known issue due to the PowerShell eventing framework running registered + `OnIdle` events outside of PowerShell Editor Service's dedicated PowerShell execution + pipeline. Until we can disable event registration, you will need to avoid registering + events in the first place. + + * A known work around includes unregistering from this event. `Get-EventSubscriber + -Force -SourceIdentifier PowerShell.OnIdle -EA 0 | Unregister-Event -Force` can be run + manually (or added to your profile) to avoid this bug. + + * Also see: [PowerShell Editor Services #1591](https://github.com/PowerShell/PowerShellEditorServices/issues/1591), + [PSReadLine #3091](https://github.com/PowerShell/PSReadLine/issues/3091), + and [Azure PowerShell #16585](https://github.com/Azure/azure-powershell/issues/16586). + +## Reporting an issue + +If you experience a problem with the PowerShell Extension: + +1. Search through [existing issues][] on GitHub. + + In some circumstances, an issue may already be closed due to a fix being merged but not + yet released - so be sure to quickly check closed issues as well. + +2. Most features are provided by the client-agnostic [PowerShell Editor Services][] + backend project that the extension leverages, so it's also worth a [look there][]. + +3. If you don't see the issue you're experiencing, please [open a new issue][]. + +## Opening a new issue + +If you experience an issue with the PowerShell Extension and can't find an existing issue +for it, [open a new issue][]. + +You can also open an issue directly from VS Code by entering the [Command Palette][] with +Ctrl+Shift+P +(Cmd+Shift+P on macOS) and running the `PowerShell: +Upload Bug Report to GitHub` command. + +When opening an issue, keep in mind: + +* The fastest way to fixing a bug is reproducing it, and reproducing it + is easier with [more information][]. + +* The issue templates are designed to help you provide all the information needed to solve + your issue, please fill out the entire questionnaire. + +* As Open Source Software the [PowerShell Extension][] thrives on the contributions of + community members! If you're interested in [tackling an issue][], we love accepting + contributions and will help you at every step. + +## Reproducing the issue + +To fix the issue, we need to be able to reproduce it. To do that, we need: + +* A small/minimal script or sequence of user steps that result in the problem occurring. +* A description of the behavior you are expecting. +* A description of the actual behavior that occurs. + +In some cases, a GIF of the issue occurring is also very helpful. + +When you [open a new issue][], the GitHub issue template will have sections to guide you +through providing all of this information as well as environment information discussed +below. + +## Providing information about your environment + +For solving most issues, the following information is important to provide: + +### Logs + +Logs provide context for what was happening when the issue occurred. **You should browse +your logs for any sensitive information you would not like to share online!** + +* Before sending through logs, try and reproduce the issue with **log level set to + Trace**. You can set this in the [VS Code Settings][] + (Ctrl+,) with: + + ```json + "powershell.developer.editorServicesLogLevel": "Trace" + ``` + +* After you have captured the issue with the log level turned up, you may want to return + it (since verbose logging can use disk space): + + ```json + "powershell.developer.editorServicesLogLevel": "Normal" + ``` + +* Logs are located at: + * Unix: `~/.config/Code/User/globalStorage/ms-vscode.powershell/logs`. + * Windows: `%APPDATA%\Code\User\globalStorage\ms-vscode.powershell\logs` + +* In VS Code you can open and read the logs directly from the [Command Palette][] + (Ctrl+Shift+P) with `PowerShell: Open PowerShell Extension Logs Folder`. + + > NOTE: Don't forget to also attach the [Language Server Protocol payload + > logs](#provide-language-server-protocol-payload-logs)! + +* You can attach your logs to an issue by zipping them and dragging and dropping them onto + your open issue description in the browser. + +* If you prefer to share your logs privately, you can send them to + . **Please still open an issue though so we can track + the work, and reference it in your email.** + +#### Provide Language Server Protocol payload logs + +A lot of the features of the PowerShell extension actually come from Visual Studio Code directly interacting with the [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) process via a [Language Server Protocol client](https://code.visualstudio.com/api/language-extensions/language-server-extension-guide#logging-support-for-language-server). +In some cases, getting to the bottom of a bug will require looking at the payloads of +these messages. To enable viewing these messages: + +* Add the following setting to your settings file: + + ```json + "powershell.trace.server":"verbose" + ``` + +* Restart VS Code and reproduce the issue. + +* Go into the "Output" panel (Ctrl+Shift+U or + Cmd+Shift+U). + +* In the drop down on the right, select "PowerShell Editor Services Client". + +* Copy the entire contents of the Output panel and paste it into the GitHub issue in the + browser. At this point, you may delete the setting if you want. + +* Again, if you prefer to share your logs privately, you can send them to + . **Please still open an issue though so we can track + the work, and reference it in your email.** + +### Visual Studio Code version + +[Your VS Code version][] can be obtained from the Extension Terminal or any terminal: + +```powershell +code --version +``` + +If you are using VS Code Insiders, substitute `code-insiders` for `code`. + +You should get an output like: + +```text +1.57.1 +507ce72a4466fbb27b715c3722558bb15afa9f48 +arm64 +``` + +If VS Code is not on your path, you will get a message like: + +```text +code: The term 'code' is not recognized as the name of a cmdlet, ... +``` + +In this case, use the file menu in VS Code and choose `Help` > `About` (or `Code` > `About +Visual Studio Code` on macOS) to get version information. + +### PowerShell extension version + +[Your installed PowerShell Extension version][] can similarly be found with: + +```powershell +code --list-extensions --show-versions | Select-String powershell +``` + +You should get an output like: + +```text +ms-vscode.powershell@2021.8.0 +``` + +If VS Code isn't on your path, use the [Command Palette][] +(Ctrl+Shift+P) to run `Extensions: Show Installed +Extensions` and list your extensions. + +### Editor Services version + +To get the [PowerShell Editor Services][] version, in the Extension Terminal, enter: + +```powershell +> $psEditor.EditorServicesVersion +Major Minor Build Revision +----- ----- ----- -------- +1 8 4 0 +``` + +### PowerShell version table + +You can get [your PowerShell version table][] from the Extension Terminal through the +variable `$PSVersionTable`: + +```powershell +PS> $PSVersionTable + +Name Value +---- ----- +PSVersion 7.1.3 +PSEdition Core +GitCommitId 7.1.3 +OS Darwin 20.4.0 Darwin Kernel +Platform Unix +PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} +PSRemotingProtocolVersion 2.3 +SerializationVersion 1.1.0.1 +WSManStackVersion 3.0 +``` + +### Operating system information + +* Windows: all needed information should already be in the `$PSVersionTable`. +* macOS: your macOS version (e.g. High Sierra 10.13.6). +* Linux: Use `uname -a` and and `lsb_release -a`. + +[Editor Syntax]: https://github.com/PowerShell/EditorSyntax +[PowerShell Editor Services]: https://github.com/PowerShell/PowerShellEditorServices +[PowerShell Extension]: https://github.com/PowerShell/vscode-powershell/ +[PSScriptAnalyzer]: https://github.com/PowerShell/PSScriptAnalyzer + +[Command Palette]: https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette +[dynamic scope]: http://ig2600.blogspot.com/2010/01/powershell-is-dynamically-scoped-and.html +[Electron]: https://github.com/Microsoft/vscode/issues/42356 +[existing issues]: https://github.com/PowerShell/vscode-powershell/issues +[formally undecidable]: https://en.wikipedia.org/wiki/Undecidable_problem +[ISE compatibility doc]: https://docs.microsoft.com/powershell/scripting/components/vscode/how-to-replicate-the-ise-experience-in-vscode +[language status item API]: https://code.visualstudio.com/updates/v1_65#_language-status-items +[lexical scope]: https://stackoverflow.com/questions/1047454/what-is-lexical-scope +[look there]: https://github.com/PowerShell/PowerShellEditorServices/issues +[more information]: #providing-information-about-your-environment +[open a new issue]: https://github.com/PowerShell/vscode-powershell/issues/new/choose +[open an issue there]: https://github.com/PowerShell/PSScriptAnalyzer/issues/new/choose +[PowerShell 7.4 LTS]: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.4 +[semantic highlighting]: https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide +[tackling an issue]: ./development.md +[v2021.2.2]: https://github.com/PowerShell/vscode-powershell/releases/tag/v2021.2.2 +[VS Code Settings]: https://code.visualstudio.com/docs/getstarted/settings +[WMF 5.1]: https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/wmf/setup/install-configure +[dotnet-framework]: https://dotnet.microsoft.com/en-us/download/dotnet-framework +[word separators]: https://stackoverflow.com/questions/31632351/visual-studio-code-customizing-word-separators +[Your installed PowerShell Extension version]: https://code.visualstudio.com/docs/editor/extension-gallery#_list-installed-extensions +[your PowerShell version table]: http://www.powertheshell.com/topic/learnpowershell/firststeps/psversion/ +[Your VS Code version]: https://code.visualstudio.com/docs/supporting/FAQ#_how-do-i-find-the-vs-code-version + +[#25]: https://github.com/PowerShell/vscode-powershell/issues/25 +[#4474]: https://github.com/PowerShell/vscode-powershell/issues/4474 +[#3991]: https://github.com/PowerShell/vscode-powershell/issues/3991 +[#261]: https://github.com/PowerShell/vscode-powershell/issues/261 +[#410 (comment)]: https://github.com/PowerShell/vscode-powershell/issues/410#issuecomment-397531817 +[#984]: https://github.com/PowerShell/vscode-powershell/issues/984 +[#2571]: https://github.com/PowerShell/vscode-powershell/issues/2572 +[#3221]: https://github.com/PowerShell/vscode-powershell/issues/3221#issuecomment-810563456 +[#3295]: https://github.com/PowerShell/vscode-powershell/issues/3295 +[#3701]: https://github.com/PowerShell/vscode-powershell/issues/3701 +[#633]: https://github.com/PowerShell/vscode-powershell/issues/633 diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..9ad447020d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,50 @@ +import eslint from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier/flat"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + eslint.configs.recommended, + tseslint.configs.strictTypeChecked, + tseslint.configs.stylisticTypeChecked, + eslintConfigPrettier, + { + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + "@typescript-eslint/explicit-function-return-type": "error", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-floating-promises": [ + "error", + { + ignoreVoid: true, + }, + ], + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-require-imports": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + }, + ], + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/prefer-nullish-coalescing": [ + "error", + { + ignoreConditionalTests: true, + ignoreMixedLogicalExpressions: true, + }, + ], + }, + }, +); diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000000..a89a881917 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,5 @@ +# Don't checkin this output dir +Release/ + +# Auto-generated test file +foo[1].ps1 diff --git a/examples/.vscode/launch.json b/examples/.vscode/launch.json index 8aa56df100..310016412d 100644 --- a/examples/.vscode/launch.json +++ b/examples/.vscode/launch.json @@ -1,10 +1,59 @@ { - "version": "0.1.0", - "configurations": [ - { - "name": "PowerShell", - "type": "PowerShell", - "program": "DebugTest.ps1" - } - ] + "version": "0.2.0", + "configurations": [ + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch Current File", + "script": "${file}", + "args": [], + "cwd": "${file}" + }, + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch Current File in Temporary Console", + "script": "${file}", + "args": [], + "cwd": "${file}", + "createTemporaryIntegratedConsole": true + }, + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch Current File w/Args Prompt", + "script": "${file}", + "args": ["${command:SpecifyScriptArgs}"], + "cwd": "${file}" + }, + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Launch DebugTest.ps1", + "script": "${workspaceRoot}/DebugTest.ps1", + "args": ["-Count 55 -DelayMilliseconds 250"], + "cwd": "${workspaceRoot}" + }, + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Interactive Session", + "cwd": "${workspaceRoot}" + }, + { + "type": "PowerShell", + "request": "launch", + "name": "PowerShell Pester Tests", + "script": "Invoke-Pester", + "args": [], + "cwd": "${workspaceRoot}" + }, + { + "type": "PowerShell", + "request": "attach", + "name": "PowerShell Attach to Host Process", + "processId": "${command:PickPSHostProcess}", + "runspaceId": 1 + } + ] } diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json new file mode 100644 index 0000000000..23c9990db9 --- /dev/null +++ b/examples/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + // Use a custom PowerShell Script Analyzer settings file for this workspace. + // Relative paths for this setting are always relative to the workspace root dir. + "powershell.scriptAnalysis.settingsPath": "./PSScriptAnalyzerSettings.psd1", + "files.defaultLanguage": "powershell" +} diff --git a/examples/.vscode/tasks.json b/examples/.vscode/tasks.json new file mode 100644 index 0000000000..8ae38829cc --- /dev/null +++ b/examples/.vscode/tasks.json @@ -0,0 +1,89 @@ +// A task runner that invokes Pester to run all Pester tests under the +// current workspace folder. +// NOTE: This Test task runner requires an updated version of Pester (>=4.0.3) +// in order for the problemMatcher to find failed test information (message, line, file). +// If you don't have that version, you can update Pester from the PowerShell Gallery +// with this command: +// +// PS C:\> Update-Module Pester +// +// If that gives an error like: +// "Module 'Pester' was not installed by using Install-Module, so it cannot be updated." +// then execute: +// +// PS C:\> Install-Module Pester -Scope CurrentUser -Force +// +// NOTE: The Clean, Build and Publish tasks require PSake. PSake can be installed +// from the PowerShell Gallery with this command: +// +// PS C:\> Install-Module PSake -Scope CurrentUser -Force +// +// Available variables which can be used inside of strings: +// ${workspaceFolder} the path of the workspace folder that contains the tasks.json file +// ${workspaceFolderBasename} the name of the workspace folder that contains the tasks.json file without any slashes (/) +// ${file} the current opened file +// ${relativeFile} the current opened file relative to the workspace folder containing the file +// ${fileBasename} the current opened file's basename +// ${fileBasenameNoExtension} the current opened file's basename without the extension +// ${fileDirname} the current opened file's dirname +// ${fileExtname} the current opened file's extension +// ${cwd} the task runner's current working directory on startup +// ${lineNumber} the current selected line number in the active file +{ + "version": "2.0.0", + "windows": { + "options": { + "shell": { + "executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "args": ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command"] + } + } + }, + "linux": { + "options": { + "shell": { + "executable": "/usr/bin/pwsh", + "args": ["-NoProfile", "-Command"] + } + } + }, + "osx": { + "options": { + "shell": { + "executable": "/usr/local/bin/pwsh", + "args": ["-NoProfile", "-Command"] + } + } + }, + "tasks": [ + { + "label": "Clean", + "type": "shell", + "command": "Invoke-PSake build.ps1 -taskList Clean" + }, + { + "label": "Build", + "type": "shell", + "command": "Invoke-PSake build.ps1 -taskList Build", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Test", + "type": "shell", + "command": "Invoke-Pester -PesterOption @{IncludeVSCodeMarker=$true}", + "group": { + "kind": "test", + "isDefault": true + }, + "problemMatcher": ["$pester"] + }, + { + "label": "Publish", + "type": "shell", + "command": "Invoke-PSake build.ps1 -taskList Publish" + } + ] +} diff --git a/examples/Assets/script.js b/examples/Assets/script.js new file mode 100644 index 0000000000..adfa13d65d --- /dev/null +++ b/examples/Assets/script.js @@ -0,0 +1,3 @@ +var h1 = document.createElement('h1'); +h1.appendChild(document.createTextNode('Hello from JavaScript!')); +document.body.appendChild(h1); \ No newline at end of file diff --git a/examples/Assets/style.css b/examples/Assets/style.css new file mode 100644 index 0000000000..976559bafc --- /dev/null +++ b/examples/Assets/style.css @@ -0,0 +1,4 @@ +body { + color: white; + background-color: cornflowerblue; +} \ No newline at end of file diff --git a/examples/Build.ps1 b/examples/Build.ps1 new file mode 100644 index 0000000000..cacac20cb2 --- /dev/null +++ b/examples/Build.ps1 @@ -0,0 +1,294 @@ +############################################################################## +# PREVIEW VERSION OF PSAKE SCRIPT FOR MODULE BUILD & PUBLISH TO THE PSGALLERY +############################################################################## +# +# We are hoping to add support for publishing modules to the PowerShell gallery +# and private repositories in a future release of this extension. This is an +# early look at the approach we are considering which is to supply a +# PSake-based script that will: +# +# 1. Create a directory from which to publish your module. +# 2. Copy the appropriate module files to that directory excluding items like +# the .vscode directory, Pester tests, etc. These are configurable in Build.ps1. +# 3. Verify all existing Pester tests pass. +# 4. Publish the module to the desired repository (defaulting to the PSGallery). +# +# Requirements: PSake. If you don't have this module installed use the following +# command to install it: +# +# PS C:\> Install-Module PSake -Scope CurrentUser +# +############################################################################## +# This is a PSake script that supports the following tasks: +# clean, build, test and publish. The default task is build. +# +# The publish task uses the Publish-Module command to publish +# to either the PowerShell Gallery (the default) or you can change +# the $Repository property to the name of an alternate repository. +# +# The test task invokes Pester to run any Pester tests in your +# workspace folder. Name your test scripts .Tests.ps1 +# and Pester will find and run the tests contained in the files. +# +# You can run this build script directly using the invoke-psake +# command which will execute the build task. This task "builds" +# a temporary folder from which the module can be published. +# +# PS C:\> invoke-psake build.ps1 +# +# You can run your Pester tests (if any) by running the following command. +# +# PS C:\> invoke-psake build.ps1 -taskList test +# +# You can execute the publish task with the following command. Note that +# the publish task will run the test task first. The Pester tests must pass +# before the publish task will run. The first time you run the publish +# command, you will be prompted to enter your PowerShell Gallery NuGetApiKey. +# After entering the key, it is encrypted and stored so you will not have to +# enter it again. +# +# PS C:\> invoke-psake build.ps1 -taskList publish +# +# You can verify the stored and encrypted NuGetApiKey by running the following +# command. This will display your NuGetApiKey in plain text! +# +# PS C:\> invoke-psake build.ps1 -taskList showKey +# +# You can store a new NuGetApiKey with this command. You can leave off +# the -properties parameter and you'll be prompted for the key. +# +# PS C:\> invoke-psake build.ps1 -taskList storeKey -properties @{NuGetApiKey='test123'} +# + +############################################################################### +# Customize these properties for your module. +############################################################################### +Properties { + # The name of your module should match the basename of the PSD1 file. + $ModuleName = (Get-Item $PSScriptRoot\*.psd1 | + Foreach-Object {$null = Test-ModuleManifest -Path $_ -ErrorAction SilentlyContinue; if ($?) {$_}})[0].BaseName + + # Path to the release notes file. Set to $null if the release notes reside in the manifest file. + $ReleaseNotesPath = "$PSScriptRoot\ReleaseNotes.md" + + # The directory used to publish the module from. If you are using Git, the + # $PublishRootDir should be ignored if it is under the workspace directory. + $PublishRootDir = "$PSScriptRoot\Release" + $PublishDir = "$PublishRootDir\$ModuleName" + + # The following items will not be copied to the $PublishDir. + # Add items that should not be published with the module. + $Exclude = @( + (Split-Path $PSCommandPath -Leaf), + 'Release', + 'Tests', + '.git*', + '.vscode', + # These files are unique to this examples dir. + 'DebugTest.ps1', + 'PSScriptAnalyzerSettings.psd1', + 'Readme.md', + 'Stop*.ps1' + ) + + # Name of the repository you wish to publish to. Default repo is the PSGallery. + $PublishRepository = $null + + # Your NuGet API key for the PSGallery. Leave it as $null and the first time + # you publish you will be prompted to enter your API key. The build will + # store the key encrypted in a file, so that on subsequent publishes you + # will no longer be prompted for the API key. + $NuGetApiKey = $null + $EncryptedApiKeyPath = "$env:LOCALAPPDATA\vscode-powershell\NuGetApiKey.clixml" +} + +############################################################################### +# Customize these tasks for performing operations before and/or after publish. +############################################################################### +Task PrePublish { +} + +Task PostPublish { +} + +############################################################################### +# Core task implementations - this possibly "could" ship as part of the +# vscode-powershell extension and then get dot sourced into this file. +############################################################################### +Task default -depends Build + +Task Publish -depends Test, PrePublish, PublishImpl, PostPublish { +} + +Task PublishImpl -depends Test -requiredVariables EncryptedApiKeyPath, PublishDir { + if ($NuGetApiKey) { + "Using script embedded NuGetApiKey" + } + elseif (Test-Path -LiteralPath $EncryptedApiKeyPath) { + $NuGetApiKey = LoadAndUnencryptNuGetApiKey $EncryptedApiKeyPath + "Using stored NuGetApiKey" + } + else { + $cred = PromptUserForNuGetApiKeyCredential -DestinationPath $EncryptedApiKeyPath + $NuGetApiKey = $cred.GetNetworkCredential().Password + "The NuGetApiKey has been stored in $EncryptedApiKeyPath" + } + + $publishParams = @{ + Path = $PublishDir + NuGetApiKey = $NuGetApiKey + } + + if ($PublishRepository) { + $publishParams['Repository'] = $PublishRepository + } + + # Consider not using -ReleaseNotes parameter when Update-ModuleManifest has been fixed. + if ($ReleaseNotesPath) { + $publishParams['ReleaseNotes'] = @(Get-Content $ReleaseNotesPath) + } + + "Calling Publish-Module..." + Publish-Module @publishParams -WhatIf +} + +Task Test -depends Build { + Import-Module Pester + Invoke-Pester $PSScriptRoot +} + +Task Build -depends Clean, Init -requiredVariables PublishDir, Exclude, ModuleName { + Copy-Item -Path $PSScriptRoot\* -Destination $PublishDir -Recurse -Exclude $Exclude + + # Get contents of the ReleaseNotes file and update the copied module manifest file + # with the release notes. + # DO NOT USE UNTIL UPDATE-MODULEMANIFEST IS FIXED - DOES NOT HANDLE SINGLE QUOTES CORRECTLY. + # if ($ReleaseNotesPath) { + # $releaseNotes = @(Get-Content $ReleaseNotesPath) + # Update-ModuleManifest -Path $PublishDir\${ModuleName}.psd1 -ReleaseNotes $releaseNotes + # } +} + +Task Clean -requiredVariables PublishRootDir { + # Sanity check the dir we are about to "clean". If $PublishRootDir were to + # inadvertently get set to $null, the Remove-Item commmand removes the + # contents of \*. That's a bad day. Ask me how I know? :-( + if ((Test-Path $PublishRootDir) -and $PublishRootDir.Contains($PSScriptRoot)) { + Remove-Item $PublishRootDir\* -Recurse -Force + } +} + +Task Init -requiredVariables PublishDir { + if (!(Test-Path $PublishDir)) { + $null = New-Item $PublishDir -ItemType Directory + } +} + +Task RemoveKey -requiredVariables EncryptedApiKeyPath { + if (Test-Path -LiteralPath $EncryptedApiKeyPath) { + Remove-Item -LiteralPath $EncryptedApiKeyPath + } +} + +Task StoreKey -requiredVariables EncryptedApiKeyPath { + $nuGetApiKeyCred = PromptUserForNuGetApiKeyCredential -DestinationPath $EncryptedApiKeyPath + "The NuGetApiKey has been stored in $EncryptedApiKeyPath" +} + +Task ShowKey -requiredVariables EncryptedApiKeyPath { + if ($NuGetApiKey) { + "The embedded (partial) NuGetApiKey is: $($NuGetApiKey[0..7])" + } + else { + $NuGetApiKey = LoadAndUnencryptNuGetApiKey -Path $EncryptedApiKeyPath + "The stored (partial) NuGetApiKey is: $($NuGetApiKey[0..7])" + } + + "To see the full key, use the task 'ShowFullKey'" +} + +Task ShowFullKey -requiredVariables EncryptedApiKeyPath { + if ($NuGetApiKey) { + "The embedded NuGetApiKey is: $NuGetApiKey" + } + else { + $NuGetApiKey = LoadAndUnencryptNuGetApiKey -Path $EncryptedApiKeyPath + "The stored NuGetApiKey is: $NuGetApiKey" + } +} + +Task ? -description 'Lists the available tasks' { + "Available tasks:" + $PSake.Context.Peek().Tasks.Keys | Sort-Object +} + +############################################################################### +# Helper functions +############################################################################### +function PromptUserForNuGetApiKeyCredential { + [Diagnostics.CodeAnalysis.SuppressMessage("PSProvideDefaultParameterValue", '')] + param( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $DestinationPath + ) + + $message = "Enter your NuGet API Key in the password field (or nothing, this isn't used yet in the preview)" + $nuGetApiKeyCred = Get-Credential -Message $message -UserName "ignored" + + if ($DestinationPath) { + EncryptAndSaveNuGetApiKey -NuGetApiKeySecureString $nuGetApiKeyCred.Password -Path $DestinationPath + } + + $nuGetApiKeyCred +} + +function EncryptAndSaveNuGetApiKey { + [Diagnostics.CodeAnalysis.SuppressMessage("PSAvoidUsingConvertToSecureStringWithPlainText", '')] + [Diagnostics.CodeAnalysis.SuppressMessage("PSProvideDefaultParameterValue", '')] + param( + [Parameter(Mandatory, ParameterSetName='SecureString')] + [ValidateNotNull()] + [SecureString] + $NuGetApiKeySecureString, + + [Parameter(Mandatory, ParameterSetName='PlainText')] + [ValidateNotNullOrEmpty()] + [string] + $NuGetApiKey, + + [Parameter(Mandatory)] + $Path + ) + + if ($PSCmdlet.ParameterSetName -eq 'PlainText') { + $NuGetApiKeySecureString = ConvertTo-SecureString -String $NuGetApiKey -AsPlainText -Force + } + + $parentDir = Split-Path $Path -Parent + if (!(Test-Path -LiteralPath $parentDir)) { + $null = New-Item -Path $parentDir -ItemType Directory + } + elseif (Test-Path -LiteralPath $Path) { + Remove-Item -LiteralPath $Path + } + + $NuGetApiKeySecureString | ConvertFrom-SecureString | Export-Clixml $Path + Write-Verbose "The NuGetApiKey has been encrypted and saved to $Path" +} + +function LoadAndUnencryptNuGetApiKey { + [Diagnostics.CodeAnalysis.SuppressMessage("PSProvideDefaultParameterValue", '')] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] + $Path + ) + + $storedKey = Import-Clixml $Path | ConvertTo-SecureString + $cred = New-Object -TypeName PSCredential -ArgumentList 'jpgr',$storedKey + $cred.GetNetworkCredential().Password + Write-Verbose "The NuGetApiKey has been loaded and unencrypted from $Path" +} diff --git a/examples/ChildDebugSessionAttach.ps1 b/examples/ChildDebugSessionAttach.ps1 new file mode 100644 index 0000000000..c06a57f2a7 --- /dev/null +++ b/examples/ChildDebugSessionAttach.ps1 @@ -0,0 +1,22 @@ +# Example on how Start-DebugAttachSession can be used to attach to another +# process. This launches a child process that runs ChildDebugSessionTarget.ps1 +# but it can be adapted to attach to any other PowerShell process that is +# either already running or started like this example. To test this example, +# add a breakpoint to ChildDebugSessionTarget.ps1, select the +# 'PowerShell Launch Current File' configuration and press F5. + +$pipeName = "TestPipe-$(New-Guid)" +$scriptPath = Join-Path -Path $PSScriptRoot -ChildPath 'ChildDebugSessionTarget.ps1' + +$procParams = @{ + FilePath = 'pwsh' + ArgumentList = ('-CustomPipeName {0} -File "{1}" -WaitForAttach' -f $pipeName, $scriptPath) + PassThru = $true +} +$proc = Start-Process @procParams + +Start-DebugAttachSession -CustomPipeName $pipeName -RunspaceId 1 + +# We need to ensure this debug session stays alive until the process exits. If +# we exit early then the child debug session will also exit. +$proc | Wait-Process diff --git a/examples/ChildDebugSessionTarget.ps1 b/examples/ChildDebugSessionTarget.ps1 new file mode 100644 index 0000000000..ed4c9f2a6a --- /dev/null +++ b/examples/ChildDebugSessionTarget.ps1 @@ -0,0 +1,31 @@ +[CmdletBinding()] +param ( + [Parameter()] + [switch] + $WaitForAttach +) + +if ($WaitForAttach) { + # For an attach request we need to wait for the debug pipe runspace to be + # opened before continuing. There is no builtin way to do this so we + # poll the runspace list until a new one is created. + $runspaces = Get-Runspace + while ($true) { + if (Get-Runspace | Where-Object { $_.Id -notin $runspaces.Id }) { + break + } + Start-Sleep -Seconds 1 + } + + # Windows PowerShell 5.1 will not sync breakpoints until the debugger has + # stopped at least once. We use Wait-Debugger to make this happen. + if ($PSVersionTable.PSVersion -lt '6.0') { + Wait-Debugger + } + else { + Start-Sleep -Seconds 1 # Give the debugger time to sync breakpoints + } +} + +$processInfo = "This process is running with PID $PID and has runspace ID $([Runspace]::DefaultRunspace.Id)" +Write-Host $processInfo # Place breakpoint here diff --git a/examples/DebugTest.ps1 b/examples/DebugTest.ps1 index 68f648b1d5..478990bfd2 100644 Binary files a/examples/DebugTest.ps1 and b/examples/DebugTest.ps1 differ diff --git a/examples/ExtensionExamples.ps1 b/examples/ExtensionExamples.ps1 new file mode 100644 index 0000000000..a6db28b20a --- /dev/null +++ b/examples/ExtensionExamples.ps1 @@ -0,0 +1,53 @@ +# Instructions: select the entire file and hit F8 to +# load the extensions. To see the list of registered +# extensions and run them, hit Ctrl+Shift+P, type 'addi' +# and run the "Show additional commands from PowerShell modules" +# command. A quick pick list will appear with all 3 +# extensions registered. Selecting one of them will launch it. + +function Invoke-MyCommand { + Write-Output "My command's function was executed!" +} + +# Registering a command for an existing function + +Register-EditorCommand -Verbose ` + -Name "MyModule.MyCommandWithFunction" ` + -DisplayName "My command with function" ` + -Function Invoke-MyCommand + +# Registering a command to run a ScriptBlock + +Register-EditorCommand -Verbose ` + -Name "MyModule.MyCommandWithScriptBlock" ` + -DisplayName "My command with script block" ` + -ScriptBlock { Write-Output "My command's script block was executed!" } + +# A real command example: + +function Invoke-MyEdit([Microsoft.PowerShell.EditorServices.Extensions.EditorContext]$context) { + + # Insert text at pre-defined position + + $context.CurrentFile.InsertText( + "`r`n# I was inserted by PowerShell code!`r`nGet-Process -Name chrome`r`n", + 35, 1); + + # TRY THIS ALSO, comment out the above 4 lines and uncomment the below + + # # Insert text at cursor position + + # $context.CurrentFile.InsertText( + # "Get-Process -Name chrome", + # $context.CursorPosition); +} + +# After registering this command, you only need to re-evaluate the +# Invoke-MyEdit command when you've made changes to its code. The +# registration of the command persists. + +Register-EditorCommand -Verbose ` + -Name "MyModule.MyEditCommand" ` + -DisplayName "Apply my edit!" ` + -Function Invoke-MyEdit ` + -SuppressOutput diff --git a/examples/PSScriptAnalyzerSettings.psd1 b/examples/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000000..0b2f42c88f --- /dev/null +++ b/examples/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,44 @@ +# Use the PowerShell extension setting `powershell.scriptAnalysis.settingsPath` to get the current workspace +# to use this PSScriptAnalyzerSettings.psd1 file to configure code analysis in Visual Studio Code. +# This setting is configured in the workspace's `.vscode/settings.json`. +# +# For more information on PSScriptAnalyzer settings see: +# https://github.com/PowerShell/PSScriptAnalyzer/blob/master/README.md#settings-support-in-scriptanalyzer +# +# You can see the predefined PSScriptAnalyzer settings here: +# https://github.com/PowerShell/PSScriptAnalyzer/tree/master/Engine/Settings +@{ + # Only diagnostic records of the specified severity will be generated. + # Uncomment the following line if you only want Errors and Warnings but + # not Information diagnostic records. + # + # Severity = @('Error', 'Warning') + + # Analyze **only** the following rules. Use IncludeRules when you want + # to invoke only a small subset of the default rules. + IncludeRules = @('PSAvoidDefaultValueSwitchParameter', + 'PSMisleadingBacktick', + 'PSMissingModuleManifestField', + 'PSReservedCmdletChar', + 'PSReservedParams', + 'PSShouldProcess', + 'PSUseApprovedVerbs', + 'PSAvoidUsingCmdletAliases', + 'PSUseDeclaredVarsMoreThanAssignments') + + # Do not analyze the following rules. Use ExcludeRules when you have + # commented out the IncludeRules settings above and want to include all + # the default rules except for those you exclude below. + # Note that if a rule is in both IncludeRules and ExcludeRules, the rule + # will be excluded. + # + # ExcludeRules = @('PSAvoidUsingWriteHost') + + # You can use rule configuration to configure rules that support it: + # + # Rules = @{ + # PSAvoidUsingCmdletAliases = @{ + # AllowList = @("cd") + # } + # } +} diff --git a/examples/PathProcessingNoWildcards.ps1 b/examples/PathProcessingNoWildcards.ps1 new file mode 100644 index 0000000000..25889fd301 --- /dev/null +++ b/examples/PathProcessingNoWildcards.ps1 @@ -0,0 +1,59 @@ +<# +.SYNOPSIS + Demonstrates how to write a command that works with paths that do + not allow wildards but must exist. +.DESCRIPTION + This command does not require a LiteralPath parameter because the + Path parameter can handle paths that use wildcard characters. That's + because this command does not "resolve" the supplied path. +.EXAMPLE + C:\PS> Import-FileNoWildcard -Path ..\..\Tests\foo[1].txt -WhatIf + This example shows how the Path parameter can handle a path that happens + to use the wildcard chars "[" and "]". +#> +function Import-FileNoWildcard { + [CmdletBinding(SupportsShouldProcess=$true)] + param( + # Specifies a path to one or more locations. + [Parameter(Mandatory=$true, + Position=0, + ParameterSetName="Path", + ValueFromPipeline=$true, + ValueFromPipelineByPropertyName=$true, + HelpMessage="Path to one or more locations.")] + [Alias("PSPath")] + [ValidateNotNullOrEmpty()] + [string[]] + $Path + ) + + begin { + } + + process { + # Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=$true)] + $paths = @() + foreach ($aPath in $Path) { + if (!(Test-Path -LiteralPath $aPath)) { + $ex = New-Object System.Management.Automation.ItemNotFoundException "Cannot find path '$aPath' because it does not exist." + $category = [System.Management.Automation.ErrorCategory]::ObjectNotFound + $errRecord = New-Object System.Management.Automation.ErrorRecord $ex,'PathNotFound',$category,$aPath + $psCmdlet.WriteError($errRecord) + continue + } + + # Resolve any relative paths + $paths += $psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($aPath) + } + + foreach ($aPath in $paths) { + if ($pscmdlet.ShouldProcess($aPath, 'Operation')) { + # Process each path + $aPath + } + } + } + + end { + } +} \ No newline at end of file diff --git a/examples/PathProcessingNonExistingPaths.ps1 b/examples/PathProcessingNonExistingPaths.ps1 new file mode 100644 index 0000000000..d11e025303 --- /dev/null +++ b/examples/PathProcessingNonExistingPaths.ps1 @@ -0,0 +1,53 @@ +<# +.SYNOPSIS + Demonstrates how to write a command that works with paths that do + not allow wildards and do not have to exist. +.DESCRIPTION + This command does not require a LiteralPath parameter because the + Path parameter can handle paths that use wildcard characters. That's + because this command does not "resolve" the supplied path. This command + also does not verify the path exists because the point of the command is + to create a new file at the specified path. +.EXAMPLE + C:\PS> New-File -Path xyzzy[1].txt -WhatIf + This example shows how the Path parameter can handle a path that happens + to use the wildcard chars "[" and "]" and does not exist to start with. +#> +function New-File { + [CmdletBinding(SupportsShouldProcess=$true)] + param( + # Specifies a path to one or more locations. + [Parameter(Mandatory=$true, + Position=0, + ParameterSetName="Path", + ValueFromPipeline=$true, + ValueFromPipelineByPropertyName=$true, + HelpMessage="Path to one or more locations.")] + [Alias("PSPath")] + [ValidateNotNullOrEmpty()] + [string[]] + $Path + ) + + begin { + } + + process { + # Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=$true)] + $paths = @() + foreach ($aPath in $Path) { + # Resolve any relative paths + $paths += $psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($aPath) + } + + foreach ($aPath in $paths) { + if ($pscmdlet.ShouldProcess($aPath, 'Operation')) { + # Process each path + $aPath + } + } + } + + end { + } +} \ No newline at end of file diff --git a/examples/PathProcessingWildcards.ps1 b/examples/PathProcessingWildcards.ps1 new file mode 100644 index 0000000000..6ba85f9e67 --- /dev/null +++ b/examples/PathProcessingWildcards.ps1 @@ -0,0 +1,93 @@ +<# +.SYNOPSIS + Demonstrates how to write a command that works with paths that allow + wildards and must exist. +.DESCRIPTION + This command also demonstrates how you need to supply a LiteralPath + parameter when your Path parameter accepts wildcards. This is in order + to handle paths like foo[1].txt. If you pass this path to the Path + parameter, it will fail to find this file because "[1]" is interpreted + as a wildcard spec e.g it resolves to foo1.txt. The LiteralPath parameter + is used in this case as it does not interpret wildcard chars. +.EXAMPLE + C:\PS> Import-FileWildcard -LiteralPath ..\..\Tests\foo[1].txt -WhatIf + This example shows how to use the LiteralPath parameter with a path + that happens to use the wildcard chars "[" and "]". +#> +function Import-FileWildcard { + [CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName='Path')] + param( + # Specifies a path to one or more locations. Wildcards are permitted. + [Parameter(Mandatory=$true, + Position=0, + ParameterSetName="Path", + ValueFromPipeline=$true, + ValueFromPipelineByPropertyName=$true, + HelpMessage="Path to one or more locations.")] + [ValidateNotNullOrEmpty()] + [SupportsWildcards()] + [string[]] + $Path, + + # Specifies a path to one or more locations. Unlike the Path parameter, the value of the LiteralPath parameter is + # used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters, + # enclose it in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any + # characters as escape sequences. + [Parameter(Mandatory=$true, + Position=0, + ParameterSetName="LiteralPath", + ValueFromPipelineByPropertyName=$true, + HelpMessage="Literal path to one or more locations.")] + [Alias("PSPath")] + [ValidateNotNullOrEmpty()] + [string[]] + $LiteralPath + ) + + begin { + } + + process { + # Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName='Path')] + $paths = @() + if ($psCmdlet.ParameterSetName -eq 'Path') { + foreach ($aPath in $Path) { + if (!(Test-Path -Path $aPath)) { + $ex = New-Object System.Management.Automation.ItemNotFoundException "Cannot find path '$aPath' because it does not exist." + $category = [System.Management.Automation.ErrorCategory]::ObjectNotFound + $errRecord = New-Object System.Management.Automation.ErrorRecord $ex,'PathNotFound',$category,$aPath + $psCmdlet.WriteError($errRecord) + continue + } + + # Resolve any wildcards that might be in the path + $provider = $null + $paths += $psCmdlet.SessionState.Path.GetResolvedProviderPathFromPSPath($aPath, [ref]$provider) + } + } + else { + foreach ($aPath in $LiteralPath) { + if (!(Test-Path -LiteralPath $aPath)) { + $ex = New-Object System.Management.Automation.ItemNotFoundException "Cannot find path '$aPath' because it does not exist." + $category = [System.Management.Automation.ErrorCategory]::ObjectNotFound + $errRecord = New-Object System.Management.Automation.ErrorRecord $ex,'PathNotFound',$category,$aPath + $psCmdlet.WriteError($errRecord) + continue + } + + # Resolve any relative paths + $paths += $psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($aPath) + } + } + + foreach ($aPath in $paths) { + if ($pscmdlet.ShouldProcess($aPath, 'Operation')) { + # Process each path + $aPath + } + } + } + + end { + } +} \ No newline at end of file diff --git a/examples/PromptExamples.ps1 b/examples/PromptExamples.ps1 new file mode 100644 index 0000000000..d2d801af6c --- /dev/null +++ b/examples/PromptExamples.ps1 @@ -0,0 +1,41 @@ +<# ------ Input Prompts ------ #> + +$fields = @( + New-Object "System.Management.Automation.Host.FieldDescription" "Input" + New-Object "System.Management.Automation.Host.FieldDescription" "Input List" +) +$fields[1].SetParameterType([int[]]) + +$host.UI.Prompt("Caption", "Message", $fields) + +Get-Credential +Get-Credential -Message "Test!" +Get-Credential -UserName "myuser" -Message "Password stealer" + +$host.UI.PromptForCredential("Caption", "Message", $null, $null, [System.Management.Automation.PSCredentialTypes]::Default, [System.Management.Automation.PSCredentialUIOptions]::Default) +$host.UI.PromptForCredential("Caption", "Message", "testuser", $null, [System.Management.Automation.PSCredentialTypes]::Default, [System.Management.Automation.PSCredentialUIOptions]::Default) + +Read-Host -AsSecureString +Read-Host -Prompt "Enter a secure string" -AsSecureString + +$field = New-Object "System.Management.Automation.Host.FieldDescription" "SecureString" +$field.SetParameterType([SecureString]) +$host.UI.Prompt("Caption", "Message", $field) + +$field = New-Object "System.Management.Automation.Host.FieldDescription" "PSCredential" +$field.SetParameterType([PSCredential]) +$host.UI.Prompt("Caption", "Message", $field) + +<# ------ Choice Prompts ------ #> + +$choices = @( + New-Object "System.Management.Automation.Host.ChoiceDescription" "&Apple", "Apple" + New-Object "System.Management.Automation.Host.ChoiceDescription" "&Banana", "Banana" + New-Object "System.Management.Automation.Host.ChoiceDescription" "&Orange", "Orange" +) + +# Single-choice prompt +$host.UI.PromptForChoice("Choose a fruit", "You may choose one", $choices, 1) + +# Multi-choice prompt +$host.UI.PromptForChoice("Choose a fruit", "You may choose more than one", $choices, [int[]]@(0, 2)) \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index a6edead042..cb231d166c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,19 +3,23 @@ *NOTE: For a more comfortable reading experience, use the key combination `Ctrl+Shift+V`* This folder contains a few basic PowerShell script files that you can use -to experiment with the new PowerShell editing and debugging capabilities. +to experiment with the new PowerShell editing debugging capabilities as well +as an early preview of a workflow for publishing a module to the PowerShell +Gallery. + Here are some ideas for what you can try with these scripts: ## Language Features -- **Integrated syntax checks** from the PowerShell engine and **integrated +- **Integrated syntax checks** from the PowerShell engine and **integrated rule-based analysis** using PowerShell Script Analyzer - - Try opening `DebugTest.ps1` and `StopTest.ps1` by double-clicking on their - file names. You will see red and green squiggles for rule-based checks. - You can introduce a syntax error somewhere to see the red squiggle for - that as well. To see a list of all errors and warnings, try pressing - `Ctrl+Shift+M`. -- **Go to definition `(F12)`** and **Peek definition `(Alt+F12)`** + - Try opening `DebugTest.ps1` by double-clicking on its file name in the + Explorer view. You will see a green squiggle on the function name `Do-Work` + indicating that `Do` is not an approved verb. These rule-based checks use + PSScriptAnalyzer to analyze/lint your scripts. You can introduce a syntax + error somewhere to see a red squiggle for that as well. To see a list of + all errors and warnings, try pressing `Ctrl+Shift+M`. +- **Go to definition `(F12)`** and **Peek definition `(Alt+F12)`** for cmdlet and variable names - Try this on the `Stop-Process2` cmdlet in `StopTest.ps1` - **Find all references `(Shift+F12)`** for cmdlet and variable names @@ -28,7 +32,7 @@ Here are some ideas for what you can try with these scripts: You can run scripts under the debugger by going to the debug workspace `(Ctrl+Shift+D)` and clicking the `Start` button or just by pressing `F5`. By default the debugger will start the `DebugTest.ps1` script. You can -set breakpoints, pause execution, look at the call stack, inspect variables, +set breakpoints, pause execution, look at the call stack, inspect variables, and set specific variables to be watched. Try these steps: @@ -38,31 +42,96 @@ Try these steps: 3. Press the blue **Pause** button at the top of the screen. The debugger will stop executing wherever it is at the moment and will bring you to the file and line where it stopped. -4. Check out the **Variables** pane at the top left of the window. Scroll +4. Check out the **Variables** pane at the top left of the window. Scroll through the list and inspect some of the variables there. 5. Find the variable `i` in the Variables list, right click it and select **Add to Watch**. The variable should appear in the **Watch** pane now. 6. Hover over the title of the **Watch** pane and some buttons should appear. - Click the plus sign `+` button and type `str` then press enter. + Click the plus sign `+` button and type `$str` then press enter. 7. Back in the editor, click to the left of line 10 to set a breakpoint there. 8. Click the green **Play** button or press `F5` to continue execution. 9. Observe that every time the breakpoint is hit, the watch variables get updated. 10. When you're done debugging, click the red **Stop** button or press `Shift+F5` -If you would like to debug a different script, you will need to edit the -`.vscode\launch.json` file and change the `program` parameter to point to -the script file to be debugged. In the future we hope to remove the -necessity of this setting so that the current script file will be executed -when `F5` is pressed. +The debugger will attempt to execute the file in the active editor pane. +If you would like to configure a single script to always be executed upon +launch of the debugger, you will need to edit the `.vscode\launch.json` +file and change the `program` parameter to point to the script file to be +debugged. The path must be absolute but you can use the ${workspaceRoot} variable +to refer to the open folder in VSCode e.g. +`"program": "${workspaceRoot}\\DebugTest.ps1"` + +### Passing Arguments to the Script + +If you would like to pass arguments to your script, open the `.vscode\launch.json` +file in your workspace and modify the `args` parameter e.g.: + +`"args": [ "-Param1 foo -Recurse" ]` + +You can pass all your script arguments in a single string or break them up +into individual strings e.g.: + +`"args": [ "-Param1", "foo" "-Recurse" ],` + +At runtime these arguments will be concatenated together using a space +delimiter so it will result in the same string as the first `args` example. + +### Setting the Working Directory + +When the debugger starts it will set the working directory of the PowerShell +environment depending on the value of the `cwd` parameter in the +`.vscode\launch.json` file in your workspace. If this parameter is missing or +is set to an empty string, the working directory will be set to the workspace directory. +By default it is set to `${file}` which will set the working directory to the parent +directory of the file in the active editor pane when the debugger is launched. +You can also set the parameter explicitly e.g.: + +`"cwd": "C:\\Users\\JSnover\\Documents\\MonadUberAlles"` + +## Module Publishing Preview + +### Requirements: +* [PSake](https://github.com/psake/psake) - install PSake with the command: + + PS C:\\> `Install-Module PSake -Scope CurrentUser` + +The are two files (Build.ps1 and tasks.json) that facilitate building a directory from which +to publish a module from and then publishing from that directory. The act of creating or +building this "Release" directory can be executed with the key combination `Ctrl+Shift+B` +which is the `Build` keyboard shortcut in Visual Studio Code. + +When you execute the `Build` command, the build task from the `.vscode\tasks.json` file +is executed. This task invokes PSake on the file `Build.ps1`. This file +contains items you might want to customize such as `$PublishRepository` or the +`$ReleaseNotesPath`. It also contains two PSake tasks which you might want to +customize: `PrePublish` and `PostPublish`. If you sign your scripts, you can +use the `PrePublish` task and the script in it will get executed after the build +but before the `Publish` task is executed. + +To execute the `Publish` task, press `Ctrl+P` then type `"task publish"` and press `Enter`. + +NOTE: the `Publish` task does not actually publish to allow for experimentation. +If you wish to publish, remove the `-WhatIf` parameter on the `Publish-Module` command +in Build.ps1. But make sure you've modified the module manifest (psd1) file or supplied your own +in order to give your module a unique name and guid. + +NOTE: the very first time you execute the publish task, you will be prompted for +a NuGet API Key. This would normally be the NuGet API Key you are assigned when you +register for an account on the [PowerShell Gallery](https://www.powershellgallery.com/). +However since this is just an example of how this feature could work in the future, +you can supply any string you want. + +For more details on how this works, inspect the `.vscode\tasks.json` file and the +`Build.ps1` file. ## Feedback -We would love to hear your feedback! Please post feature requests or issue +We would love to hear your feedback! Please post feature requests or issue reports on our [GitHub issues page](http://github.com/PowerShell/vscode-powershell). -If you are experiencing any errors or crashes, please include the +If you are experiencing any errors or crashes, please include the following two log files: -- The language service log file: `$env:USERPROFILE\.vscode\extensions\vscode-powershell\bin\EditorServices.log` -- The debugging service log file: `$env:USERPROFILE\.vscode\extensions\vscode-powershell\bin\DebugService.log` - - NOTE: This file may not exist if you haven't use the debugger yet. +- The language service log file: `$Home\.vscode\extensions\ms-vscode.PowerShell-\bin\EditorServices.log` +- The debugging service log file: `$Home\.vscode\extensions\ms-vscode.PowerShell-\bin\DebugService.log` + - NOTE: This file may not exist if you haven't use the debugger yet. Replace `` in the paths above with the version number of the extension. diff --git a/examples/ReleaseNotes.md b/examples/ReleaseNotes.md new file mode 100644 index 0000000000..44a2053ddc --- /dev/null +++ b/examples/ReleaseNotes.md @@ -0,0 +1,11 @@ +## What is New in SampleModule 1.0 +March 9, 2016 + +* Note: Due to a bug in `Update-ModuleManifest` you cannot put a single +quote in your release notes. + +* Initial release with support for New-File, Import-FileNoWildcard and +Import-FileWildcard commands. + +### Feedback +Please send your feedback to http://github.com/____.com/issues \ No newline at end of file diff --git a/examples/SampleModule.psd1 b/examples/SampleModule.psd1 new file mode 100644 index 0000000000..eaae97e03c --- /dev/null +++ b/examples/SampleModule.psd1 @@ -0,0 +1,115 @@ +# DO NOT COPY THIS MANIFEST VERBATIM. THIS IS JUST A SAMPLE. +# GENERATE YOUR MANIFEST USING THE New-ModuleManifest COMMAND TO +# GUARANTEE YOU GET A UNIQUE GUID FOR YOUR MODULE. +@{ + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + PSData = @{ + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('Import', 'File') + + # A URL to the license for this module. + LicenseUri = 'https://github.com/___/license' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/___/' + + # A URL to an icon representing this module. + IconUri = 'https://github.com/___/icon.png' + + # ReleaseNotes of this module - our ReleaseNotes are in + # the file ReleaseNotes.md + # ReleaseNotes = '' + + } # End of PSData hashtable + + } # End of PrivateData hashtable + +# Script module or binary module file associated with this manifest. +RootModule = 'SampleModule.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# ID used to uniquely identify this module +GUID = '3ff4d4b6-ade9-46f3-a4f2-2ad6f5508388' + +# Author of this module +Author = '' + +# Company or vendor of this module +CompanyName = 'Unknown' + +# Copyright statement for this module +Copyright = '(c) 2021 .' + +# Description of the functionality provided by this module +Description = 'Some description. This is required by the PowerShell Gallery' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module - explicitly list each function that should be +# exported. This improves performance of PowerShell when discovering the commands in +# module. +FunctionsToExport = @('New-File','Import-FileNoWildcard','Import-FileWildcard') + +# Cmdlets to export from this module +# CmdletsToExport = '*' + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module +# AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/examples/SampleModule.psm1 b/examples/SampleModule.psm1 new file mode 100644 index 0000000000..1eb7d5ec62 --- /dev/null +++ b/examples/SampleModule.psm1 @@ -0,0 +1,4 @@ + +. $PSScriptRoot\PathProcessingNonExistingPaths.ps1 +. $PSScriptRoot\PathProcessingNoWildcards.ps1 +. $PSScriptRoot\PathProcessingWildcards.ps1 diff --git a/examples/Stop-Process2.ps1 b/examples/Stop-Process2.ps1 index 9fa66141d6..4174844499 100644 --- a/examples/Stop-Process2.ps1 +++ b/examples/Stop-Process2.ps1 @@ -8,40 +8,30 @@ .EXAMPLE Another example of how to use this cmdlet #> -function Stop-Process2 -{ +function Stop-Process2 { [CmdletBinding(SupportsShouldProcess = $true)] [Alias()] [OutputType([int])] - Param - ( + param( # Param1 help description [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] $Name ) - - Begin - { - } - Process - { + + process { if ($PSCmdlet.ShouldProcess("")) { $processes = Get-Process -Name $Name - foreach ($process in $processes) - { + foreach ($process in $processes) { $id = $process.Id $name = $process.Name Write-Output "Killing $name ($id)" - + $process.Kill(); - + Start-Sleep -Seconds 1 } } } - End - { - } } \ No newline at end of file diff --git a/examples/StopTest.ps1 b/examples/StopTest.ps1 index 0884e47a5a..cf633a81fa 100644 --- a/examples/StopTest.ps1 +++ b/examples/StopTest.ps1 @@ -1,5 +1,4 @@ - -. .\Stop-Process2.ps1 +. ./Stop-Process2.ps1 notepad.exe notepad.exe diff --git a/examples/Tests/PathProcessing.Tests.ps1 b/examples/Tests/PathProcessing.Tests.ps1 new file mode 100644 index 0000000000..d84ffbd7ee --- /dev/null +++ b/examples/Tests/PathProcessing.Tests.ps1 @@ -0,0 +1,112 @@ +# These Pester tests are for the for parameter-* and ex-path* snippets. +# Take a look at the .vscode\tasks.json file to see how you can create +# and configure a test task runner that will run all the Pester tests +# in your workspace folder. + +# To run these Pester tests, press Ctrl+Shift+T or press Ctrl+Shift+P, +# type "test" and select "Tasks: Run Test Task". This will invoke the +# test task runner defined in .vscode\tasks.json. + +# This (empty) file is required by some of the tests. + +BeforeAll { + $null = New-Item -Path "$PSScriptRoot\foo[1].txt" -Force + + Import-Module $PSScriptRoot\..\SampleModule.psd1 + + $WorkspaceRoot = Convert-Path $PSScriptRoot/.. + Set-Location $WorkspaceRoot +} + +Describe 'Verify Path Processing for Non-existing Paths Allowed Impl' { + It 'Processes non-wildcard absolute path to non-existing file via -Path param' { + New-File -Path $WorkspaceRoot\ReadmeNew.md | Should -Be "$WorkspaceRoot\READMENew.md" + } + It 'Processes multiple absolute paths via -Path param' { + New-File -Path $WorkspaceRoot\Readme.md, $WorkspaceRoot\XYZZY.ps1 | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\XYZZY.ps1") + } + It 'Processes relative path via -Path param' { + New-File -Path ..\Examples\READMENew.md | Should -Be "$WorkspaceRoot\READMENew.md" + } + It 'Processes multiple relative path via -Path param' { + New-File -Path ..\Examples\README.md, XYZZY.ps1 | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\XYZZY.ps1") + } + + It 'Should accept pipeline input to Path' { + Get-ChildItem -LiteralPath "$WorkspaceRoot\Tests\foo[1].txt" | New-File | Should -Be "$PSScriptRoot\foo[1].txt" + } +} + +Describe 'Verify Path Processing for NO Wildcards Allowed Impl' { + It 'Processes non-wildcard absolute path via -Path param' { + Import-FileNoWildcard -Path $WorkspaceRoot\Readme.md | Should -Be "$WorkspaceRoot\README.md" + } + It 'Processes multiple absolute paths via -Path param' { + Import-FileNoWildcard -Path $WorkspaceRoot\Readme.md, $WorkspaceRoot\PathProcessingWildcards.ps1 | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\PathProcessingWildcards.ps1") + } + It 'Processes relative path via -Path param' { + Import-FileNoWildcard -Path ..\examples\README.md | Should -Be "$WorkspaceRoot\README.md" + } + It 'Processes multiple relative path via -Path param' { + Import-FileNoWildcard -Path ..\examples\README.md, .vscode\launch.json | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\.vscode\launch.json") + } + + It 'Should accept pipeline input to Path' { + Get-ChildItem -LiteralPath "$WorkspaceRoot\Tests\foo[1].txt" | Import-FileNoWildcard | Should -Be "$PSScriptRoot\foo[1].txt" + } +} + +Describe 'Verify Path Processing for Wildcards Allowed Impl' { + It 'Processes non-wildcard absolute path via -Path param' { + Import-FileWildcard -Path $WorkspaceRoot\Readme.md | Should -Be "$WorkspaceRoot\README.md" + } + It 'Processes multiple absolute paths via -Path param' { + Import-FileWildcard -Path $WorkspaceRoot\Readme.md, $WorkspaceRoot\PathProcessingWildcards.ps1 | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\PathProcessingWildcards.ps1") + } + It 'Processes wildcard absolute path via -Path param' { + $files = Import-FileWildcard -Path $WorkspaceRoot\*.psd1 + $files.Count | Should -Be 2 + $files[0] | Should -Be "$WorkspaceRoot\PSScriptAnalyzerSettings.psd1" + $files[1] | Should -Be "$WorkspaceRoot\SampleModule.psd1" + } + It 'Processes wildcard relative path via -Path param' { + $files = Import-FileWildcard -Path *.psd1 + $files.Count | Should -Be 2 + $files[0] | Should -Be "$WorkspaceRoot\PSScriptAnalyzerSettings.psd1" + $files[1] | Should -Be "$WorkspaceRoot\SampleModule.psd1" + } + It 'Processes relative path via -Path param' { + Import-FileWildcard -Path ..\examples\README.md | Should -Be "$WorkspaceRoot\README.md" + } + It 'Processes multiple relative path via -Path param' { + Import-FileWildcard -Path ..\examples\README.md, .vscode\launch.json | + Should -Be @("$WorkspaceRoot\README.md", "$WorkspaceRoot\.vscode\launch.json") + } + + It 'DefaultParameterSet should -be Path' { + $files = Import-FileWildcard *.psd1 + $files.Count | Should -Be 2 + $files[0] | Should -Be "$WorkspaceRoot\PSScriptAnalyzerSettings.psd1" + $files[1] | Should -Be "$WorkspaceRoot\SampleModule.psd1" + } + + It 'Should process absolute literal paths via -LiteralPath param'{ + Import-FileWildcard -LiteralPath "$PSScriptRoot\foo[1].txt" | Should -Be "$PSScriptRoot\foo[1].txt" + } + It 'Should process relative literal paths via -LiteralPath param'{ + Import-FileWildcard -LiteralPath "..\examples\Tests\foo[1].txt" | Should -Be "$PSScriptRoot\foo[1].txt" + } + It 'Should process multiple literal paths via -LiteralPath param'{ + Import-FileWildcard -LiteralPath "..\examples\Tests\foo[1].txt", "$WorkspaceRoot\README.md" | + Should -Be @("$PSScriptRoot\foo[1].txt", "$WorkspaceRoot\README.md") + } + + It 'Should accept pipeline input to LiteralPath' { + Get-ChildItem -LiteralPath "$WorkspaceRoot\Tests\foo[1].txt" | Import-FileWildcard | Should -Be "$PSScriptRoot\foo[1].txt" + } +} diff --git a/examples/Tests/SampleModule.Tests.ps1 b/examples/Tests/SampleModule.Tests.ps1 new file mode 100644 index 0000000000..3f36af55ec --- /dev/null +++ b/examples/Tests/SampleModule.Tests.ps1 @@ -0,0 +1,10 @@ +BeforeAll { + $ModuleManifestName = 'SampleModule.psd1' + Import-Module $PSScriptRoot\..\$ModuleManifestName +} +Describe 'Module Manifest Tests' { + It 'Passes Test-ModuleManifest' { + Test-ModuleManifest -Path $PSScriptRoot\..\$ModuleManifestName + $? | Should -Be $true + } +} diff --git a/examples/en-US/about_SampleModule.help.txt b/examples/en-US/about_SampleModule.help.txt new file mode 100644 index 0000000000..7dc37ae5aa --- /dev/null +++ b/examples/en-US/about_SampleModule.help.txt @@ -0,0 +1,15 @@ +TOPIC + SampleModule 1.0.0 + +SHORT DESCRIPTION + You should considering providing an introduction and overview of your + module here. + +LONG DESCRIPTION + Discuss what the "primary" commands are in your module especially if + there are many commands. Discuss how to get started using this module + providing examples where appropriate. + +YOUR HEADER HERE + About topics in PowerShell are free-form text. Add headers to your + about topic as necessary. \ No newline at end of file diff --git a/images/PowerShell_icon.png b/images/PowerShell_icon.png deleted file mode 100644 index 76dc30059b..0000000000 Binary files a/images/PowerShell_icon.png and /dev/null differ diff --git a/media/PowerShell_Icon.png b/media/PowerShell_Icon.png new file mode 100644 index 0000000000..c64b93277b Binary files /dev/null and b/media/PowerShell_Icon.png differ diff --git a/media/PowerShell_Preview_Icon.png b/media/PowerShell_Preview_Icon.png new file mode 100644 index 0000000000..96ec617872 Binary files /dev/null and b/media/PowerShell_Preview_Icon.png differ diff --git a/media/walkthrough.md b/media/walkthrough.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..631b3b3a9b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7179 @@ +{ + "name": "powershell", + "version": "2025.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "powershell", + "version": "2025.2.0", + "license": "SEE LICENSE IN LICENSE.txt", + "dependencies": { + "@vscode/extension-telemetry": "^0.9.9", + "semver": "^7.7.2", + "untildify": "^4.0.0", + "uuid": "^9.0.1", + "vscode-languageclient": "^9.0.1", + "vscode-languageserver-protocol": "^3.17.5" + }, + "devDependencies": { + "@vscode/vsce": "^3.6.0", + "esbuild": "^0.25.9" + }, + "engines": { + "vscode": "^1.101.0" + }, + "optionalDependencies": { + "@eslint/js": "^9.26.0", + "@types/mock-fs": "^4.13.4", + "@types/node": "^22.18.1", + "@types/semver": "^7.7.1", + "@types/sinon": "^17.0.4", + "@types/ungap__structured-clone": "^1.2.0", + "@types/uuid": "^9.0.8", + "@types/vscode": "~1.101.0", + "@ungap/structured-clone": "^1.3.0", + "@vscode/debugprotocol": "^1.68.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.5.2", + "esbuild-register": "^3.6.0", + "eslint": "^9.35.0", + "eslint-config-prettier": "^10.1.8", + "mock-fs": "^5.5.0", + "prettier": "^3.6.2", + "prettier-plugin-organize-imports": "^4.2.0", + "sinon": "^19.0.5", + "typescript": "^5.9.2", + "typescript-eslint": "^8.43.0" + } + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "integrity": "sha1-q9RtqyQi4xK9G/428NQnq2A5gl0=", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "integrity": "sha1-s2Q68MX+6dU+aal8g1xAS9yA95I=", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "integrity": "sha1-Qv4MyrI4QdmQWBLFjxCC0neEVm0=", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.0", + "integrity": "sha1-aNunA2CA4dnVaZxOSCFKt5b6c60=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.0", + "integrity": "sha1-n07JyJpjUWknhArmIMYOgRoLVKM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.20.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.22.0", + "integrity": "sha1-duRKdQk6L0d/xUuE9GBJ3CzmWAA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.0", + "integrity": "sha1-NBFT9bKSdTnriYV3ZR7kjOmN2iU=", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.0", + "integrity": "sha1-/Cg0/FHh4rt0twwoS0D4JNhnQio=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.11.1", + "integrity": "sha1-GbpbdgGuTy3tAQxVylUgD/pseew=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^4.2.0", + "@azure/msal-node": "^3.5.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "integrity": "sha1-VQHPhdT1JjBgKozHXfdlaMlpqCc=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "4.22.0", + "integrity": "sha1-X846k4h22rPvekUJcIVIZxKUuHQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.12.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "15.12.0", + "integrity": "sha1-XDCgW0OW4tu8NdJ72btjbUTMsA4=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "3.7.3", + "integrity": "sha1-xsjhHAjjal40evm6e9bkprjFNqU=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.12.0", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@azure/msal-node/node_modules/uuid": { + "version": "8.3.2", + "integrity": "sha1-gNW1ztJxu5r2xEXyGhoExgbO++I=", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "integrity": "sha1-IA9xXmbVKiOyIalDVTSpHME61b4=", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "integrity": "sha1-pwVNzBRaln3U3I/uhFpXwTFsnfg=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "integrity": "sha1-daLotRy3WKdVPWgEpZMteqznXDk=", + "license": "MIT", + "optional": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "integrity": "sha1-vvljUfFlIAVclHq6KIAu7ePJ6ak=", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "integrity": "sha1-0qdT/ipMc7eUN9C6FIDi12AJdBk=", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "integrity": "sha1-0ucL59UaUpQlQiCR4Ny5A3TBVGw=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "integrity": "sha1-UniDbjx651dhYmli+QKg1VNS5oM=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "integrity": "sha1-8VE+r57I+hXcr0w0Gw8AXT6LR64=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "integrity": "sha1-4n28O1B7OhzqO5KAoEuLa3Jfgr4=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "integrity": "sha1-Nk4+W3of1F2SvgjGzF2JDKdZCMo=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "integrity": "sha1-fIabRfrrPfZo4ZrOBzNaBxHsVqs=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "integrity": "sha1-bOS5yr8UgnQQFwHREridxnzFLzc=", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "integrity": "sha1-SNQoYXWMlAthq+pDupopsYbWy4s=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "integrity": "sha1-IH5UiZt5ysnCbDI/wcqjLjFD8cQ=", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "integrity": "sha1-C6SKEnFZqPartYJ/IRmLmZ/9H8A=", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "integrity": "sha1-pNTMaT0YX2amr96U93KzjOXWTrU=", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "integrity": "sha1-D1gFwcbWQ1odr9wEPLB6GQUDV9s=", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "integrity": "sha1-Z3bt7OD4/KefM4Y5i1GD/yqCdUc=", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "integrity": "sha1-P28p7wNpOER8IhjTCdyHUiWGGDA=", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "integrity": "sha1-gx/gsOGoCouDkSJOojd9VSDhUn8=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "integrity": "sha1-BvmdfuvgNfu+Q94BydfpjSoKpUg=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "integrity": "sha1-25mFjmvtbnORH5Kojk7dOoxCmlI=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "integrity": "sha1-r7iGyGfjb52GuyHoeOEYX11aCTU=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "integrity": "sha1-MIVcn4OB+sag71tfMaxucQimbs8=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "integrity": "sha1-LyFErzHmetwqjjcFwgwr2XvYgxQ=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "integrity": "sha1-abmam1vSJsnrnGpz+ZD93Ul9cy4=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "integrity": "sha1-14kzCnEq+RbIgyX0/+Rl+IVxnGs=", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "integrity": "sha1-UvxzVAa9SWiCU+dOToN6wroHieM=", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "integrity": "sha1-WFYk3IKc+258CqbDyn1+baqH408=", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "integrity": "sha1-cwjfFY4GTw3YuP21iqFPoqf5E7M=", + "license": "MIT", + "optional": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "integrity": "sha1-DNcv6FUOPC6uFWqWpN3c0cisWAA=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "integrity": "sha1-z8bP/jnfOQo4Qc3iq8z5Lqp64OA=", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "integrity": "sha1-q9vL0WsSTGOAgXZjkqTWtQn3JjY=", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha1-q5tFRGblqMw6GHvqrVgEEqnFuEM=", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "integrity": "sha1-0xbkeQW9ChqTH6UOZpua9BBNFhc=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "integrity": "sha1-WThjJ9eGLMNgPrx8eBWdLcxKho8=", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "integrity": "sha1-5V9/HdQAYA3QZtu6NJxMC6yRaWQ=", + "license": "MIT", + "optional": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=", + "license": "MIT", + "optional": 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/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", + "license": "Python-2.0", + "optional": true + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha1-q5tFRGblqMw6GHvqrVgEEqnFuEM=", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "integrity": "sha1-wftl+PUBeQHN0slRhkuhhFihBgI=", + "license": "MIT", + "optional": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "license": "MIT", + "optional": true + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.35.0", + "integrity": "sha1-/7x+E88SBNsYVS6c2dSo4XxpLQc=", + "license": "MIT", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "integrity": "sha1-WDaatbWzyhF4gMD2wLDzL2lQ8k8=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "integrity": "sha1-/Ydk8O55yN2rTaZUYMZBzv7gF8U=", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "integrity": "sha1-F8Vcp9Qmcz/jxWGQa4Fzwza0Cnc=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "integrity": "sha1-giy3s6EsWiQKJPYhtaJBPiekXyY=", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "integrity": "sha1-r1smkaIrRL6EewyoFkHF+2rQFyw=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "integrity": "sha1-wrnS43TuYsWG062+qHGZsdenpro=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "integrity": "sha1-MIHa28NGBmG3UedZHX+upd853Sk=", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "integrity": "sha1-Sz2rq32OdaQpQUqWvWe/TB0T4PM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "integrity": "sha1-s3Znt7wYHBaHgiWbq0JHT79StVA=", + "devOptional": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "integrity": "sha1-hAyIA7DYBH9P8M+WMXazLU7z7XI=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "integrity": "sha1-FPja7G2B5yIdKjV+Zoyrc728p5Q=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "integrity": "sha1-5F44TkuOwWvOL9kDr3hFD2v37Jg=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "integrity": "sha1-eg7mAfYPmaIMfHxf8MgDiMEYm9Y=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "integrity": "sha1-aRKwDSxjHA0Vzhp6tXzWV/Ko+Lo=", + "license": "MIT", + "optional": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "integrity": "sha1-SnbE2u7l3wn105QOCHRC+zbOK5k=", + "license": "MIT", + "optional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@microsoft/1ds-core-js": { + "version": "4.3.9", + "integrity": "sha1-kSqK1QiFFPBodHO6ePD2rPf2eZE=", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-core-js": "3.3.9", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + } + }, + "node_modules/@microsoft/1ds-post-js": { + "version": "4.3.9", + "integrity": "sha1-LSzc16kSzWw6x14Fd/6XasSK6Ys=", + "license": "MIT", + "dependencies": { + "@microsoft/1ds-core-js": "4.3.9", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + } + }, + "node_modules/@microsoft/applicationinsights-channel-js": { + "version": "3.3.9", + "integrity": "sha1-QN0OaXRLduCae9ub2sHOMVCOha4=", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-common": "3.3.9", + "@microsoft/applicationinsights-core-js": "3.3.9", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-common": { + "version": "3.3.9", + "integrity": "sha1-IZP6OgZT5ryUeTB7+W5dp32WEUI=", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-core-js": "3.3.9", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-core-js": { + "version": "3.3.9", + "integrity": "sha1-OpijcfM1njy22QKOHmlDUqYUNiI=", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/applicationinsights-shims": { + "version": "3.0.1", + "integrity": "sha1-OGW3Os6EBbnEYYzFxXHy/jh28G8=", + "license": "MIT", + "dependencies": { + "@nevware21/ts-utils": ">= 0.9.4 < 2.x" + } + }, + "node_modules/@microsoft/applicationinsights-web-basic": { + "version": "3.3.9", + "integrity": "sha1-fHT3Q8NvMpI8tgOb6oyn+jmIhHY=", + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-channel-js": "3.3.9", + "@microsoft/applicationinsights-common": "3.3.9", + "@microsoft/applicationinsights-core-js": "3.3.9", + "@microsoft/applicationinsights-shims": "3.0.1", + "@microsoft/dynamicproto-js": "^2.0.3", + "@nevware21/ts-async": ">= 0.5.4 < 2.x", + "@nevware21/ts-utils": ">= 0.11.8 < 2.x" + }, + "peerDependencies": { + "tslib": ">= 1.0.0" + } + }, + "node_modules/@microsoft/dynamicproto-js": { + "version": "2.0.3", + "integrity": "sha1-ritAgGHj/wGpcHhCn8doMx4jklY=", + "license": "MIT", + "dependencies": { + "@nevware21/ts-utils": ">= 0.10.4 < 2.x" + } + }, + "node_modules/@nevware21/ts-async": { + "version": "0.5.4", + "integrity": "sha1-UvhEndCzsWqjF6GLRmL2+xOhNfE=", + "license": "MIT", + "dependencies": { + "@nevware21/ts-utils": ">= 0.11.6 < 2.x" + } + }, + "node_modules/@nevware21/ts-utils": { + "version": "0.12.5", + "integrity": "sha1-/jPBDRGui3JMyqox0tAQnRhgHaY=", + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "integrity": "sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "integrity": "sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "integrity": "sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "integrity": "sha1-p36nQvqyV3UUVDTrHSMoz1ATrDM=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "integrity": "sha1-XWRug7sqrPvVIYlozrNYQgtMLLM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "integrity": "sha1-p3kMjQMB209tR+b7Dw+Ugv5lLZo=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "integrity": "sha1-zUHVwnugfCF/CvTg4k29/l72IEI=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "integrity": "sha1-yM41gDrQ2EHMm25wPW+raKFE6cA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "integrity": "sha1-sSOLbiPqM3r3HH+KKV21rwwViuo=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@secretlint/node": { + "version": "10.2.2", + "integrity": "sha1-HYpu1iAXC/TymCmjqRh4aCxDxNk=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "integrity": "sha1-gsCFqxlmgGdju/btuDCYfyXU55c=", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "integrity": "sha1-nDw+L+8AZ5/M6ZeT524Z5XW3VyE=", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "integrity": "sha1-XEBEpqbJ2V4vVycNYYSTHwl51kk=", + "dev": true, + "license": "MIT", + "dependencies": { + "node-sarif-builder": "^3.2.0" + } + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "integrity": "sha1-6kPcwqvR2sMoiwVmEDYfMZ9c5uk=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "integrity": "sha1-J7F8OLNgxniIJtKPzaKKxul3LQs=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "integrity": "sha1-1gC21Eh4Wc3Tm7sc+M90RUCz96E=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "integrity": "sha1-FBLY9pn9kAGCy/TCkjqd+esyHKc=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "integrity": "sha1-cZ33+0F2a8FDNp6qDdVtjch8mVg=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "integrity": "sha1-ECk1fkTKkBphVYX20nc428iQhM0=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "integrity": "sha1-NrnbwhrVVGSG6pFz1r6gY+sXF9U=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.3", + "integrity": "sha1-62/670IeHid4PMm1JWfeIMsoBy0=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "integrity": "sha1-3rJFPo8I3K566YxiaxPd2wFVkGw=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "integrity": "sha1-KCBG8D6IbjUrLV9dpet1XgFFfz8=", + "license": "(Unlicense OR Apache-2.0)", + "optional": true + }, + "node_modules/@textlint/ast-node-types": { + "version": "15.2.2", + "integrity": "sha1-RQYy5U0I/Gd2piBnGgrim7bOwIs=", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.2.2", + "integrity": "sha1-0JMRzbqbSO7zgA3Kd6wSxOZTrTo=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.2.2", + "@textlint/resolver": "15.2.2", + "@textlint/types": "15.2.2", + "chalk": "^4.1.2", + "debug": "^4.4.1", + "js-yaml": "^3.14.1", + "lodash": "^4.17.21", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "integrity": "sha1-crcmqm+sHt7uQiVsfY3CVrM1Z38=", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/module-interop": { + "version": "15.2.2", + "integrity": "sha1-z/tBYiZYE6WBPVyAfZ+q53hjjT8=", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/resolver": { + "version": "15.2.2", + "integrity": "sha1-SHHFkKo+YztRLvpZeOlulr9/ubg=", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.2.2", + "integrity": "sha1-nkfRAh7OLO/hdJExsFThozLKvNo=", + "dev": true, + "license": "MIT", + "dependencies": { + "@textlint/ast-node-types": "15.2.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "integrity": "sha1-lYuRyZGxhnztMYvt6g4hXuBQcm4=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "integrity": "sha1-dznCMqH+6bTTzomF8xTAxtM1Sdc=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "integrity": "sha1-WWoXRyM2lNUPatinhp/Lb1bPWEE=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "integrity": "sha1-kfYpBejSPL1mIlMS8jlFSiO+v6A=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/mock-fs": { + "version": "4.13.4", + "integrity": "sha1-5z7bS0iJ1E0j8eoC1u6+UKowsJo=", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.18.1", + "integrity": "sha1-zIXuaZmyopKHOSgdL1b/QQoUDFI=", + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "integrity": "sha1-VuLMJsOXwDj6sOOpF6EtXFkJ6QE=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "integrity": "sha1-2rTRa6dWjphGxFSodk8zxdmOVSQ=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "integrity": "sha1-POOvGlUk7zJ9Lank/YttlcjXBSg=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/sinon": { + "version": "17.0.4", + "integrity": "sha1-/Zo+jgfuoaP0pvgqlyyJnld482k=", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "integrity": "sha1-X9NZL/EMHpaV03cCDAMxFswoifI=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/ungap__structured-clone": { + "version": "1.2.0", + "integrity": "sha1-Ern9SrPmqCKS1gBISSsF63W0pI8=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "integrity": "sha1-dUW6T8PAA9bHVvZR878WPY8PKbo=", + "license": "MIT", + "optional": true + }, + "node_modules/@types/vscode": { + "version": "1.101.0", + "integrity": "sha1-BiLKJuoVqvvlcNxNJZF8dcr+V4o=", + "license": "MIT", + "optional": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.43.0", + "integrity": "sha1-TXMMK+zY5H73bln2iu4PtWCSfPw=", + "license": "MIT", + "optional": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/type-utils": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.43.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "integrity": "sha1-TLX2zX1MerA2VzjHrqiIuqbX79k=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.43.0", + "integrity": "sha1-QCQVmSXnZx8Xgr3TSYvc+9SPkTc=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.43.0", + "integrity": "sha1-lY26oW+9HoHUarhuE59idnVxQPg=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.43.0", + "@typescript-eslint/types": "^8.43.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.43.0", + "integrity": "sha1-AJ68Ccxufg3WeJig6acNKVNhxrk=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.43.0", + "integrity": "sha1-5nIduhg9YXaakP/a0gKuvDg7GMg=", + "license": "MIT", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.43.0", + "integrity": "sha1-KeouNO6uW46f5PRzDFZZ+jMKoE4=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.43.0", + "integrity": "sha1-ANNKUJlQTrGyY+AizBfEJD/yMC4=", + "license": "MIT", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.43.0", + "integrity": "sha1-OeXUMSObTZB4cHKuDCKQy9PgpWI=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/project-service": "8.43.0", + "@typescript-eslint/tsconfig-utils": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.43.0", + "integrity": "sha1-XDkRM6UvhQDf2r1wJr5ypTfXtZ4=", + "license": "MIT", + "optional": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.43.0", + "integrity": "sha1-Yz00FK/sPPCg5Fg+FXX0EB71HTA=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.0", + "integrity": "sha1-9Qb/IXDllKJX+OeKoZYIjzpGoi0=", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "integrity": "sha1-0Gu7OE689sUF/eHD0O1N3/4Kr/g=", + "license": "ISC", + "optional": true + }, + "node_modules/@vscode/debugprotocol": { + "version": "1.68.0", + "integrity": "sha1-5Vi6av/hvnr/TsgkWZ8xa2HZpp0=", + "license": "MIT", + "optional": true + }, + "node_modules/@vscode/extension-telemetry": { + "version": "0.9.9", + "integrity": "sha1-WIROcqx4YOsEl4mFRcLE9YCWRl4=", + "license": "MIT", + "dependencies": { + "@microsoft/1ds-core-js": "^4.3.4", + "@microsoft/1ds-post-js": "^4.3.4", + "@microsoft/applicationinsights-web-basic": "^3.3.4" + }, + "engines": { + "vscode": "^1.75.0" + } + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "integrity": "sha1-NfDoHC4P+NrOsiPpnRtlMGwVgiw=", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.5.2", + "integrity": "sha1-99QHjoIwzpyUMi8qKcwWwXlUCF0=", + "license": "MIT", + "optional": true, + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^8.1.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/vsce": { + "version": "3.6.0", + "integrity": "sha1-cQLLhG24PtcOxxGZhq99fGnPNTg=", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.1", + "@secretlint/secretlint-formatter-sarif": "^10.1.1", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.1", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.1", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^11.0.0", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.1", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.6", + "integrity": "sha1-orEeKdq1Y3nFE+DMUmFe2tHTTNM=", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.5", + "@vscode/vsce-sign-alpine-x64": "2.0.5", + "@vscode/vsce-sign-darwin-arm64": "2.0.5", + "@vscode/vsce-sign-darwin-x64": "2.0.5", + "@vscode/vsce-sign-linux-arm": "2.0.5", + "@vscode/vsce-sign-linux-arm64": "2.0.5", + "@vscode/vsce-sign-linux-x64": "2.0.5", + "@vscode/vsce-sign-win32-arm64": "2.0.5", + "@vscode/vsce-sign-win32-x64": "2.0.5" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.5", + "integrity": "sha1-40y/kfToamz1KrwubnUISuGPbEo=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.5", + "integrity": "sha1-dEPA6DnnTwP84MwxRTMPDSqAzIc=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.5", + "integrity": "sha1-LqusfYNxKSqNIqFbP/V/GYjCnWs=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.5", + "integrity": "sha1-lvsDKcijZxhMID1iV0+akhkwItg=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.5", + "integrity": "sha1-vwc0DbH+Ncs6iiIrLaSqJTEO4lE=", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.5", + "integrity": "sha1-wEUCMqukP76t/1MJg4pWVdxwOcg=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.5", + "integrity": "sha1-I4KZJPQIZ+kNXju4Yejo+gResO4=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.5", + "integrity": "sha1-GO8nH199mzHAMSdYLBscUfJuI7Q=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.5", + "integrity": "sha1-g7iTk+RFHPp+OiGCrqQlD15xrKg=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha1-q5tFRGblqMw6GHvqrVgEEqnFuEM=", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "11.0.3", + "integrity": "sha1-nYCH5tct2zxHB7HSd4+A6j6u/NY=", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { + "version": "10.0.3", + "integrity": "sha1-z3oDFKFsTZq3OncwoOjjw1AtR6o=", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/jackspeak": { + "version": "4.1.1", + "integrity": "sha1-lodgMPRQUCBH/H6Mf8+M6BJOQ64=", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/lru-cache": { + "version": "11.2.1", + "integrity": "sha1-1CasRxUhcpxsGs2l96Yz6tqijbI=", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@vscode/vsce/node_modules/path-scurry": { + "version": "2.0.0", + "integrity": "sha1-nwUiifI62L+Tl6KgQl57hhXFhYA=", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "integrity": "sha1-o2CJi8QV7arEbIJB9jg5dbkwuBY=", + "license": "MIT", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "integrity": "sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=", + "license": "MIT", + "optional": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "integrity": "sha1-48121MVI7oldPD/Y3B9sW5Ay56g=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "integrity": "sha1-N9mlx3ava8ktf0+VEOukwKYNEaY=", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "integrity": "sha1-N2ETQOsiQ+cMxgTK011jJw1IeBs=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "integrity": "sha1-APwZ9JG7sY4dSBuXhoIE+SEJv+c=", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "integrity": "sha1-YCFu6kZNhkWXzigyAAc4oFiWUME=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "integrity": "sha1-eQxYsZuhcgqEIFtXxhjVrYUklz4=", + "license": "ISC", + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "integrity": "sha1-SDFDxWeu7UeFdZwIZXhtx319LjE=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "license": "MIT" + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "integrity": "sha1-OLnv18WsdDVP5Ojb5CaX2wuOhaU=", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "integrity": "sha1-GxtEAWClv3rUC2UPCVljSBkDkwo=", + "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" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "integrity": "sha1-9uFKl4WNMnJSIAJC1Mz+UixEVSI=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "integrity": "sha1-w2s+a1xZ5iFgVwmwmc2o3agkzHI=", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "integrity": "sha1-RRU1JkGCvsL7vIOmKrmM8R2fezo=", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha1-VqmzbqllwAxak+8x6xEaDxEFaWc=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true, + "license": "ISC" + }, + "node_modules/boundary": { + "version": "2.0.0", + "integrity": "sha1-FpyLHw1Ezywlk4lnoyjzfgpOXvw=", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "integrity": "sha1-VPxTI3phPYVMe9N0Y6rRffhyFOc=", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "integrity": "sha1-SQMy9AkZRSJy1VqEgK3AxEE1h4k=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=", + "license": "ISC", + "optional": true + }, + "node_modules/buffer": { + "version": "5.7.1", + "integrity": "sha1-umLnwTEzBTWCGXFghRqPZI6Z7tA=", + "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" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "integrity": "sha1-87lrNBYNZDGhnXaIE1r3z7h5eIk=", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8": { + "version": "9.1.0", + "integrity": "sha1-Dle6Ornllgqx1lC0qG9x5Ty2gRI=", + "license": "ISC", + "optional": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=14.14.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "integrity": "sha1-S1QowiK+mF15w9gmV0edvgtZstY=", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "integrity": "sha1-I43pNdKippKSjFOMfM+pEGf9Bio=", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "integrity": "sha1-VoW5XrIJrJwMF3Rnd4ychN9Yupo=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cheerio": { + "version": "1.1.2", + "integrity": "sha1-Jq936JM2yBxj6oMZf4aLTL01E2k=", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.12.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "integrity": "sha1-TYZzKGuBJsoqjkJ0DV48SISuIbQ=", + "dev": true, + "license": "BSD-2-Clause", + "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.6.0", + "integrity": "sha1-GXxsxmnvKo3F57TZfuTgksPrDVs=", + "license": "MIT", + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "integrity": "sha1-JKSDHs9aawHd6zL7caSyCIsNzjg=", + "license": "MIT", + "optional": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "integrity": "sha1-F3Oo9LnE1qwxVj31Oz/B15Ri/kE=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "integrity": "sha1-DASwddsCy/5g3I5s8vVIaxo2CKo=", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "integrity": "sha1-V1+Te8QECiCuJzUqbQfJxadBmB8=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "integrity": "sha1-AUI7NvUBJZ/arE0OTWDJbJkVhdM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "integrity": "sha1-S1YPZJ/E6RjdCrdc9JYei8iC2Co=", + "license": "MIT", + "optional": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "integrity": "sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U=", + "license": "MIT", + "optional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "integrity": "sha1-ilj+ePANzXDDcEUXWd+/rwPo7p8=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "integrity": "sha1-Abbo0WNje7LdbJgspO1lhjaCeG4=", + "dev": true, + "license": "BSD-2-Clause", + "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.2.2", + "integrity": "sha1-zcyPm2l3cZ/fvR3nrsJKv3Vrneo=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "integrity": "sha1-5ai8bLxMbNPmQwiwaTo9T6VQGJs=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "integrity": "sha1-qkcte/Zg6xXzSU79UxyrfypwmDc=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "integrity": "sha1-yjh2Et234QS9FthaqwDV7PCcZvw=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "integrity": "sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE=", + "license": "MIT", + "optional": true + }, + "node_modules/default-browser": { + "version": "5.2.1", + "integrity": "sha1-e3umEgT/PkJbVWhprm0+nZ8XEs8=", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "integrity": "sha1-odmL+WDBUILYo/pp6DFQzMzDryY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "integrity": "sha1-27Ga37dG1/xtc0oGty9KANAhJV8=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "integrity": "sha1-8EcVuLqBXlO02BCWVbZQimhlp+g=", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "integrity": "sha1-Jt7QR80RebeLlTfV73JVA84a5TE=", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "integrity": "sha1-5BuALh7t+fbK4YPOXmIteJ19jlM=", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha1-XEXo6GmVJiYzHXqrMm0B2vZdWJ0=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "integrity": "sha1-zDhff3UfHR/GUMITdIBCVFOMfTE=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "integrity": "sha1-7b/itmiwwdl8JLrw8QYrEyIhvHg=", + "dev": true, + "license": "BSD-2-Clause", + "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/dunder-proto": { + "version": "1.0.1", + "integrity": "sha1-165mfh3INIL4tw/Q9u78UNow9Yo=", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "integrity": "sha1-aWzi7Aqg5uqTo5f/zySqeEDIJ8s=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "integrity": "sha1-rg8PothQRe8UqBfao86azQSJ5b8=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "integrity": "sha1-ORPE7qmqRYbhe80l1k1e3xeQZXo=", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "integrity": "sha1-OW7JesIs5aA3ukSvGZKsnUanuBk=", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "integrity": "sha1-c0TXEd6kDgt0q8LtSXeHQ8ztsIw=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "integrity": "sha1-m19MXAdrh4fHj+VAOSznaoiFW0Q=", + "license": "MIT", + "optional": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "integrity": "sha1-XSaOpecRPsdMTQM7eepaNaSI+0g=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "integrity": "sha1-jobGaxgPNjx6sxF4fgJZZl9FqfE=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "integrity": "sha1-mD6y+aZyTpMD9hrd8BHHLgngsPo=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "integrity": "sha1-BfdaJdq5jk+x3NXhRywFRtUFfI8=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "integrity": "sha1-HE8sSDcydZfOadLKGQp/3RcjOME=", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "integrity": "sha1-8x274MGDsAptJutjJcgQwP0YvU0=", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "integrity": "sha1-FauOOa5s3GTCT/iiwK71s/2fqXY=", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/esbuild-register": { + "version": "3.6.0", + "integrity": "sha1-zycM+md7rrvAAQrAJLgjy/cjo20=", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "integrity": "sha1-ARo/aYVroYnf+n3I/M6Z0qh5A+U=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "integrity": "sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.35.0", + "integrity": "sha1-eokFS3ue4d/RtiA12M51VHdz9H4=", + "license": "MIT", + "optional": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.35.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "integrity": "sha1-FXNM5K+MJ3jMMvCwGzewtc0ey5c=", + "license": "MIT", + "optional": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "integrity": "sha1-iOZGogf61hQ2/6OetQUUcgBlXII=", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "integrity": "sha1-TP6mD+fdCtjoFuHtAmwdUlG1EsE=", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=", + "license": "MIT", + "optional": 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/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha1-q5tFRGblqMw6GHvqrVgEEqnFuEM=", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "integrity": "sha1-bSN9mQg5UMeSkPJMdkKj3poo+eM=", + "license": "ISC", + "optional": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "license": "MIT", + "optional": true + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "integrity": "sha1-1U9JSdRikAWh+haNk3w/8ffiqDc=", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "integrity": "sha1-kUGSNPgE2FKoLc7sPhbNwiz52uc=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "integrity": "sha1-eteWTWeauyi+5yzsY3WLHF0smSE=", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "integrity": "sha1-LupSkHAvJquP5TcDcP+GyWXSESM=", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "integrity": "sha1-bhSz/O4POmNA7LV9LokYaSBSpHw=", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "integrity": "sha1-0G1YXOjbqQoWsFBcVDw8z7OuuBg=", + "devOptional": true, + "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.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=", + "license": "MIT", + "optional": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "license": "MIT", + "optional": true + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "integrity": "sha1-Zu7P9sdkwN+bdi5iyn7c+1O07fo=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", + "integrity": "sha1-1Q6rqAPIhGqIPBZJKCHrzSzaVfU=", + "devOptional": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "integrity": "sha1-d4e93PETG/+5JjbGlFe7wO3W2B8=", + "license": "MIT", + "optional": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "integrity": "sha1-RCZdPKwH4+p9wkdRY4BkN1SgUpI=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "integrity": "sha1-TJKBnstwg1YeT0okCoa+UZj1Nvw=", + "license": "MIT", + "optional": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "integrity": "sha1-jKb+MyBp/6nTJMMnGYxZglnOskE=", + "license": "BSD-3-Clause", + "optional": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "integrity": "sha1-Ds45/LFO4BL0sEEL0z3ZwfAREnw=", + "license": "MIT", + "optional": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "integrity": "sha1-Z8j62VRUp8er6/dLt47nSkQCM1g=", + "license": "ISC", + "optional": true + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "integrity": "sha1-Mujp7Rtoo0l777msK2rfkqY4V28=", + "devOptional": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "integrity": "sha1-eEzczgZpqdaOlNEaxO6pgIjt0sQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "integrity": "sha1-unofl6hflMbbLlL/aVcNs2cdWnQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "license": "ISC", + "optional": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "integrity": "sha1-ysZAd4XQNnWipeGlMFxpezR9kNY=", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "integrity": "sha1-LALYZNl/PqbIgwxGTL0Rq26rehw=", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", + "license": "ISC", + "optional": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.1", + "integrity": "sha1-uFiJ13mIGmUd/ecdN5bdvpVJASs=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "integrity": "sha1-dD8OO2lkqTpUke0b/6rgVNf5jQE=", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "integrity": "sha1-FQs/J0OGnvPoUewMSdFbHRTQDuE=", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "10.4.5", + "integrity": "sha1-9NnwuQ/9urCcnXf18ptCYlF7CVY=", + "license": "ISC", + "optional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=", + "devOptional": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "integrity": "sha1-iY10E8Kbq89rr+Vvyt3thYrack4=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "integrity": "sha1-E4t453z1qNeU4yexXc6Avx+wpz4=", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "integrity": "sha1-TLX2zX1MerA2VzjHrqiIuqbX79k=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "integrity": "sha1-ifVrghe9vIgCvSmd9tfxCB1+UaE=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "integrity": "sha1-QYPk6L8Iu24Fu7L30uDI9xLKQOM=", + "devOptional": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "integrity": "sha1-+y8dVeDjoYSa7/yQxPoN1ToOZsY=", + "license": "MIT", + "optional": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "integrity": "sha1-/JxqeDoISVHQuXH+EBjegTcHozg=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "integrity": "sha1-LNxC1AvvLltO6rfAGnPFTOerWrw=", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "integrity": "sha1-AD6vkb563DcuhOxZ3DclLO24AAM=", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=", + "license": "MIT", + "optional": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "integrity": "sha1-gnuChn6f8cjQxNnVOIA5fSyG0iQ=", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "integrity": "sha1-39YAJ9o2o238viNiYsAKWCJoFFM=", + "license": "MIT", + "optional": true + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "integrity": "sha1-d60kkDe2a/jMmcbihu9zuDrrYh0=", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "integrity": "sha1-wow0pDN5yn9h0HQTCy9fcCCjBpQ=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "integrity": "sha1-mosfJGhmwChQlIZYX2K48sGMJw4=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "integrity": "sha1-2o3+rH2hMLBcK6S1nJts1mYRprk=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "integrity": "sha1-pS+AvzjaGVLrXGgXkHGYcaGnJQE=", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "integrity": "sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I=", + "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" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "5.3.2", + "integrity": "sha1-PNQOcp82Q/2HywTlC/DrcivFlvU=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "license": "MIT", + "optional": true + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "integrity": "sha1-nOy1ZQPAraHydB271lRuSxO1fM8=", + "license": "MIT", + "optional": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/index-to-position": { + "version": "1.1.0", + "integrity": "sha1-LlC9VMgEC91tmz2V7CqP7fhrTUQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "license": "ISC", + "optional": true + }, + "node_modules/ini": { + "version": "1.3.8", + "integrity": "sha1-op2kJbSIBvNHZ6Tvzjlyaa8oQyw=", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=", + "license": "MIT", + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "integrity": "sha1-kAk6oxBid9inelkQ265xdH4VogA=", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "integrity": "sha1-ZPYeQsu7LuwgcanawLKLoeZdUIQ=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "integrity": "sha1-6B+6aZZi6zHb2vJnZqYdSBRxfqQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "integrity": "sha1-QMV2FFk4JtoRAK3mBZd41ZfxbpA=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "integrity": "sha1-ReQuN/zPH0Dajl927iFRWEDAkoc=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "integrity": "sha1-PybHaoCVk7Ur+i7LVxDtJ3m1Iqc=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "integrity": "sha1-4cZX45wQCQr8vt7GFyD2uSTDy9I=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "license": "MIT", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "devOptional": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "integrity": "sha1-LRZsSwZE1Do58Ev2wu3R5YXzF1Y=", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "integrity": "sha1-kIMFusmlvRdaxqdEier9D8JEWn0=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "license": "MIT", + "optional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "integrity": "sha1-y0U1FitXhKpiPO4hpyUs8sgHrJM=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "integrity": "sha1-5uE/6/HBaFEAriZICaT49G4B39M=", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "integrity": "sha1-iDOp2Jq0rN5hiJQr0cU7Y5DtWoo=", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "integrity": "sha1-2ugS/bOCX6MGYJqHFzg8UMNqBTc=", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "integrity": "sha1-kziAKjDTtmBfvgYT4JQAjKjAWhM=", + "license": "MIT", + "optional": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "integrity": "sha1-rnvLNlard6c7pcSb9lTzjmtoYOI=", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "license": "MIT", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "integrity": "sha1-eM1vGhm9wStz21rQxh79ZsHikoM=", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "integrity": "sha1-8qUktPf9EePXkeVZl3rWC5i3mLQ=", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "integrity": "sha1-fCZb0bZd5pd0eDAAh8mfHIQ4P2I=", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "integrity": "sha1-Zf+R9KvvF4RpfUCVK7GZjFBMqvM=", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "integrity": "sha1-NK7nDrGOofrsL1iSCKFX0f6wkcI=", + "license": "(MIT OR GPL-3.0-or-later)", + "optional": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/just-extend": { + "version": "6.2.0", + "integrity": "sha1-uBar+z1n7oYEgudAFWRnJVgWOUc=", + "license": "MIT", + "optional": true + }, + "node_modules/jwa": { + "version": "1.4.2", + "integrity": "sha1-FgEaxttI3nsQJ3fleJeQFSDux7k=", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "integrity": "sha1-ABCZ82OUaMlBQADpmZX6UvtHgwQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "integrity": "sha1-TGIlcI9RtQy/d8Wq6BchlkwpGMs=", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "integrity": "sha1-qHmpnilFL5QkOfKkBeOvizHU3pM=", + "license": "MIT", + "optional": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "integrity": "sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "integrity": "sha1-rkViwAdHO5MqYgDUAyaN0v/8at4=", + "license": "MIT", + "optional": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "integrity": "sha1-3Pgt7lRfRgdNryAMfBxaCOD0D2o=", + "license": "MIT", + "optional": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "integrity": "sha1-nvI4v6bccL2Of5VytS02mvVptCE=", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "integrity": "sha1-VTIeswn+u8WcSAHZMackUqaB0oY=", + "license": "MIT", + "optional": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", + "license": "MIT", + "optional": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "integrity": "sha1-P727lbRoOsn8eFER55LlWNSr1QM=", + "license": "MIT", + "optional": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "integrity": "sha1-w8IwencSd82WODBfkVwprnQbYU4=", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "integrity": "sha1-PDxZkog8Yz20cUzLTXtZNdmLfUU=", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "integrity": "sha1-oN10voHiqlwvJ+Zc4oNgXuTit/k=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "integrity": "sha1-gGduwEMwJd0+F+6YPQ/o3loiN+A=", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "integrity": "sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "integrity": "sha1-1m+hjzpHB2eJMgubGvMr2G2fogI=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "integrity": "sha1-u6vNwChZ9JhzAchW4zh85exDv3A=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "integrity": "sha1-OBqHG2KnNEUGYK497uRIE/cNlZo=", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "integrity": "sha1-rL4rM0n5m53qyn+3Dki4PpTmcHY=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "integrity": "sha1-LR1Zr5wbEpgVrMwsRqAipc4fo8k=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "integrity": "sha1-10+d1rV9g9jpjPuCEzsDl4vJKeU=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "integrity": "sha1-waRk52kzAuCCoHXO4MBXdBrEdyw=", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "integrity": "sha1-k6libOXl5mvU24aEnnUV6SNApwc=", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "integrity": "sha1-+hDJEVzG2IZb4iG6R+6b7XhgERM=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/mocha": { + "version": "10.8.2", + "integrity": "sha1-jYNC0BbtQRsSpCnrcxuCX5Ya+5Y=", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", + "license": "Python-2.0", + "optional": true + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha1-oCZe5lVHb8gHrqnfPfjfd4OAi08=", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "integrity": "sha1-04j2Vlk+9wjuPjRkD9+5mp/Rwz4=", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "integrity": "sha1-wftl+PUBeQHN0slRhkuhhFihBgI=", + "license": "MIT", + "optional": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha1-HPy4z1Ui6mmVLNKvla4JR38SKpY=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "integrity": "sha1-zW/BfihQDP9WwbhsCn/UpUpzAFw=", + "license": "MIT", + "optional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha1-HIK/D2tqZur85+8w43b0mhJHf2Y=", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "integrity": "sha1-LrfcOwKJcY/ClfNidThFxBoMlO4=", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mock-fs": { + "version": "5.5.0", + "integrity": "sha1-lKRtKZqqWI5zWiAcvoI8h26R84U=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "integrity": "sha1-V0yBOM4dK1hh8LRFedut1gxmFbI=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "integrity": "sha1-FjDEKyJR/4HiooPelqVJfqkuXg0=", + "dev": true, + "license": "ISC" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "integrity": "sha1-E8IsAYf8/MzhRhhEE2NypH3cAn4=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "license": "MIT", + "optional": true + }, + "node_modules/nise": { + "version": "6.1.1", + "integrity": "sha1-eOqTzEm+Ei5Ey3yP31l7Dod4tko=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", + "just-extend": "^6.2.0", + "path-to-regexp": "^8.1.0" + } + }, + "node_modules/node-abi": { + "version": "3.77.0", + "integrity": "sha1-OtkNXJ1FZjQg5apP9Y2/TjYlQZo=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "integrity": "sha1-UqGgtHUZPgko6Y4EJqDRJUeCt38=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-sarif-builder": { + "version": "3.2.0", + "integrity": "sha1-ugCJldixZVcMPzgwDlYpmpNTHbE=", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "integrity": "sha1-p7wiFn/iQCVBK8/wqWUet2iwNQY=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "integrity": "sha1-m3UaysCXdXZn8wEUYH73tmH/Txc=", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "integrity": "sha1-QQ/IoXtw5ZgBPfJXwkRrfzOD8Rk=", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "integrity": "sha1-yeq0KO/842zWuSySS9sADvHx7R0=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "integrity": "sha1-g3UmXiG8IND6WCwi4bE0hdbgAhM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "integrity": "sha1-nxbJLYye9RIOOs2d2ZV8zuzBq2A=", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.2.0", + "integrity": "sha1-udhVvgB2IOgLb7BfrJgUH+Yttzw=", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "integrity": "sha1-fqHBpdkddk+yghOciP4R4YKjpzQ=", + "license": "MIT", + "optional": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "integrity": "sha1-j7u3FRr+M7VA3RU/Fx/6i9OOmGE=", + "license": "MIT", + "optional": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "integrity": "sha1-sSOLbiPqM3r3HH+KKV21rwwViuo=", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.5.0", + "integrity": "sha1-viNJi54520diJtjoHkZ/Oayia3g=", + "license": "MIT", + "optional": true + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "integrity": "sha1-CfCrDebTdE1I0mXruY9l0R8qmzo=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "integrity": "sha1-u5Xl8FMiZRysMMD+tkBPnyqKlDk=", + "license": "MIT", + "optional": true, + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "integrity": "sha1-2CSYS2FsKSouGYIH1KYJmDhC9xQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "integrity": "sha1-tbuOIWXOJ11NQ0dt0nAK2Qkdttw=", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "integrity": "sha1-4drMvnjQ0TiMoYxk/qOOPlfjcGs=", + "license": "MIT", + "optional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "integrity": "sha1-g8gxXGeFAF470CGDlBHJ4RDm2DQ=", + "license": "MIT", + "optional": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.3", + "integrity": "sha1-esIQotNvgewotzYTSBD3ukQYzbY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "integrity": "sha1-TxRxoBCCeob5TP2bByfjbSZ95QU=", + "devOptional": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "1.0.11", + "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8=", + "license": "(MIT AND Zlib)", + "optional": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", + "license": "MIT", + "optional": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "integrity": "sha1-iKGVohVwJROaIxek8vklK2EwTtU=", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "integrity": "sha1-SNVdtzfDKHzUg14X+hP+rOHEHvg=", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "integrity": "sha1-1+Ik+nI5nHoXUJn0X8KtAksF7AU=", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "integrity": "sha1-tagGVI7Yk6Q+JMy0L7t4BpMR6Bs=", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "integrity": "sha1-18IOrcN5aNJy4sAmYP/5LdJ+YOE=", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "integrity": "sha1-wow0pDN5yn9h0HQTCy9fcCCjBpQ=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "integrity": "sha1-eWCmaIiFlKByCxKpEdGnQqufEdI=", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "integrity": "sha1-QQ/IoXtw5ZgBPfJXwkRrfzOD8Rk=", + "license": "ISC", + "optional": true + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "integrity": "sha1-qoGKaYH5kyEAOgiYfTzsnDR0zR8=", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "integrity": "sha1-Lxu2eRqRzpkZTK7eXWxZIO2B61E=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "integrity": "sha1-PTIa8+q5ObCDyPkpodEs2oHCa2s=", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "integrity": "sha1-O6ODNzNkbZ0+SZWUbBNlpn+wekI=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "integrity": "sha1-Gm+hajjRKhkB4DIPoBcFHFOc47E=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "integrity": "sha1-1jCrrSsUdEPyCiEpF76uaLgJLuw=", + "dev": true, + "license": "MIT", + "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": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "integrity": "sha1-3rxkidem5rDnYRiIzsiAM30xY5Y=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "integrity": "sha1-zNoCoQA+u7K/2m+DoHSXj2CLk5M=", + "license": "MIT", + "optional": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.2.0", + "integrity": "sha1-kqxI4j5kl7rk12HUPRet7RgFpG0=", + "license": "MIT", + "optional": true, + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", + "license": "MIT", + "optional": true + }, + "node_modules/pump": { + "version": "3.0.3", + "integrity": "sha1-FR2XnxopZo3AAl7FiaRVtTKCJo0=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "integrity": "sha1-AnQi4vrsCyXhVJw+G9gwm5EztuU=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "integrity": "sha1-a1PlatdViCNOefSv+pCXLH3Yzbc=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "integrity": "sha1-xj+kBoDSxclBQSoOiZyJr2DAqTA=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "integrity": "sha1-SSkii7xyTfrEPg77BYyve2z7YkM=", + "devOptional": 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" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "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-config-loader": { + "version": "4.1.3", + "integrity": "sha1-E1KYa4otjZbW/QVKW7GaYMV2h2o=", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "js-yaml": "^4.1.0", + "json5": "^2.2.2", + "require-from-string": "^2.0.2" + } + }, + "node_modules/rc-config-loader/node_modules/argparse": { + "version": "2.0.1", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/rc-config-loader/node_modules/js-yaml": { + "version": "4.1.0", + "integrity": "sha1-wftl+PUBeQHN0slRhkuhhFihBgI=", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "integrity": "sha1-sbgfsVEE9duxIba73um7yXOfVps=", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "integrity": "sha1-G7mlHII6r51zqL/NPRoj3elLDOQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "integrity": "sha1-kRJegEK7obmIf0k0X2J3Anzovps=", + "license": "MIT", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "license": "MIT", + "optional": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "integrity": "sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc=", + "license": "MIT", + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "integrity": "sha1-iaf92TgmEmcxjq/hT5wy5ZjDaQk=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "integrity": "sha1-B2bZVpnvrLFBUJk/VbrwlT6h6+c=", + "license": "MIT", + "optional": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "integrity": "sha1-D+E7lSLhRz9RtVjueW4I8R+bSJ8=", + "devOptional": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "integrity": "sha1-5aVTwr/9Yg4WnSdsHNjxtkd4++s=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "integrity": "sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4=", + "devOptional": 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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=", + "devOptional": 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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "integrity": "sha1-RMyJiDd/EmME07P8EBDHM7kp7w8=", + "dev": true, + "license": "ISC" + }, + "node_modules/secretlint": { + "version": "10.2.2", + "integrity": "sha1-wM+ZcVOivvC2U4dNyHAw2qajUUA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "integrity": "sha1-Z9mf3NNc7CHm+Lh6f9UVoz+YK1g=", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "integrity": "sha1-3voeBVyDv21Z6oBdjahiJU62psI=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "license": "MIT", + "optional": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "integrity": "sha1-w/z/nE2pMnhIczNeyXZfqU/2a8k=", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "integrity": "sha1-EMtZhCYxFdO3oOM2WR4pCoMK+K0=", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "integrity": "sha1-1rtrN5Asb+9RdOX1M/q0xzKib0I=", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "integrity": "sha1-Ed2hnVNo5Azp7CvcH7DsvAeQ7Oo=", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "integrity": "sha1-lSGIwcvVRgcOLdIND0HArgUwywQ=", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "integrity": "sha1-9Gl2CCujXCJj8cirXt/ibEHJVS8=", + "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" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "integrity": "sha1-SjnbVJKHyXnTUhEvoD/Zn9a8NUM=", + "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" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sinon": { + "version": "19.0.5", + "integrity": "sha1-ZP0vhHhqBD9yEkbECza+9MS3azw=", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.5", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "7.0.0", + "integrity": "sha1-P7NNOHzXbYA/buvqZ7kh2rAYKpo=", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "license": "MIT", + "optional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "integrity": "sha1-vjrd3N8JrDjuvo3Nx7GlenWwlc4=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "integrity": "sha1-UA6N0P1VsFgVCGJVsxla3ypF/ms=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "integrity": "sha1-T1qwZo8AWeNPnADc4zF4ShLeTpw=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "integrity": "sha1-XWB9J/yAb2bXtkp2ZlD6iQ8E7WY=", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "integrity": "sha1-q/Wgim9dcnlVm2afR/CkPo80ZO8=", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "integrity": "sha1-OQA39ExK4aGuU1xf443Dq6jZl74=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "license": "MIT", + "optional": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "integrity": "sha1-JpxxF9J7Ba0uU2gwqOyJXvnG0BA=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "integrity": "sha1-JpxxF9J7Ba0uU2gwqOyJXvnG0BA=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "integrity": "sha1-Eyh1q95njH6o1pFTPy5+Irt0Tbo=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "integrity": "sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/structured-source": { + "version": "4.0.0", + "integrity": "sha1-DJ5Z7kPe3Y/GCmNzH2DjWBAqSUg=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/supports-color": { + "version": "9.4.0", + "integrity": "sha1-F7/PaGKI9THbPeoyFVEGIcy1WVQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "integrity": "sha1-uOSFsXloHepJah56vfiYW9MUVGE=", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "6.9.0", + "integrity": "sha1-UAQK+mJkFBx1ZrO4HU2CxHqGaPU=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.2.3", + "integrity": "sha1-S2e2NbLZdXigaicT0vBIAMI36Zs=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar-fs": { + "version": "2.1.3", + "integrity": "sha1-+zuIQ6JrbxOgjmBveSKHXrH7v5I=", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha1-rK2EwoQTawYNw/qmRHSqmuvXcoc=", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha1-VqmzbqllwAxak+8x6xEaDxEFaWc=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "integrity": "sha1-Xz5QMpQg+tl9B9Yk998YUdgpY/E=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "integrity": "sha1-BKhphmHYBepvopO2y55jrARO8V4=", + "license": "ISC", + "optional": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha1-q5tFRGblqMw6GHvqrVgEEqnFuEM=", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "integrity": "sha1-uN8PuAK7+o6JvR2Ti04WV47UTys=", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "integrity": "sha1-hkU10J9JAmFQyW8LDXnx+ghp2xU=", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "integrity": "sha1-sGvNI/DzyDV7QmiRcm0WAVq/2Pg=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "integrity": "sha1-WV9wlORu7TZME/0j51+VE9Kbr5E=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "integrity": "sha1-YS7+TtI11Wfoq6Xypfq3AoCt6D8=", + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "integrity": "sha1-cvExSzSlsZLbASMk3yzFh8pH+Sw=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "integrity": "sha1-B7ggO/pwVsBlcFDjzNLDdzC6uPE=", + "license": "MIT", + "optional": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "integrity": "sha1-auHI5XMSc8K/H1itOcuuLJGkbFg=", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "integrity": "sha1-aQbwLjyR6NhRV58lWr8P1ggAoE0=", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "integrity": "sha1-2TRQzd7FFUotXKvjuBArgzFvsqY=", + "license": "Apache-2.0", + "optional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.43.0", + "integrity": "sha1-M1rBaoWfOF37IwIuDYKYliNk0Jk=", + "license": "MIT", + "optional": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.43.0", + "@typescript-eslint/parser": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/utils": "8.43.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "integrity": "sha1-+NP30OxMPeo1p+PI76TLi0XJ5+4=", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.7", + "integrity": "sha1-lw4zljr5p92iKPF+voOZ5fvmOhA=", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.15.0", + "integrity": "sha1-dIUAdUmtF4K3yrKr+qHBqnt14QY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "integrity": "sha1-aR0ArzkJvpOn+qE75hs6W1DvEss=", + "license": "MIT", + "optional": true + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "integrity": "sha1-Tv1FyFpp4N1XbSVTL7+iKqXIoQQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "integrity": "sha1-Fo78IYCWTmOG0GHglN9hr+I5sY0=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "integrity": "sha1-K8lHuVNlJIfkYAlJ+wkeOujNkZs=", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "integrity": "sha1-tkLiGiZGgI/6F4xMX9o5hE4Szec=", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "license": "MIT", + "optional": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "integrity": "sha1-4YjUyIU8xyIiA5LEJM1jfzIpPzA=", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "integrity": "sha1-uVcqv6Yr1VbBbXX968GkEdX/MXU=", + "license": "ISC", + "optional": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "integrity": "sha1-id8ekhsU03UVqrXkLtSsBRXKssE=", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "integrity": "sha1-9D36NftR52PRfNlNzKDJRY81q/k=", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "integrity": "sha1-zf4gJncmyNTbg53B6dGBbhKW6FQ=", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha1-HPy4z1Ui6mmVLNKvla4JR38SKpY=", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "integrity": "sha1-hkqLjzkINVcvThO9n4MT0OOsS+o=", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "integrity": "sha1-MnNnbwzy6rQLP0TQhay7fwijnYo=", + "license": "MIT" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "integrity": "sha1-0PTvdpkF1CbhaI8+NDgambYLduU=", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "integrity": "sha1-vBv5SphdxQOI1UqSWKxAXDyi/Ao=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "integrity": "sha1-0sRcbdT7zmIaZvE2y+Mor9BBCzQ=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "integrity": "sha1-Bg9zs50Mr5fG22TaAEzQG0wJlUQ=", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "integrity": "sha1-VtwiNo7lcPrOG0mBmXXZuaXq0hQ=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "integrity": "sha1-wETV3MUhoHZBNHJZehrLHxA8QEE=", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "integrity": "sha1-hAyIA7DYBH9P8M+WMXazLU7z7XI=", + "devOptional": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "integrity": "sha1-FPja7G2B5yIdKjV+Zoyrc728p5Q=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "license": "ISC", + "optional": true + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "integrity": "sha1-h4PU32cdTVA2W+LuTHGRegVXuqs=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "integrity": "sha1-2UQGMfuy7YACA/rRBvJyT2LEk7c=", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "integrity": "sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU=", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "integrity": "sha1-mR3zmspnWhkrgW4eA2P5110qomk=", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "integrity": "sha1-kJa87r+ZDSG7MfqVFuDt4pSnfTU=", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "integrity": "sha1-8TH5ImkRrl2a04xDL+gJNmwjJes=", + "license": "MIT", + "optional": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "integrity": "sha1-o9ZdPdZZpbCTeFDoYJ8i//orXDU=", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "integrity": "sha1-ApTrPe4FAo0x7hpfosVWpqrxChs=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 586dd1f573..bb12dafd7f 100644 --- a/package.json +++ b/package.json @@ -1,84 +1,1260 @@ { - "name": "PowerShell", - "displayName": "PowerShell", - "version": "0.1.0", - "publisher": "ms-vscode", - "description": "Develop PowerShell scripts in Visual Studio Code!", - "engines": { "vscode": "0.10.x" }, - "license":"SEE LICENSE IN LICENSE.txt", - "homepage": "https://github.com/PowerShell/vscode-powershell/README.md", - "categories": [ - "Languages", - "Snippets", - "Debuggers", - "Linters" - ], - "icon": "images/PowerShell_icon.png", - "galleryBanner": { - "color": "#ACD1EC", - "theme": "light" - }, - "repository": { - "type": "git", - "url": "https://github.com/PowerShell/vscode-powershell.git" - }, - "main": "./out/main", - "activationEvents": ["onLanguage:PowerShell"], - "dependencies": { - "vscode-languageclient": "0.10.7" - }, - "devDependencies": { - "vscode": "0.10.0" - }, - "scripts": { - "vscode:prepublish": "node ./node_modules/vscode/bin/compile", - "compile": "node ./node_modules/vscode/bin/compile -watch -p ./" + "name": "powershell", + "displayName": "PowerShell", + "version": "2025.5.0", + "preview": false, + "publisher": "ms-vscode", + "description": "Develop PowerShell modules, commands and scripts in Visual Studio Code!", + "engines": { + "vscode": "^1.101.0" + }, + "author": "Microsoft Corporation", + "license": "SEE LICENSE IN LICENSE.txt", + "homepage": "https://github.com/PowerShell/vscode-powershell/blob/main/README.md", + "categories": [ + "Debuggers", + "Formatters", + "Programming Languages", + "Snippets", + "Linters", + "Themes" + ], + "keywords": [ + "PowerShell", + "pwsh" + ], + "icon": "media/PowerShell_Icon.png", + "galleryBanner": { + "color": "#ACD1EC", + "theme": "light" + }, + "badges": [ + { + "url": "https://github.com/PowerShell/vscode-powershell/actions/workflows/ci-test.yml/badge.svg", + "href": "https://github.com/PowerShell/vscode-powershell/actions/workflows/ci-test.yml?query=branch%3Amain", + "description": "Build Status" }, - "contributes": { - "languages": [{ - "id": "PowerShell", - "extensions": [ ".ps1", ".psm1", ".psd1", ".pssc", ".psrc" ], - "aliases": [ "PowerShell", "powershell", "ps", "ps1" ] - }], - "grammars": [{ - "language": "PowerShell", - "scopeName": "source.powershell", - "path": "./syntaxes/PowerShell.tmLanguage" - }], - "snippets": [ - { - "language": "PowerShell", - "path": "./snippets/PowerShell.json" - } - ], - "debuggers": [ - { - "type": "PowerShell", - "enableBreakpointsFor": { "languageIds": ["PowerShell"] }, - "program": "bin/Microsoft.PowerShell.EditorServices.Host.DebugAdapter.cmd" - } - ], - "configuration": { - "type": "object", - "title": "PowerShell Configuration", - "properties": { - "PowerShell.editorServicesHostPath": { - "type": "string", - "default": "../bin/Microsoft.PowerShell.EditorServices.Host.exe", - "description": "Specifies the path to the PowerShell Editor Services host executable." - }, - "PowerShell.waitForDebugger": { - "type": "boolean", - "default": false, - "description": "Launches the language service with the /waitForDebugger flag to force it to wait for a .NET debugger to attach before proceeding." - }, - "PowerShell.enableLogging": { - "type": "boolean", - "default": true, - "description": "Enables diagnostic logging for the extension." - } - } - } - }, - "private": true -} \ No newline at end of file + { + "url": "https://img.shields.io/discord/180528040881815552.svg?label=%23vscode&logo=discord&logoColor=white", + "href": "https://aka.ms/powershell-vscode-discord", + "description": "Join the chat on Discord" + }, + { + "url": "https://badges.gitter.im/PowerShell/vscode-powershell.svg", + "href": "https://gitter.im/PowerShell/vscode-powershell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge", + "description": "Join the chat on Gitter" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/PowerShell/vscode-powershell.git" + }, + "bugs": { + "url": "https://github.com/PowerShell/vscode-powershell/issues" + }, + "activationEvents": [ + "onDebugResolve:PowerShell", + "onLanguage:powershell", + "onCommand:PowerShell.PickPSHostProcess", + "onCommand:PowerShell.PickRunspace", + "onCommand:PowerShell.SpecifyScriptArgs" + ], + "dependencies": { + "@vscode/extension-telemetry": "^0.9.9", + "semver": "^7.7.2", + "untildify": "^4.0.0", + "uuid": "^9.0.1", + "vscode-languageclient": "^9.0.1", + "vscode-languageserver-protocol": "^3.17.5" + }, + "devDependencies": { + "@vscode/vsce": "^3.6.0", + "esbuild": "^0.25.9" + }, + "optionalDependencies": { + "@eslint/js": "^9.26.0", + "@types/mock-fs": "^4.13.4", + "@types/node": "^22.18.1", + "@types/semver": "^7.7.1", + "@types/sinon": "^17.0.4", + "@types/ungap__structured-clone": "^1.2.0", + "@types/uuid": "^9.0.8", + "@types/vscode": "~1.101.0", + "@ungap/structured-clone": "^1.3.0", + "@vscode/debugprotocol": "^1.68.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.5.2", + "esbuild-register": "^3.6.0", + "eslint": "^9.35.0", + "eslint-config-prettier": "^10.1.8", + "mock-fs": "^5.5.0", + "prettier": "^3.6.2", + "prettier-plugin-organize-imports": "^4.2.0", + "sinon": "^19.0.5", + "typescript": "^5.9.2", + "typescript-eslint": "^8.43.0" + }, + "extensionDependencies": [ + "vscode.powershell" + ], + "main": "./dist/extension.js", + "scripts": { + "compile": "esbuild ./src/extension.ts --outdir=dist --sourcemap --bundle --external:vscode --platform=node", + "watch": "npm run compile -- --watch", + "lint": "eslint src test --ext .ts", + "format": "prettier --check '**/*.{ts,json,yml,mjs,code-workspace}'", + "package": "vsce package --out out/ --no-gitHubIssueLinking --follow-symlinks", + "publish": "vsce publish", + "pretest": "npm run compile", + "test": "vscode-test" + }, + "prettier": { + "endOfLine": "auto", + "plugins": [ + "prettier-plugin-organize-imports" + ] + }, + "contributes": { + "breakpoints": [ + { + "language": "powershell" + } + ], + "viewsContainers": { + "activitybar": [ + { + "id": "PowerShell", + "title": "PowerShell", + "icon": "$(terminal-powershell)" + } + ] + }, + "views": { + "PowerShell": [ + { + "id": "PowerShellCommands", + "name": "Command Explorer", + "when": "config.powershell.sideBar.CommandExplorerVisibility" + } + ] + }, + "keybindings": [ + { + "command": "PowerShell.ShowHelp", + "key": "ctrl+f1", + "when": "editorTextFocus && editorLangId == 'powershell'" + }, + { + "command": "PowerShell.ExpandAlias", + "key": "shift+alt+e", + "when": "editorTextFocus && editorLangId == 'powershell'" + }, + { + "command": "PowerShell.ShowAdditionalCommands", + "key": "shift+alt+s", + "when": "editorTextFocus && editorLangId == 'powershell'" + }, + { + "command": "PowerShell.RunSelection", + "key": "f8", + "when": "editorTextFocus && editorLangId == 'powershell'" + }, + { + "command": "editor.action.insertSnippet", + "when": "editorTextFocus && editorLangId == 'powershell'", + "mac": "cmd+alt+j", + "win": "ctrl+alt+j", + "linux": "ctrl+alt+j" + } + ], + "commands": [ + { + "command": "PowerShell.ExpandAlias", + "title": "Expand Alias", + "category": "PowerShell" + }, + { + "command": "PowerShell.EnableISEMode", + "title": "Enable ISE Mode", + "category": "PowerShell" + }, + { + "command": "PowerShell.DisableISEMode", + "title": "Disable ISE Mode (restore to defaults)", + "category": "PowerShell" + }, + { + "command": "PowerShell.ToggleISEMode", + "title": "Toggle ISE Mode", + "category": "PowerShell" + }, + { + "command": "PowerShell.RefreshCommandsExplorer", + "title": "Refresh Command Explorer", + "category": "PowerShell", + "icon": "$(sync)" + }, + { + "command": "PowerShell.InsertCommand", + "title": "Insert Command", + "category": "PowerShell", + "icon": "$(pencil)" + }, + { + "command": "PowerShell.ShowHelp", + "title": "Get Help for Command", + "category": "PowerShell", + "icon": "$(question)" + }, + { + "command": "PowerShell.Debug.Start", + "title": "Run", + "category": "PowerShell", + "icon": "$(run)" + }, + { + "command": "PowerShell.RunSelection", + "title": "Run Selection", + "category": "PowerShell", + "icon": "$(debug-line-by-line)" + }, + { + "command": "PowerShell.RestartSession", + "title": "Restart Session", + "category": "PowerShell" + }, + { + "command": "PowerShell.ShowLogs", + "title": "Show PowerShell Extension Logs", + "category": "PowerShell" + }, + { + "command": "PowerShell.OpenLogFolder", + "title": "Open PowerShell Extension Logs Folder", + "category": "PowerShell" + }, + { + "command": "PowerShell.GenerateBugReport", + "title": "Upload Bug Report to GitHub", + "category": "PowerShell" + }, + { + "command": "PowerShell.OpenInISE", + "title": "Open Current File in PowerShell ISE", + "category": "PowerShell" + }, + { + "command": "PowerShell.PowerShellFindModule", + "title": "Find/Install PowerShell Modules from the Gallery", + "category": "PowerShell", + "deprecationMessage": "This feature is no longer available, we're sorry!" + }, + { + "command": "PowerShell.ShowAdditionalCommands", + "title": "Show Additional Commands from PowerShell Modules", + "category": "PowerShell" + }, + { + "command": "PowerShell.ShowSessionMenu", + "title": "Show Session Menu", + "category": "PowerShell" + }, + { + "command": "PowerShell.ShowSessionConsole", + "title": "Show Extension Terminal", + "category": "PowerShell" + }, + { + "command": "PowerShell.RunPesterTestsFromFile", + "title": "Run Pester tests", + "category": "PowerShell" + }, + { + "command": "PowerShell.DebugPesterTestsFromFile", + "title": "Debug Pester tests", + "category": "PowerShell" + }, + { + "command": "PowerShell.OpenExamplesFolder", + "title": "Open Examples Folder", + "category": "PowerShell" + }, + { + "command": "PowerShell.InvokeRegisteredEditorCommand", + "title": "Invoke Registered Editor Command", + "category": "PowerShell" + }, + { + "command": "PowerShell.ClosePanel", + "title": "Close panel", + "category": "PowerShell" + }, + { + "command": "PowerShell.PositionPanelLeft", + "title": "Move panel left", + "category": "PowerShell", + "icon": "$(layout-sidebar-left)" + }, + { + "command": "PowerShell.PositionPanelBottom", + "title": "Move panel to bottom", + "category": "PowerShell", + "icon": "$(layout-panel-right)" + }, + { + "title": "[PowerShell Debug Input Task] Wait for and return PSES startup PID", + "command": "PowerShell.WaitForPsesActivationAndReturnProcessId", + "enablement": "false" + }, + { + "title": "[PowerShell Debug Input Task] Get the VS Code Session ID for writing the PID file", + "command": "GetVsCodeSessionId", + "enablement": "false" + } + ], + "menus": { + "commandPalette": [ + { + "command": "PowerShell.InsertCommand", + "when": "false" + }, + { + "command": "PowerShell.RefreshCommandsExplorer", + "when": "config.powershell.sideBar.CommandExplorerVisibility" + }, + { + "command": "PowerShell.InvokeRegisteredEditorCommand", + "when": "false" + } + ], + "explorer/context": [ + { + "command": "PowerShell.RunPesterTestsFromFile", + "when": "resourceFilename =~ /\\.tests\\.ps1$/i" + }, + { + "command": "PowerShell.DebugPesterTestsFromFile", + "when": "resourceFilename =~ /\\.tests\\.ps1$/i" + } + ], + "editor/context": [ + { + "when": "editorLangId == powershell", + "command": "PowerShell.RunSelection", + "group": "2_powershell" + }, + { + "when": "editorLangId == powershell", + "command": "PowerShell.ShowHelp", + "group": "2_powershell" + } + ], + "editor/title": [ + { + "when": "editorLangId == powershell && config.powershell.buttons.showPanelMovementButtons", + "command": "PowerShell.PositionPanelBottom", + "group": "navigation@97" + }, + { + "when": "editorLangId == powershell && config.powershell.buttons.showPanelMovementButtons", + "command": "PowerShell.PositionPanelLeft", + "group": "navigation@98" + }, + { + "when": "editorLangId == powershell && config.powershell.buttons.showRunButtons", + "command": "PowerShell.Debug.Start", + "group": "navigation@100" + }, + { + "when": "editorLangId == powershell && config.powershell.buttons.showRunButtons", + "command": "PowerShell.RunSelection", + "group": "navigation@101" + } + ], + "editor/title/context": [ + { + "when": "resourceFilename =~ /\\.tests\\.ps1$/i", + "command": "PowerShell.RunPesterTestsFromFile" + }, + { + "when": "resourceFilename =~ /\\.tests\\.ps1$/i", + "command": "PowerShell.DebugPesterTestsFromFile" + } + ], + "view/title": [ + { + "command": "PowerShell.RefreshCommandsExplorer", + "when": "view == PowerShellCommands", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "PowerShell.ShowHelp", + "when": "view == PowerShellCommands", + "group": "inline@1" + }, + { + "command": "PowerShell.InsertCommand", + "when": "view == PowerShellCommands", + "group": "inline@2" + } + ] + }, + "problemMatchers": [ + { + "name": "pester", + "owner": "powershell", + "fileLocation": [ + "absolute" + ], + "severity": "error", + "pattern": [ + { + "regexp": "^\\s*(?:\\[-\\]\\s+)(.*?)(?:\\s+\\d+\\.?\\d*\\s*m?s)(?:\\s+\\(\\d+\\.?\\d*m?s\\|\\d+\\.?\\d*m?s\\))?\\s*$", + "message": 1 + }, + { + "regexp": "^\\s+[Aa]t\\s+([^,]+,)?(.+?):(\\s+line\\s+)?(\\d+)(\\s+char:\\d+)?$", + "file": 2, + "line": 4 + } + ] + } + ], + "snippets": [ + { + "language": "powershell", + "path": "./snippets/PowerShell.json" + } + ], + "debuggers": [ + { + "type": "PowerShell", + "label": "PowerShell", + "variables": { + "PickPSHostProcess": "PowerShell.PickPSHostProcess", + "PickRunspace": "PowerShell.PickRunspace", + "SpecifyScriptArgs": "PowerShell.SpecifyScriptArgs" + }, + "languages": [ + "powershell" + ], + "configurationSnippets": [ + { + "label": "PowerShell: Launch Current File", + "description": "Launch and debug the file in the currently active editor window", + "body": { + "name": "PowerShell Launch Current File", + "type": "PowerShell", + "request": "launch", + "script": "^\"\\${file}\"", + "cwd": "^\"\\${cwd}\"" + } + }, + { + "label": "PowerShell: Launch Script", + "description": "Launch and debug the specified file or command", + "body": { + "name": "PowerShell Launch Script", + "type": "PowerShell", + "request": "launch", + "script": "^\"Enter path or command to execute, for example, \\${workspaceFolder}/src/foo.ps1 or Invoke-Pester\"", + "cwd": "^\"\\${cwd}\"" + } + }, + { + "label": "PowerShell: Interactive Session", + "description": "Debug commands executed from the Extension Terminal", + "body": { + "name": "PowerShell Interactive Session", + "type": "PowerShell", + "request": "launch", + "cwd": "^\"\\${cwd}\"" + } + }, + { + "label": "PowerShell: Attach to PowerShell Host Process", + "description": "Attach the debugger to a running PowerShell Host Process", + "body": { + "name": "PowerShell Attach to Host Process", + "type": "PowerShell", + "request": "attach" + } + }, + { + "label": "PowerShell: Run Pester Tests", + "description": "Debug Pester Tests detected in your current directory (runs Invoke-Pester)", + "body": { + "name": "PowerShell Run Pester Tests", + "type": "PowerShell", + "request": "launch", + "script": "Invoke-Pester", + "createTemporaryIntegratedConsole": true, + "attachDotnetDebugger": true + } + }, + { + "label": "PowerShell: Interactive Session (Module)", + "description": "Debug commands executed from the PowerShell Extension Terminal after auto-loading your module", + "body": { + "name": "PowerShell: Module Interactive Session", + "type": "PowerShell", + "request": "launch", + "script": "Enter command to import your binary module, for example: \"Import-Module -Force ${workspaceFolder}/path/to/module.psd1|dll\"" + } + }, + { + "label": "PowerShell: Interactive Session (Binary Module)", + "description": "Debug a .NET binary or hybrid module loaded into a PowerShell session. Breakpoints you set in your .NET (C#/F#/VB/etc.) code will be hit upon command execution. You may want to add a compile or watch action as a pre-launch task to this configuration.", + "body": { + "name": "PowerShell: Binary Module Interactive", + "type": "PowerShell", + "request": "launch", + "script": "Enter command to import your binary module, for example: \"Import-Module -Force ${workspaceFolder}/path/to/module.psd1|dll\"", + "createTemporaryIntegratedConsole": true, + "attachDotnetDebugger": true + } + }, + { + "label": "PowerShell: Run Pester Tests (Binary Module)", + "description": "Debug a .NET binary or hybrid module by running Pester tests. Breakpoints you set in your .NET (C#/F#/VB/etc.) code will be hit upon command execution. You may want to add a compile or watch action as a pre-launch task to this configuration.", + "body": { + "name": "PowerShell: Binary Module Pester Tests", + "type": "PowerShell", + "request": "launch", + "script": "Invoke-Pester", + "createTemporaryIntegratedConsole": true, + "attachDotnetDebugger": true + } + }, + { + "label": "PowerShell: Windows PowerShell", + "description": "(Windows Only) Launch a temporary Windows PowerShell console for debugging. This is useful for debugging legacy scripts that require Windows PowerShell.", + "body": { + "name": "PowerShell: Windows PowerShell", + "type": "PowerShell", + "request": "launch", + "sessionName": "Windows PowerShell (x64)" + } + } + ], + "configurationAttributes": { + "launch": { + "properties": { + "script": { + "type": "string", + "description": "Optional: Absolute path to the PowerShell script to launch under the debugger." + }, + "args": { + "type": "array", + "description": "Command line arguments to pass to the PowerShell script. Specify \"${command:SpecifyScriptArgs}\" if you want to be prompted for the args.", + "items": { + "type": "string" + }, + "default": [] + }, + "cwd": { + "type": "string", + "description": "Absolute path to the working directory. Default is the current workspace folder.", + "default": "${workspaceFolder}" + }, + "createTemporaryIntegratedConsole": { + "type": "boolean", + "description": "Determines whether a temporary PowerShell Extension Terminal is created for each debugging session, useful for debugging PowerShell classes and binary modules. Overrides the user setting 'powershell.debugging.createTemporaryIntegratedConsole'.", + "default": false + }, + "sessionName": { + "type": [ + "string", + "null" + ], + "description": "If specified, uses the PowerShell session name to launch the debug configuration. Will always launch in a temporary console if specified.", + "default": null + }, + "attachDotnetDebugger": { + "type": "boolean", + "description": "If specified, a C# debug session will be started and attached to the new temporary extension terminal. This does nothing unless 'powershell.debugging.createTemporaryIntegratedConsole' is also specified.", + "default": false + }, + "dotnetDebuggerConfigName": { + "type": "string", + "description": "If you would like to use a custom coreclr attach debug launch configuration for the debug session, specify the name here. Otherwise a default basic config will be used. The config must be a coreclr attach config. Launch configs are not supported.", + "default": false + }, + "temporaryConsoleWindowActionOnDebugEnd": { + "type": "string", + "description": "Determines whether the temporary PowerShell Extension Terminal is closed when the debugging session ends.", + "default": "keep", + "enum": [ + "close", + "hide", + "keep" + ], + "enumDescriptions": [ + "Closes the temporary PowerShell Extension Terminal when the debugging session ends.", + "Hides the temporary PowerShell Extension Terminal when the debugging session ends and restores the previous window before the debug session had started. This does nothing if the previous window was closed during the debug session.", + "Keeps the temporary PowerShell Extension Terminal open after the debugging session ends." + ] + }, + "pathMappings": { + "type": "array", + "description": "Optional: An array of path mappings to use when debugging a remote PowerShell host process. Each mapping is an object with 'localRoot' and 'remoteRoot' properties. This is only used if the current integrated terminal is connected to a remote PowerShell runspace.", + "items": { + "type": "object", + "properties": { + "localRoot": { + "type": "string", + "description": "The local root to map." + }, + "remoteRoot": { + "type": "string", + "description": "The remote root to map." + } + }, + "required": [ + "localRoot", + "remoteRoot" + ] + }, + "default": [] + } + } + }, + "attach": { + "properties": { + "computerName": { + "type": "string", + "description": "Optional: The computer name to which a remote session will be established.", + "default": null + }, + "processId": { + "type": "number", + "description": "Optional: The ID of the PowerShell host process that should be attached. Will prompt if unspecified.", + "default": null + }, + "runspaceId": { + "type": "number", + "description": "Optional: The ID of the runspace to debug in the attached process. Will prompt if unspecified.", + "default": null + }, + "runspaceName": { + "type": "string", + "description": "Optional: The name of the runspace to debug in the attached process.", + "default": null + }, + "customPipeName": { + "type": "string", + "description": "The custom pipe name of the PowerShell host process to attach to.", + "default": null + }, + "createTemporaryIntegratedConsole": { + "type": "boolean", + "description": "Determines whether a temporary PowerShell Extension Terminal is created for each debugging session, useful for debugging PowerShell classes and binary modules. Overrides the user setting 'powershell.debugging.createTemporaryIntegratedConsole'.", + "default": false + }, + "temporaryConsoleWindowActionOnDebugEnd": { + "type": "string", + "description": "Determines whether the temporary PowerShell Extension Terminal is closed when the debugging session ends.", + "default": "keep", + "enum": [ + "close", + "hide", + "keep" + ], + "enumDescriptions": [ + "Closes the temporary PowerShell Extension Terminal when the debugging session ends.", + "Hides the temporary PowerShell Extension Terminal when the debugging session ends and restores the previous window before the debug session had started. This does nothing if the previous window was closed during the debug session.", + "Keeps the temporary PowerShell Extension Terminal open after the debugging session ends." + ] + }, + "pathMappings": { + "type": "array", + "description": "Optional: An array of path mappings to use when debugging a remote PowerShell host process. Each mapping is an object with 'localRoot' and 'remoteRoot' properties.", + "items": { + "type": "object", + "properties": { + "localRoot": { + "type": "string", + "description": "The local root to map." + }, + "remoteRoot": { + "type": "string", + "description": "The remote root to map." + } + }, + "required": [ + "localRoot", + "remoteRoot" + ] + }, + "default": [] + } + } + } + }, + "initialConfigurations": [] + } + ], + "configuration": [ + { + "title": "Interface", + "properties": { + "powershell.buttons.showRunButtons": { + "type": "boolean", + "default": true, + "markdownDescription": "Show the `Run` and `Run Selection` buttons in the editor's title bar." + }, + "powershell.buttons.showPanelMovementButtons": { + "type": "boolean", + "default": false, + "markdownDescription": "Show buttons in the editor's title bar for moving the terminals pane (with the PowerShell Extension Terminal) around." + }, + "powershell.enableReferencesCodeLens": { + "type": "boolean", + "default": true, + "markdownDescription": "Specifies if Code Lenses are displayed above function definitions, used to show the number of times the function is referenced in the workspace and navigate to those references. Large workspaces may want to disable this setting if performance is compromised. See also `#powershell.analyzeOpenDocumentsOnly#`." + }, + "powershell.codeFolding.enable": { + "type": "boolean", + "default": true, + "markdownDescription": "Enables syntax based code folding. When disabled, the default indentation based code folding is used." + }, + "powershell.codeFolding.showLastLine": { + "type": "boolean", + "default": true, + "markdownDescription": "Shows the last line of a folded section similar to the default VS Code folding style. When disabled, the entire folded region is hidden." + }, + "powershell.helpCompletion": { + "type": "string", + "default": "BlockComment", + "enum": [ + "Disabled", + "BlockComment", + "LineComment" + ], + "markdownEnumDescriptions": [ + "Disables the feature.", + "Inserts a block style help comment, for example:\n\n`<#`\n\n`.`\n\n``\n\n`#>`", + "Inserts a line style help comment, for example:\n\n`# .`\n\n`# `" + ], + "markdownDescription": "Specifies the [comment based help](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help) completion style triggered by typing ` ##`." + }, + "powershell.sideBar.CommandExplorerVisibility": { + "type": "boolean", + "default": false, + "markdownDescription": "Specifies the visibility of the Command Explorer in the side bar." + }, + "powershell.sideBar.CommandExplorerExcludeFilter": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "markdownDescription": "Specifies an array of modules to exclude from Command Explorer listing." + }, + "powershell.promptToUpdatePowerShell": { + "type": "boolean", + "default": true, + "markdownDescription": "Specifies whether you may be prompted to update your version of PowerShell." + }, + "powershell.promptToUpdatePackageManagement": { + "type": "boolean", + "default": false, + "markdownDescription": "**Deprecated:** Specifies whether you should be prompted to update your version of `PackageManagement` if it's under 1.4.6.", + "markdownDeprecationMessage": "**Deprecated:** This prompt has been removed as it's no longer strictly necessary to upgrade the `PackageManagement` module." + }, + "powershell.suppressAdditionalExeNotFoundWarning": { + "type": "boolean", + "default": false, + "markdownDescription": "Suppresses the warning message when any of `#powershell.powerShellAdditionalExePaths#` is not found." + } + } + }, + { + "title": "Formatting", + "properties": { + "powershell.codeFormatting.preset": { + "type": "string", + "default": "Custom", + "enum": [ + "Custom", + "Allman", + "OTBS", + "Stroustrup" + ], + "markdownEnumDescriptions": [ + "The three brace settings are respected as-is.", + "Sets `#powershell.codeFormatting.openBraceOnSameLine#` to `false`, `#powershell.codeFormatting.newLineAfterOpenBrace#` to `true`, and `#powershell.codeFormatting.newLineAfterCloseBrace#` to `true`.", + "Sets `#powershell.codeFormatting.openBraceOnSameLine#` to `true`, `#powershell.codeFormatting.newLineAfterOpenBrace#` to `true`, and `#powershell.codeFormatting.newLineAfterCloseBrace#` to `false`.", + "Sets `#powershell.codeFormatting.openBraceOnSameLine#` to `true`, `#powershell.codeFormatting.newLineAfterOpenBrace#` to `true`, and `#powershell.codeFormatting.newLineAfterCloseBrace#` to `true`." + ], + "markdownDescription": "Sets the code formatting options to follow the given indent style in a way that is compatible with PowerShell syntax. Any setting other than `Custom` will configure (and override) the settings:\n\n* `#powershell.codeFormatting.openBraceOnSameLine#`\n\n* `#powershell.codeFormatting.newLineAfterOpenBrace#`\n\n* `#powershell.codeFormatting.newLineAfterCloseBrace#`\n\nFor more information about the brace styles, please see [PoshCode's discussion](https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81)." + }, + "powershell.codeFormatting.autoCorrectAliases": { + "type": "boolean", + "default": false, + "markdownDescription": "Replaces aliases with their aliased name." + }, + "powershell.codeFormatting.avoidSemicolonsAsLineTerminators": { + "type": "boolean", + "default": false, + "markdownDescription": "Removes redundant semicolon(s) at the end of a line where a line terminator is sufficient." + }, + "powershell.codeFormatting.openBraceOnSameLine": { + "type": "boolean", + "default": true, + "markdownDescription": "Places open brace on the same line as its associated statement." + }, + "powershell.codeFormatting.newLineAfterOpenBrace": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a newline (line break) after an open brace." + }, + "powershell.codeFormatting.newLineAfterCloseBrace": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a newline (line break) after a closing brace." + }, + "powershell.codeFormatting.pipelineIndentationStyle": { + "type": "string", + "default": "NoIndentation", + "enum": [ + "IncreaseIndentationForFirstPipeline", + "IncreaseIndentationAfterEveryPipeline", + "NoIndentation", + "None" + ], + "markdownEnumDescriptions": [ + "Indent once after the first pipeline and keep this indentation.", + "Indent more after the first pipeline and keep this indentation.", + "Do not increase indentation.", + "Do not change any existing pipeline indentation (disables feature)." + ], + "markdownDescription": "Whether to increase indentation after a pipeline for multi-line statements. See [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer/blob/a94d9f5666bba9f569cdf9c1bc99556934f2b8f4/docs/Rules/UseConsistentIndentation.md#pipelineindentation-string-default-value-is-increaseindentationforfirstpipeline) for examples. It is suggested to use `IncreaseIndentationForFirstPipeline` instead of the default `NoIndentation`. **This default may change in the future,** please see the [Request For Comment](https://github.com/PowerShell/vscode-powershell/issues/4296)." + }, + "powershell.codeFormatting.whitespaceBeforeOpenBrace": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a space between a keyword and its associated script-block expression." + }, + "powershell.codeFormatting.whitespaceBeforeOpenParen": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a space between a keyword (`if`, `elseif`, `while`, `switch`, etc.) and its associated conditional expression." + }, + "powershell.codeFormatting.whitespaceAroundOperator": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds spaces before and after an operator (`=`, `+`, `-`, etc.)." + }, + "powershell.codeFormatting.whitespaceAfterSeparator": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a space after a separator (`,` and `;`)." + }, + "powershell.codeFormatting.whitespaceInsideBrace": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a space after an opening brace (`{`) and before a closing brace (`}`)." + }, + "powershell.codeFormatting.whitespaceBetweenParameters": { + "type": "boolean", + "default": false, + "markdownDescription": "Removes redundant whitespace between parameters." + }, + "powershell.codeFormatting.whitespaceAroundPipe": { + "type": "boolean", + "default": true, + "markdownDescription": "**Deprecated:** Please use the `#powershell.codeFormatting.addWhitespaceAroundPipe#` setting instead. If you've used this setting before, we have moved it for you automatically.", + "markdownDeprecationMessage": "**Deprecated:** Please use the `#powershell.codeFormatting.addWhitespaceAroundPipe#` setting instead. If you've used this setting before, we have moved it for you automatically." + }, + "powershell.codeFormatting.addWhitespaceAroundPipe": { + "type": "boolean", + "default": true, + "markdownDescription": "Adds a space before and after the pipeline operator (`|`) if it is missing." + }, + "powershell.codeFormatting.trimWhitespaceAroundPipe": { + "type": "boolean", + "default": false, + "markdownDescription": "Trims extraneous whitespace (more than one character) before and after the pipeline operator (`|`)." + }, + "powershell.codeFormatting.ignoreOneLineBlock": { + "type": "boolean", + "default": true, + "markdownDescription": "Does not reformat one-line code blocks, such as: `if (...) {...} else {...}`." + }, + "powershell.codeFormatting.alignPropertyValuePairs": { + "type": "boolean", + "default": true, + "markdownDescription": "Align assignment statements in a hashtable or a DSC Configuration." + }, + "powershell.codeFormatting.useConstantStrings": { + "type": "boolean", + "default": false, + "markdownDescription": "Use single quotes if a string is not interpolated and its value does not contain a single quote." + }, + "powershell.codeFormatting.useCorrectCasing": { + "type": "boolean", + "default": false, + "markdownDescription": "Use correct casing for cmdlets." + } + } + }, + { + "title": "Editor Services", + "properties": { + "powershell.powerShellDefaultVersion": { + "type": "string", + "default": "", + "markdownDescription": "Specifies the default PowerShell version started by the extension. The name must match what is displayed in the [Session Menu command](command:PowerShell.ShowSessionMenu), for example, `Windows PowerShell (x86)`. You can specify additional PowerShell executables with the `#powershell.powerShellAdditionalExePaths#` setting." + }, + "powershell.enableProfileLoading": { + "type": "boolean", + "default": true, + "markdownDescription": "Specifies whether the extension loads [PowerShell profiles](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles). Note that the extension's \"Current Host\" profile is `Microsoft.VSCode_profile.ps1`, which will be loaded instead of the default \"Current Host\" profile of `Microsoft.PowerShell_profile.ps1`. Use the \"All Hosts\" profile `profile.ps1` for common configuration." + }, + "powershell.startAutomatically": { + "type": "boolean", + "default": true, + "markdownDescription": "Starts the PowerShell extension automatically when a PowerShell file is opened. If `false`, to start the extension use the [Restart Session command](command:PowerShell.RestartSession). **IntelliSense, code navigation, the Extension Terminal, code formatting, and other features are not enabled until the extension starts.**" + }, + "powershell.scriptAnalysis.enable": { + "type": "boolean", + "default": true, + "markdownDescription": "Enables real-time script analysis using [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) that populates the [Problems view](command:workbench.panel.markers.view.focus)." + }, + "powershell.scriptAnalysis.settingsPath": { + "type": "string", + "default": "PSScriptAnalyzerSettings.psd1", + "markdownDescription": "Specifies the path to a [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) settings file. **This setting may not work as expected currently!**" + }, + "powershell.analyzeOpenDocumentsOnly": { + "type": "boolean", + "default": false, + "markdownDescription": "Specifies to search for references only within open documents instead of all workspace files. An alternative to `#powershell.enableReferencesCodeLens#` that allows large workspaces to support some references without the performance impact." + }, + "powershell.debugging.createTemporaryIntegratedConsole": { + "type": "boolean", + "default": false, + "markdownDescription": "Creates a temporary PowerShell Extension Terminal for each debugging session. This is useful for debugging PowerShell classes and binary modules." + }, + "powershell.debugging.executeMode": { + "type": "string", + "enum": [ + "DotSource", + "Call" + ], + "default": "DotSource", + "markdownEnumDescriptions": [ + "Use the Dot-Source operator `.` to launch the script, for example, `. 'C:\\Data\\MyScript.ps1'`", + "Use the Call operator `&` to launch the script, for example, `& 'C:\\Data\\MyScript.ps1'`" + ], + "markdownDescription": "Sets the operator used to launch scripts." + }, + "powershell.powerShellExePath": { + "type": "string", + "default": "", + "scope": "machine", + "markdownDescription": "**Deprecated:** Specifies the path to the PowerShell executable.", + "markdownDeprecationMessage": "**Deprecated:** Please use the `#powershell.powerShellAdditionalExePaths#` setting instead." + }, + "powershell.powerShellAdditionalExePaths": { + "type": "object", + "default": {}, + "markdownDescription": "Specifies a list of Item / Value pairs where the **Item** is a user-chosen name and the **Value** is an absolute path to a PowerShell executable. The name appears in the [Session Menu Command](command:PowerShell.ShowSessionMenu) and is used to reference this executable in the `#powershell.powerShellDefaultVersion#` setting.", + "additionalProperties": { + "type": "string" + } + }, + "powershell.cwd": { + "type": "string", + "default": "", + "markdownDescription": "A path where the Extension Terminal will be launched. Both the PowerShell process's and the shell's location will be set to this directory. Does not support variables, but does support the use of '~' and paths relative to a single workspace. **For multi-root workspaces, use the name of the folder you wish to have as the cwd.**" + }, + "powershell.startAsLoginShell.osx": { + "type": "boolean", + "default": true, + "markdownDescription": "Starts the PowerShell extension's underlying PowerShell process as a login shell, if applicable." + }, + "powershell.startAsLoginShell.linux": { + "type": "boolean", + "default": false, + "markdownDescription": "Starts the PowerShell extension's underlying PowerShell process as a login shell, if applicable." + }, + "powershell.useX86Host": { + "type": "boolean", + "default": false, + "markdownDescription": "**Deprecated:** Uses the 32-bit language service on 64-bit Windows. This setting has no effect on 32-bit Windows or on the PowerShell extension debugger, which has its own architecture configuration.", + "markdownDeprecationMessage": "**Deprecated:** This setting was removed when the PowerShell installation searcher was added. Please use the `#powershell.powerShellAdditionalExePaths#` setting instead." + } + } + }, + { + "title": "Pester", + "properties": { + "powershell.pester.useLegacyCodeLens": { + "type": "boolean", + "default": true, + "markdownDescription": "Use a CodeLens that is compatible with Pester 4. Disabling this will show `Run Tests` on all `It`, `Describe` and `Context` blocks, and will correctly work only with Pester 5 and newer." + }, + "powershell.pester.codeLens": { + "type": "boolean", + "default": true, + "markdownDescription": "This setting controls the appearance of the `Run Tests` and `Debug Tests` CodeLenses that appears above Pester tests." + }, + "powershell.pester.outputVerbosity": { + "type": "string", + "default": "FromPreference", + "enum": [ + "FromPreference", + "None", + "Minimal", + "Normal", + "Detailed", + "Diagnostic" + ], + "markdownDescription": "Defines the verbosity of output to be used. For Pester 5 and newer the default value `FromPreference` will use the `Output` settings from the `$PesterPreference` defined in the caller's context, and will default to `Normal` if there is none. For Pester 4 the `FromPreference` and `Normal` options map to `All`, and `Minimal` option maps to `Fails`." + }, + "powershell.pester.debugOutputVerbosity": { + "type": "string", + "enum": [ + "None", + "Minimal", + "Normal", + "Detailed", + "Diagnostic" + ], + "default": "Diagnostic", + "markdownDescription": "Defines the verbosity of output to be used when debugging a test or a block. For Pester 5 and newer the default value `Diagnostic` will print additional information about discovery, skipped and filtered tests, mocking and more." + } + } + }, + { + "title": "Terminal", + "properties": { + "powershell.integratedConsole.suppressStartupBanner": { + "type": "boolean", + "default": false, + "markdownDescription": "Do not show the startup banner in the PowerShell Extension Terminal." + }, + "powershell.integratedConsole.showOnStartup": { + "type": "boolean", + "default": true, + "markdownDescription": "Shows the Extension Terminal when the PowerShell extension is initialized. When disabled, the pane is not opened on startup, but the Extension Terminal is still created in order to power the extension's features." + }, + "powershell.integratedConsole.startInBackground": { + "type": "boolean", + "default": false, + "markdownDescription": "Starts the Extension Terminal in the background. **If this is enabled, to access the terminal you must run the [Show Extension Terminal command](command:PowerShell.ShowSessionConsole), and once shown it cannot be put back into the background.** This option completely hides the Extension Terminal from the terminals view. You are probably looking for the `#powershell.integratedConsole.showOnStartup#` option instead." + }, + "powershell.integratedConsole.startLocation": { + "type": "string", + "default": "Panel", + "enum": [ + "Editor", + "Panel" + ], + "markdownEnumDescriptions": [ + "Creates the Extension Terminal in Editor area", + "Creates the Extension Terminal in Panel area" + ], + "markdownDescription": "Sets the startup location for Extension Terminal." + }, + "powershell.integratedConsole.focusConsoleOnExecute": { + "type": "boolean", + "default": true, + "markdownDescription": "Switches focus to the console when a script selection is run or a script file is debugged." + }, + "powershell.integratedConsole.useLegacyReadLine": { + "type": "boolean", + "default": false, + "markdownDescription": "This will disable the use of PSReadLine in the PowerShell Extension Terminal and use a legacy implementation. **This setting is not recommended and likely to be deprecated!**" + }, + "powershell.integratedConsole.forceClearScrollbackBuffer": { + "type": "boolean", + "default": false, + "markdownDescription": "Use the VS Code API to clear the terminal since that's the only reliable way to clear the scrollback buffer. Turn this on if you're used to `Clear-Host` clearing scroll history. **This setting is not recommended and likely to be deprecated!**" + } + } + }, + { + "title": "Developer", + "properties": { + "powershell.developer.editorServicesLogLevel": { + "type": "string", + "default": "Warning", + "enum": [ + "Trace", + "Debug", + "Information", + "Warning", + "Error", + "None" + ], + "markdownEnumDescriptions": [ + "Enables all logging possible, please use this setting when submitting logs for bug reports!", + "Enables more detailed logging of the extension", + "Logs high-level information about what the extension is doing.", + "Only log warnings and errors. This is the default setting", + "Only log errors.", + "Disable all logging possible. No log files will be written!" + ], + "markdownDescription": "Sets the log verbosity for both the extension and its LSP server, PowerShell Editor Services. **Please set to `Trace` when recording logs for a bug report!**" + }, + "powershell.trace.server": { + "type": "string", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "markdownDescription": "Traces the communication between VS Code and the PowerShell Editor Services [LSP Server](https://microsoft.github.io/language-server-protocol/). The output will be logged and also visible in the Output pane, where the verbosity is configurable. **For extension developers and issue troubleshooting only!**" + }, + "powershell.developer.traceDap": { + "type": "boolean", + "default": false, + "markdownDescription": "Traces the DAP communication between VS Code and the PowerShell Editor Services [DAP Server](https://microsoft.github.io/debug-adapter-protocol/). The output will be logged and also visible in the Output pane, where the verbosity is configurable. **For extension developers and issue troubleshooting only!**" + }, + "powershell.developer.editorServicesWaitForDebugger": { + "type": "boolean", + "default": false, + "markdownDescription": "Launches the LSP server with the `/waitForDebugger` flag to force it to wait for a .NET debugger to attach before proceeding, and emit its PID until then. **This setting is only meant for extension developers and requires the extension to be run in development mode!**" + }, + "powershell.developer.setExecutionPolicy": { + "type": "boolean", + "default": true, + "markdownDescription": "On Windows we launch the PowerShell executable with `-ExecutionPolicy Bypass` so that the LSP server (PowerShell Editor Services module) will launch without issue. Some anti-virus programs disallow this command-line argument and this flag can be used to remove it. **Using this setting may require trusting the script manually in order for it to launch!**" + }, + "powershell.developer.bundledModulesPath": { + "type": "string", + "default": "../../PowerShellEditorServices/module", + "markdownDescription": "Specifies an alternative path to the folder containing modules that are bundled with the PowerShell extension, that is: PowerShell Editor Services, PSScriptAnalyzer and PSReadLine. **This setting is only meant for extension developers and requires the extension to be run in development mode!**" + }, + "powershell.developer.featureFlags": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "markdownDescription": "An array of strings that enable experimental features in the PowerShell extension. **No flags are currently available!**" + }, + "powershell.developer.waitForSessionFileTimeoutSeconds": { + "type": "number", + "default": 240, + "markdownDescription": "Specifies how many seconds the extension will wait for the LSP server, PowerShell Editor Services, to connect. The default is four minutes; try increasing this value if your computer is particularly slow (often caused by overactive anti-malware programs)." + }, + "powershell.bugReporting.project": { + "type": "string", + "default": "https://github.com/PowerShell/vscode-powershell", + "markdownDescription": "**Deprecated:** Specifies the URL of the GitHub project in which to generate bug reports.", + "markdownDeprecationMessage": "**Deprecated:** This setting was never meant to be changed!" + } + } + } + ], + "capabilities": { + "untrustedWorkspaces": { + "supported": false + } + }, + "configurationDefaults": { + "[powershell]": { + "debug.saveBeforeStart": "nonUntitledEditorsInActiveGroup", + "editor.semanticHighlighting.enabled": false, + "editor.wordSeparators": "`~!@#$%^&*()=+[{]}\\|;:'\",.<>/?" + } + }, + "themes": [ + { + "label": "PowerShell ISE", + "uiTheme": "vs", + "path": "./themes/theme-psise/theme.json" + } + ], + "walkthroughs": [ + { + "id": "PowerShell", + "title": "Get Started with PowerShell", + "description": "Set up your environment and see what the PowerShell Extension in Visual Studio Code can help you achieve!", + "steps": [ + { + "id": "install-windows", + "title": "Choose a version of PowerShell", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "There are multiple versions of PowerShell that you can use with the extension! Choose the version that best fits your needs here.\nFor the newest version of PowerShell, install PowerShell 7 or run ``iex \"& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI\"``\n[Install PowerShell 7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows)\n⭐️ Latest version ― if you want the latest and greatest capabilities.\n💻 Can be used to manage multiple operating systems.\n👥 [Open source](https://github.com/powershell/powershell) and community-focused!", + "when": "isWindows" + }, + { + "id": "install-mac", + "title": "Install PowerShell", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "💻 PowerShell 7 is cross-platform! See the instructions to [install on macOS](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-macos).\n⭐️ If you already have [Homebrew](https://brew.sh) installed, you can run ``brew install --cask powershell`` to install ``pwsh``.\n👥 PowerShell is [open source](https://github.com/powershell/powershell) and community-focused!", + "when": "isMac" + }, + { + "id": "install-linux", + "title": "Install PowerShell", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "💻 PowerShell 7 is cross-platform!\n⭐️ See the instructions to [install on Linux](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux).\n👥 PowerShell is [open source](https://github.com/powershell/powershell) and community-focused!", + "when": "isLinux" + }, + { + "id": "file", + "title": "Create a PowerShell file", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "[Create](command:toSide:workbench.action.files.newUntitledFile?%7B%22languageId%22%3A%22powershell%22%7D) or [open](command:toSide:workbench.action.files.openFolder) a PowerShell file, make sure to save it as ``.ps1``\n[Create a File](command:toSide:workbench.action.files.newUntitledFile?%7B%22languageId%22%3A%22powershell%22%7D)\n**Tip:** Use keyboard shortcut ``Ctrl+N`` to open a new script file or ``Ctrl+O`` to open a file." + }, + { + "id": "sessions", + "title": "Switch sessions", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "To switch between PowerShell 7 and Windows PowerShell 5.1, use the menu:\n[Open PowerShell Sessions Menu](command:PowerShell.ShowSessionMenu)\nYou can pin the [PowerShell Language Status Icon](https://github.com/PowerShell/vscode-powershell/blob/main/docs/troubleshooting.md#how-do-i-change-the-powershell-version) to the status bar in the bottom right-hand corner to easily switch sessions.", + "completionEvents": [ + "onCommand:PowerShell.ShowSessionConsole" + ] + }, + { + "id": "ise", + "title": "Try ISE mode", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "If you are familiar with the Windows PowerShell ISE and would like to configure your settings to simulate the ISE Experience, try the ISE Mode.\n[Toggle ISE Mode](command:PowerShell.ToggleISEMode)", + "completionEvents": [ + "onCommand:PowerShell.ToggleISEMode" + ] + }, + { + "id": "terminal", + "title": "Open the PowerShell Extension Terminal", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "The PowerShell Extension Terminal will run whenever the extension starts in order to enable the its features.\n[Show Panel](command:PowerShell.ShowSessionConsole)\nIf you don't want the terminal panel to open on startup, you can keep the panel closed by configuring ``powershell.integratedConsole.showOnStartup`` in your settings.\n[Close Panel](command:PowerShell.ClosePanel)\n**Tip:** Use keyboard shortcut ``Ctrl+``` to open and close terminal." + }, + { + "id": "explore", + "title": "Explore more resources", + "media": { + "markdown": "media/walkthrough.md" + }, + "description": "Now you are ready to start using the PowerShell Extension on your own and explore more resources!\n📚 See the PowerShell Extension's [documentation](https://docs.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/using-vscode?view=powershell-7.2)\nℹ️ View Visual Studio Code's [documentation](https://code.visualstudio.com/docs/languages/powershell)\n🔌 Plug into the [PowerShell Community](https://docs.microsoft.com/en-us/powershell/scripting/community/community-support?view=powershell-7.2)\n📄 Take a look at our [Release Notes](https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-73?view=powershell-7.2)" + } + ] + } + ] + }, + "private": true +} diff --git a/pwsh-extension-dev.code-workspace b/pwsh-extension-dev.code-workspace new file mode 100644 index 0000000000..dc4208242f --- /dev/null +++ b/pwsh-extension-dev.code-workspace @@ -0,0 +1,412 @@ +{ + "folders": [ + { + "name": "Client", + "path": ".", + }, + { + "name": "Server", + "path": "../PowerShellEditorServices", + }, + ], + "extensions": { + "recommendations": [ + "davidanson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "ms-dotnettools.csharp", + "ms-vscode.powershell", + "connor4312.esbuild-problem-matchers", + "ms-vscode.extension-test-runner", + ], + }, + "settings": { + "window.title": "PowerShell VS Code Extension Development", + "debug.onTaskErrors": "prompt", + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "modifications", + "editor.formatOnPaste": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + }, + "[typescript][javascript][json][jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSaveMode": "file", + }, + "files.associations": { + "**/snippets/*.json": "jsonc", // Use JSONC instead of JSON because that's how VS Code interprets snippet files, and it enables better source documentation. + }, + // Ignore the Markdown rule: + "markdownlint.config": { + "MD024": false, // no-duplicate-header + }, + "powershell.cwd": "Client", + "powershell.codeFormatting.autoCorrectAliases": true, + "powershell.codeFormatting.avoidSemicolonsAsLineTerminators": true, + "powershell.codeFormatting.newLineAfterCloseBrace": false, + "powershell.codeFormatting.trimWhitespaceAroundPipe": true, + "powershell.codeFormatting.useCorrectCasing": true, + "powershell.codeFormatting.whitespaceBeforeOpenBrace": false, + "powershell.codeFormatting.whitespaceBetweenParameters": true, + "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", + "typescript.tsdk": "Client/node_modules/typescript/lib", // Lock the TypeScript SDK path to the version we use + "typescript.tsserver.experimental.enableProjectDiagnostics": true, + "testExplorer.useNativeTesting": true, + }, + "tasks": { + "version": "2.0.0", + "windows": { + "options": { + "shell": { + "executable": "pwsh.exe", + "args": ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command"], + }, + }, + }, + "linux": { + "options": { + "shell": { + "executable": "pwsh", + "args": ["-NoProfile", "-Command"], + }, + }, + }, + "osx": { + "options": { + "shell": { + "executable": "pwsh", + "args": ["-NoProfile", "-Command"], + }, + }, + }, + "tasks": [ + { + "label": "Build", + "icon": { + "id": "tools", + }, + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Client}", + }, + "command": "Invoke-Build Build", + "problemMatcher": ["$msCompile", "$tsc"], + "group": { + "kind": "build", + "isDefault": true, + }, + }, + { + "label": "Extension: Watch", + "type": "shell", + "isBackground": true, + "options": { + "cwd": "${workspaceFolder:Client}", + }, + "command": "npm run watch", + "problemMatcher": { + "owner": "esbuild-watch", + "pattern": { + "regexp": "^\\[ERROR\\] (.+)\\n\\n\\s+([^:]+):(\\d+):(\\d+):", + "message": 1, + "file": 2, + "line": 3, + "column": 4, + }, + "background": { + "activeOnStart": true, + "beginsPattern": "^\\[watch\\] build started", + "endsPattern": "^\\[watch\\] build finished", + }, + }, + "icon": { + "id": "sync", + "color": "terminal.ansiCyan", + }, + "group": { + "kind": "build", + }, + }, + { + "label": "PSES: BuildIfChanged", + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Server}", + }, + "command": "Invoke-Build BuildIfChanged", + "problemMatcher": "$msCompile", + "icon": { + "id": "tools", + "color": "terminal.ansiCyan", + }, + "group": { + "kind": "build", + }, + }, + { + "label": "PreLaunch", + "dependsOn": ["Extension: Watch", "PSES: BuildIfChanged"], + "dependsOrder": "parallel", + }, + { + "label": "Test Client", + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Client}", + }, + "command": "Invoke-Build Test", + "problemMatcher": ["$msCompile", "$tsc"], + "group": { + "kind": "test", + "isDefault": true, + }, + }, + { + "label": "Test Server", + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Server}", + }, + "problemMatcher": ["$msCompile"], + "command": "Invoke-Build TestPS74", + "group": { + "kind": "test", + "isDefault": true, + }, + }, + { + "label": "Invoke-Build Client", + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Client}", + }, + "command": "Invoke-Build ${input:clientBuildCommand}", + "group": "build", + }, + { + "label": "Invoke-Build Server", + "type": "shell", + "options": { + "cwd": "${workspaceFolder:Server}", + }, + "command": "Invoke-Build ${input:serverBuildCommand}", + "group": "build", + }, + ], + "inputs": [ + { + "type": "pickString", + "id": "clientBuildCommand", + "description": "Which Invoke-Build Client Task?", + "options": ["Restore", "Clean", "Build", "Test", "Package"], + "default": "Clean", + }, + { + "type": "pickString", + "id": "serverBuildCommand", + "description": "Which Invoke-Build Server Task?", + "options": [ + "SetupDotNet", + "BinClean", + "Clean", + "Build", + "Test", + "TestPS74", + "TestE2EPwsh", + "TestPS51", + "TestE2EPowerShell", + ], + "default": "Clean", + }, + ], + }, + "launch": { + "version": "0.2.0", + "compounds": [ + { + "name": "Launch Extension", + "configurations": ["Launch", "PowerShell Editor Services"], + "preLaunchTask": "Build", + "stopAll": true, + "presentation": { + "hidden": false, + "group": "Test", + "order": 1, + }, + }, + { + "name": "Launch Extension - Temp Profile", + "configurations": ["Launch-Temp", "PowerShell Editor Services"], + "preLaunchTask": "PreLaunch", + "stopAll": true, + "presentation": { + "hidden": false, + "group": "Test", + "order": 2, + }, + }, + { + "name": "Launch Extension - Isolated Profile", + "configurations": ["Launch-Isolated", "PowerShell Editor Services"], + "preLaunchTask": "Build", + "stopAll": true, + "presentation": { + "hidden": false, + "group": "Test", + "order": 3, + }, + }, + ], + "configurations": [ + { + "name": "Launch", + "type": "extensionHost", + "request": "launch", + "env": { + "VSCODE_PARENT_SESSION_ID": "${command:GetVsCodeSessionId}", + }, + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder:Client}", + "${workspaceFolder:Client}/examples", + ], + "sourceMaps": true, + // This speeds up source map detection and makes smartStep work correctly + "outFiles": ["${workspaceFolder:Client}/dist/*.js"], + "skipFiles": [ + "/**", + "**/node_modules/**", + "**/.vscode-test/**", + "**/app/out/vs/**", // Skips Extension Host internals + ], + "presentation": { + "hidden": true, + }, + }, + { + "name": "Launch-Temp", + "type": "extensionHost", + "request": "launch", + "env": { + "VSCODE_PARENT_SESSION_ID": "${command:GetVsCodeSessionId}", + }, + "runtimeExecutable": "${execPath}", + "args": [ + // Runs the extension in an empty temp profile that is automatically cleaned up after use + // Undocumented: https://github.com/microsoft/vscode-docs/issues/6220 + "--profile-temp", + "--extensionDevelopmentPath=${workspaceFolder:Client}", + "${workspaceFolder:Client}/examples", + ], + "sourceMaps": true, + // This speeds up source map detection and makes smartStep work correctly + "outFiles": ["${workspaceFolder:Client}/dist/*.js"], + "skipFiles": [ + "/**", + "**/node_modules/**", + "**/.vscode-test/**", + "**/app/out/vs/**", // Skips Extension Host internals + ], + "presentation": { + "hidden": true, + }, + }, + { + "name": "Launch-Isolated", + "type": "extensionHost", + "request": "launch", + "env": { + "VSCODE_PARENT_SESSION_ID": "${command:GetVsCodeSessionId}", + }, + "runtimeExecutable": "${execPath}", + "args": [ + // Runs the extension in an empty temp profile that is automatically cleaned up after use + // Undocumented: https://github.com/microsoft/vscode-docs/issues/6220 + "--profile=pwsh-debug", + "--extensionDevelopmentPath=${workspaceFolder:Client}", + "${workspaceFolder:Client}/examples", + ], + "sourceMaps": true, + // This speeds up source map detection and makes smartStep work correctly + "outFiles": ["${workspaceFolder:Client}/dist/*.js"], + "skipFiles": [ + "/**", + "**/node_modules/**", + "**/.vscode-test/**", + "**/app/out/vs/**", // Skips Extension Host internals + ], + "presentation": { + "hidden": true, + }, + }, + { + // https://code.visualstudio.com/docs/csharp/debugger-settings + "name": "Attach to Editor Services", + "type": "coreclr", + "request": "attach", + "processId": "${command:PowerShell.PickPSHostProcess}", + "justMyCode": true, + "suppressJITOptimizations": true, + "symbolOptions": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false, + "searchNuGetOrgSymbolServer": false, + }, + "presentation": { + "hidden": false, + "group": "Test", + "order": 5, + }, + "logging": { + "moduleLoad": false, + }, + }, + { + // https://code.visualstudio.com/docs/csharp/debugger-settings + "name": "PowerShell Editor Services", + "type": "coreclr", + "request": "attach", + // Waits for the extension terminal to become available and gets the PID, saves having to enter it manually. + "processId": "${command:PowerShell.WaitForPsesActivationAndReturnProcessId}", + "justMyCode": true, + "suppressJITOptimizations": true, + "symbolOptions": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false, + "searchNuGetOrgSymbolServer": false, + }, + "presentation": { + "hidden": true, + }, + "logging": { + "moduleLoad": false, + }, + }, + { + // Runs the extension in an isolated but persistent profile separate from the user settings + // Undocumented: https://github.com/microsoft/vscode-docs/issues/6220 + "name": "Launch Extension - Rename Test Cases", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--profile=debug", + "--extensionDevelopmentPath=${workspaceFolder:Client}", + "${workspaceFolder:Server}/test/PowerShellEditorServices.Test.Shared/Refactoring", + ], + "sourceMaps": true, + // This speeds up source map detection and makes smartStep work correctly + "outFiles": ["${workspaceFolder:Client}/dist/*.js"], + "skipFiles": [ + "/**", + "**/node_modules/**", + "**/.vscode-test/**", // Skips Extension Host internals + ], + "presentation": { + "hidden": true, + }, + }, + ], + }, +} diff --git a/scripts/Install-VSCode.ps1 b/scripts/Install-VSCode.ps1 new file mode 100644 index 0000000000..bac756d5d8 --- /dev/null +++ b/scripts/Install-VSCode.ps1 @@ -0,0 +1,628 @@ +<#PSScriptInfo + +.VERSION 1.4.3 + +.GUID 539e5585-7a02-4dd6-b9a6-5dd288d0a5d0 + +.AUTHOR Microsoft + +.COMPANYNAME Microsoft Corporation + +.COPYRIGHT (c) Microsoft Corporation + +.TAGS install vscode installer + +.LICENSEURI https://github.com/PowerShell/vscode-powershell/blob/main/LICENSE.txt + +.PROJECTURI https://github.com/PowerShell/vscode-powershell/blob/main/scripts/Install-VSCode.ps1 + +.ICONURI + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES + 02/06/2021 - Fix an architecture check issue with non-English localizations. + -- + 01/04/2021 - Fix host for downloading VSCode. + -- + 07/10/2019 - Fix a version check when installing user-builds with Windows Powershell greater than 5. + -- + 30/08/2019 - Added functionality to install the "User Install" variant of Stable Edition. + -- + 07/11/2018 - Added support for PowerShell Core and macOS/Linux platforms. + -- + 15/08/2018 - Added functionality to install the new "User Install" variant of Insiders Edition. + -- + 21/03/2018 - Added functionality to install the VSCode context menus. + Also, VSCode is now always added to the search path. + -- + 20/03/2018 - Fix OS detection to prevent error + -- + 28/12/2017 - Added functionality to support 64-bit versions of VSCode + and support for installation of VSCode Insiders Edition. + -- + Initial release. +#> + +<# +.SYNOPSIS + Installs Visual Studio Code, the PowerShell extension, and optionally + a list of additional extensions. + +.DESCRIPTION + This script can be used to easily install Visual Studio Code and the + PowerShell extension on your machine. You may also specify additional + extensions to be installed using the -AdditionalExtensions parameter. + The -LaunchWhenDone parameter will cause VS Code to be launched as + soon as installation has completed. + + Please contribute improvements to this script on GitHub! + + https://github.com/PowerShell/vscode-powershell/blob/main/scripts/Install-VSCode.ps1 + +.PARAMETER Architecture + A validated string defining the bit version to download. Values can be either 64-bit or 32-bit. + If 64-bit is chosen and the OS Architecture does not match, then the 32-bit build will be + downloaded instead. If parameter is not used, then 64-bit is used as default. + +.PARAMETER BuildEdition + A validated string defining which build edition or "stream" to download: + Stable or Insiders Edition (system install or user profile install). + If the parameter is not used, then stable is downloaded as default. + + +.PARAMETER AdditionalExtensions + An array of strings that are the fully-qualified names of extensions to be + installed in addition to the PowerShell extension. The fully qualified + name is formatted as "." and can be found + next to the extension's name in the details tab that appears when you + click an extension in the Extensions panel in Visual Studio Code. + +.PARAMETER LaunchWhenDone + When present, causes Visual Studio Code to be launched as soon as installation + has finished. + +.PARAMETER EnableContextMenus + When present, causes the installer to configure the Explorer context menus + +.EXAMPLE + Install-VSCode.ps1 -Architecture 32-bit + + Installs Visual Studio Code (32-bit) and the powershell extension. +.EXAMPLE + Install-VSCode.ps1 -LaunchWhenDone + + Installs Visual Studio Code (64-bit) and the PowerShell extension and then launches + the editor after installation completes. + +.EXAMPLE + Install-VSCode.ps1 -AdditionalExtensions 'eamodio.gitlens', 'vscodevim.vim' + + Installs Visual Studio Code (64-bit), the PowerShell extension, and additional + extensions. + +.EXAMPLE + Install-VSCode.ps1 -BuildEdition Insider-User -LaunchWhenDone + + Installs Visual Studio Code Insiders Edition (64-bit) to the user profile and then launches the editor + after installation completes. + +.NOTES + This script is licensed under the MIT License: + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [parameter()] + [ValidateSet('64-bit', '32-bit')] + [string]$Architecture = '64-bit', + + [parameter()] + [ValidateSet('Stable-System', 'Stable-User', 'Insider-System', 'Insider-User')] + [string]$BuildEdition = "Stable-System", + + [Parameter()] + [ValidateNotNull()] + [string[]]$AdditionalExtensions = @(), + + [switch]$LaunchWhenDone, + + [switch]$EnableContextMenus +) + +# Taken from https://code.visualstudio.com/docs/setup/linux#_installation +$script:VSCodeYumRepoEntry = @" +[code] +name=Visual Studio Code +baseurl=https://packages.microsoft.com/yumrepos/vscode +enabled=1 +gpgcheck=1 +gpgkey=https://packages.microsoft.com/keys/microsoft.asc +"@ + +$script:VSCodeZypperRepoEntry = @" +[code] +name=Visual Studio Code +baseurl=https://packages.microsoft.com/yumrepos/vscode +enabled=1 +type=rpm-md +gpgcheck=1 +gpgkey=https://packages.microsoft.com/keys/microsoft.asc +"@ + +function Test-IsOsArchX64 { + if ($PSVersionTable.PSVersion.Major -lt 6) { + return (Get-CimInstance -ClassName Win32_OperatingSystem).OSArchitecture -match '64' + } + + return [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::X64 +} + +function Get-AvailablePackageManager +{ + if (Get-Command 'apt' -ErrorAction SilentlyContinue) { + return 'apt' + } + + if (Get-Command 'dnf' -ErrorAction SilentlyContinue) { + return 'dnf' + } + + if (Get-Command 'yum' -ErrorAction SilentlyContinue) { + return 'yum' + } + + if (Get-Command 'zypper' -ErrorAction SilentlyContinue) { + return 'zypper' + } +} + +function Get-CodePlatformInformation { + param( + [Parameter(Mandatory=$true)] + [ValidateSet('32-bit', '64-bit')] + [string] + $Bitness, + + [Parameter(Mandatory=$true)] + [ValidateSet('Stable-System', 'Stable-User', 'Insider-System', 'Insider-User')] + [string] + $BuildEdition + ) + + if ($IsWindows -or $PSVersionTable.PSVersion.Major -lt 6) { + $os = 'Windows' + } + elseif ($IsLinux) { + $os = 'Linux' + } + elseif ($IsMacOS) { + $os = 'MacOS' + } + else { + throw 'Could not identify operating system' + } + + if ($Bitness -ne '64-bit' -and $os -ne 'Windows') { + throw "Non-64-bit *nix systems are not supported" + } + + if ($BuildEdition.EndsWith('User') -and $os -ne 'Windows') { + throw 'User builds are not available for non-Windows systems' + } + + switch ($BuildEdition) { + 'Stable-System' { + $appName = "Visual Studio Code ($Bitness)" + break + } + + 'Stable-User' { + $appName = "Visual Studio Code ($($Architecture) - User)" + break + } + + 'Insider-System' { + $appName = "Visual Studio Code - Insiders Edition ($Bitness)" + break + } + + 'Insider-User' { + $appName = "Visual Studio Code - Insiders Edition ($($Architecture) - User)" + break + } + } + + switch ($os) { + 'Linux' { + $pacMan = Get-AvailablePackageManager + + switch ($pacMan) { + 'apt' { + $platform = 'linux-deb-x64' + $ext = 'deb' + break + } + + { 'dnf','yum','zypper' -contains $_ } { + $platform = 'linux-rpm-x64' + $ext = 'rpm' + break + } + + default { + $platform = 'linux-x64' + $ext = 'tar.gz' + break + } + } + + if ($BuildEdition.StartsWith('Insider')) { + $exePath = '/usr/bin/code-insiders' + break + } + + $exePath = '/usr/bin/code' + break + } + + 'MacOS' { + $platform = 'darwin' + $ext = 'zip' + + if ($BuildEdition.StartsWith('Insider')) { + $exePath = '/usr/local/bin/code-insiders' + break + } + + $exePath = '/usr/local/bin/code' + break + } + + 'Windows' { + $ext = 'exe' + switch ($Bitness) { + '32-bit' { + $platform = 'win32' + + if (Test-IsOsArchX64) { + $installBase = ${env:ProgramFiles(x86)} + break + } + + $installBase = ${env:ProgramFiles} + break + } + + '64-bit' { + $installBase = ${env:ProgramFiles} + + if (Test-IsOsArchX64) { + $platform = 'win32-x64' + break + } + + Write-Warning '64-bit install requested on 32-bit system. Installing 32-bit VSCode' + $platform = 'win32' + break + } + } + + switch ($BuildEdition) { + 'Stable-System' { + $exePath = "$installBase\Microsoft VS Code\bin\code.cmd" + } + + 'Stable-User' { + $exePath = "${env:LocalAppData}\Programs\Microsoft VS Code\bin\code.cmd" + } + + 'Insider-System' { + $exePath = "$installBase\Microsoft VS Code Insiders\bin\code-insiders.cmd" + } + + 'Insider-User' { + $exePath = "${env:LocalAppData}\Programs\Microsoft VS Code Insiders\bin\code-insiders.cmd" + } + } + } + } + + switch ($BuildEdition) { + 'Stable-System' { + $channel = 'stable' + break + } + + 'Stable-User' { + $channel = 'stable' + $platform += '-user' + break + } + + 'Insider-System' { + $channel = 'insider' + break + } + + 'Insider-User' { + $channel = 'insider' + $platform += '-user' + break + } + } + + $info = @{ + AppName = $appName + ExePath = $exePath + Platform = $platform + Channel = $channel + FileUri = "https://update.code.visualstudio.com/latest/$platform/$channel" + Extension = $ext + } + + if ($pacMan) { + $info['PackageManager'] = $pacMan + } + + return $info +} + +function Save-WithBitsTransfer { + param( + [Parameter(Mandatory=$true)] + [string] + $FileUri, + + [Parameter(Mandatory=$true)] + [string] + $Destination, + + [Parameter(Mandatory=$true)] + [string] + $AppName + ) + + Write-Host "`nDownloading latest $AppName..." -ForegroundColor Yellow + + Remove-Item -Force $Destination -ErrorAction SilentlyContinue + + $bitsDl = Start-BitsTransfer $FileUri -Destination $Destination -Asynchronous + + while (($bitsDL.JobState -eq 'Transferring') -or ($bitsDL.JobState -eq 'Connecting')) { + Write-Progress -Activity "Downloading: $AppName" -Status "$([math]::round($bitsDl.BytesTransferred / 1mb))mb / $([math]::round($bitsDl.BytesTotal / 1mb))mb" -PercentComplete ($($bitsDl.BytesTransferred) / $($bitsDl.BytesTotal) * 100 ) + } + + switch ($bitsDl.JobState) { + + 'Transferred' { + Complete-BitsTransfer -BitsJob $bitsDl + break + } + + 'Error' { + throw 'Error downloading installation media.' + } + } +} + +function Install-VSCodeFromTar { + param( + [Parameter(Mandatory=$true)] + [string] + $TarPath, + + [Parameter()] + [switch] + $Insiders + ) + + $tarDir = Join-Path ([System.IO.Path]::GetTempPath()) 'VSCodeTar' + $destDir = '/opt/VSCode-linux-x64' + + New-Item -ItemType Directory -Force -Path $tarDir + try { + Push-Location $tarDir + tar xf $TarPath + Move-Item -LiteralPath "$tarDir/VSCode-linux-x64" $destDir + } + finally { + Pop-Location + } + + if ($Insiders) { + ln -s "$destDir/code-insiders" /usr/bin/code-insiders + return + } + + ln -s "$destDir/code" /usr/bin/code +} + +# We need to be running as elevated on *nix +if (($IsLinux -or $IsMacOS) -and (id -u) -ne 0) { + throw "Must be running as root to install VSCode.`nInvoke this script with (for example):`n`tsudo pwsh -f Install-VSCode.ps1 -BuildEdition Stable-System" +} + +# User builds can only be installed on Windows systems +if ($BuildEdition.EndsWith('User') -and -not ($IsWindows -or $PSVersionTable.PSVersion.Major -lt 6)) { + throw 'User builds are not available for non-Windows systems' +} + +try { + $prevProgressPreference = $ProgressPreference + $ProgressPreference = 'SilentlyContinue' + + # Get information required for installation + $codePlatformInfo = Get-CodePlatformInformation -Bitness $Architecture -BuildEdition $BuildEdition + + # Download the installer + $tmpdir = [System.IO.Path]::GetTempPath() + + $ext = $codePlatformInfo.Extension + $installerName = "vscode-install.$ext" + + $installerPath = [System.IO.Path]::Combine($tmpdir, $installerName) + + if ($PSVersionTable.PSVersion.Major -le 5) { + Save-WithBitsTransfer -FileUri $codePlatformInfo.FileUri -Destination $installerPath -AppName $codePlatformInfo.AppName + } + # We don't want to use RPM packages -- see the installation step below + elseif ($codePlatformInfo.Extension -ne 'rpm') { + if ($PSCmdlet.ShouldProcess($codePlatformInfo.FileUri, "Invoke-WebRequest -OutFile $installerPath")) { + Invoke-WebRequest -Uri $codePlatformInfo.FileUri -OutFile $installerPath + } + } + + # Install VSCode + switch ($codePlatformInfo.Extension) { + # On Debian-like Linux distros + 'deb' { + if (-not $PSCmdlet.ShouldProcess($installerPath, 'apt install -y')) { + break + } + + # The deb file contains the information to install its own repository, + # so we just need to install it + apt install -y $installerPath + break + } + + # On distros using rpm packages, the RPM package doesn't set up the repo. + # To install VSCode properly in way that the package manager tracks it, + # we have to do things the hard way - install the repo and install the package + 'rpm' { + $pacMan = $codePlatformInfo.PackageManager + if (-not $PSCmdlet.ShouldProcess($installerPath, "$pacMan install -y")) { + break + } + + # Install the VSCode repo with the package manager + rpm --import https://packages.microsoft.com/keys/microsoft.asc + + switch ($pacMan) { + 'zypper' { + $script:VSCodeZypperRepoEntry > /etc/zypp/repos.d/vscode.repo + zypper refresh -y + } + + default { + $script:VSCodeYumRepoEntry > /etc/yum.repos.d/vscode.repo + & $pacMan check-update -y + } + } + + switch ($BuildEdition) { + 'Stable-System' { + & $pacMan install -y code + } + + default { + & $pacMan install -y code-insiders + } + } + break + } + + # On Windows + 'exe' { + $exeArgs = '/verysilent /tasks=addtopath' + if ($EnableContextMenus) { + $exeArgs = '/verysilent /tasks=addcontextmenufiles,addcontextmenufolders,addtopath' + } + + if (-not $PSCmdlet.ShouldProcess("$installerPath $exeArgs", 'Start-Process -Wait')) { + break + } + + Start-Process -Wait $installerPath -ArgumentList $exeArgs + break + } + + # On Mac + 'zip' { + if (-not $PSCmdlet.ShouldProcess($installerPath, "Expand-Archive -DestinationPath $zipDirPath -Force; Move-Item $zipDirPath/*.app /Applications/")) { + break + } + + $zipDirPath = [System.IO.Path]::Combine($tmpdir, 'VSCode') + Expand-Archive -LiteralPath $installerPath -DestinationPath $zipDirPath -Force + Move-Item "$zipDirPath/*.app" '/Applications/' + break + } + + # Remaining Linux distros using tar - more complicated + 'tar.gz' { + if (-not $PSCmdlet.ShouldProcess($installerPath, 'Install-VSCodeFromTar (expand, move to /opt/, symlink)')) { + break + } + + Install-VSCodeFromTar -TarPath $installerPath -Insiders:($BuildEdition -ne 'Stable-System') + break + } + + default { + throw "Unkown package type: $($codePlatformInfo.Extension)" + } + } + + $codeExePath = $codePlatformInfo.ExePath + + # Install any extensions + $extensions = @("ms-vscode.PowerShell") + $AdditionalExtensions + if ($PSCmdlet.ShouldProcess(($extensions -join ','), "$codeExePath --install-extension")) { + if ($IsLinux -or $IsMacOS) { + # On *nix we need to install extensions as the user -- VSCode refuses root + $extsSlashes = $extensions -join '/' + sudo -H -u $env:SUDO_USER pwsh -c "`$exts = '$extsSlashes' -split '/'; foreach (`$e in `$exts) { $codeExePath --install-extension `$e }" + } + else { + foreach ($extension in $extensions) { + Write-Host "`nInstalling extension $extension..." -ForegroundColor Yellow + & $codeExePath --install-extension $extension + } + } + } + + # Launch if requested + if ($LaunchWhenDone) { + $appName = $codePlatformInfo.AppName + + if (-not $PSCmdlet.ShouldProcess($appName, "Launch with $codeExePath")) { + return + } + + Write-Host "`nInstallation complete, starting $appName...`n`n" -ForegroundColor Green + & $codeExePath + return + } + + if ($PSCmdlet.ShouldProcess('Installation complete!', 'Write-Host')) { + Write-Host "`nInstallation complete!`n`n" -ForegroundColor Green + } +} +finally { + $ProgressPreference = $prevProgressPreference +} diff --git a/snippets/PowerShell.json b/snippets/PowerShell.json index 99330ca48b..ffbdb35e84 100644 --- a/snippets/PowerShell.json +++ b/snippets/PowerShell.json @@ -1,598 +1,707 @@ { - "Class": { - "prefix": "class", - "body": [ - "class MyClass {", - "\t# Property: Holds name", - "\t[String] $Name;", - - "", - "\t# Constructor: Creates a new MyClass object, with the specified name", - "\tMyClass([String] $NewName) {", - "\t\t# Set name for MyClass", - "\t\t$this.Name = $NewName;", - "\t}", - "", - - "\t# Method: Method that changes $Name to the default name", - "\t[void] ChangeNameToDefault() {", - "\t\t$this.Name = \"DefaultName\";", - "\t}", - "}" - ], - "description": "Simple example class with a constructor and a method" - }, - "Cmdlet": { - "prefix": "cmdlet", - "body": [ - "<#", - ".Synopsis", - "\tShort description", - ".DESCRIPTION", - "\tLong description", - ".EXAMPLE", - "\tExample of how to use this cmdlet", - ".EXAMPLE", - "\tAnother example of how to use this cmdlet", - "#>", - "function Verb-Noun", - "{", - "\t[CmdletBinding()]", - "\t[Alias()]", - "\t[OutputType([int])]", - "\tParam", - "\t(", - "\t\t# Param1 help description", - "\t\t[Parameter(Mandatory=$true,", - "\t\t\t\t ValueFromPipelineByPropertyName=$true,", - "\t\t\t\t Position=0)]", - "\t\t$Param1,", - "\t\t", - - "\t\t# Param2 help description", - "\t\t[int]", - "\t\t$Param2", - "\t)", - "\t", - - "\tBegin", - "\t{", - "\t}", - "\tProcess", - "\t{", - "\t}", - "\tEnd", - "\t{", - "\t}", - "}" - ], - "description": "ScriptCmdlet with some attributes and inline help fields" - }, - "Complete Cmdlet": { - "prefix": "complete cmdlet", - "body": [ - "<#", - ".Synopsis", - "\tShort description", - ".DESCRIPTION", - "\tLong description", - ".EXAMPLE", - "\tExample of how to use this cmdlet", - ".EXAMPLE", - "\tAnother example of how to use this cmdlet", - ".INPUTS", - "\tInputs to this cmdlet (if any)", - ".OUTPUTS", - "\tOutput from this cmdlet (if any)", - ".NOTES", - "\tGeneral notes", - ".COMPONENT", - "\tThe component this cmdlet belongs to", - ".ROLE", - "\tThe role this cmdlet belongs to", - ".FUNCTIONALITY", - "\tThe functionality that best describes this cmdlet", - "#>", - "function Verb-Noun", - "{", - "\t[CmdletBinding(DefaultParameterSetName='Parameter Set 1',", - "\t\t\t\t SupportsShouldProcess=$true,", - "\t\t\t\t PositionalBinding=$false,", - "\t\t\t\t HelpUri = 'http://www.microsoft.com/',", - "\t\t\t\t ConfirmImpact='Medium')]", - "\t[Alias()]", - "\t[OutputType([String])]", - "\tParam", - "\t(", - "\t\t# Param1 help description", - "\t\t[Parameter(Mandatory=$true,", - "\t\t\t\t ValueFromPipeline=$true,", - "\t\t\t\t ValueFromPipelineByPropertyName=$true,", - "\t\t\t\t ValueFromRemainingArguments=$false, ", - "\t\t\t\t Position=0,", - "\t\t\t\t ParameterSetName='Parameter Set 1')]", - "\t\t[ValidateNotNull()]", - "\t\t[ValidateNotNullOrEmpty()]", - "\t\t[ValidateCount(0,5)]", - "\t\t[ValidateSet(\"sun\", \"moon\", \"earth\")]", - "\t\t[Alias(\"p1\")] ", - "\t\t$Param1,", - "\t\t", - - "\t\t# Param2 help description", - "\t\t[Parameter(ParameterSetName='Parameter Set 1')]", - "\t\t[AllowNull()]", - "\t\t[AllowEmptyCollection()]", - "\t\t[AllowEmptyString()]", - "\t\t[ValidateScript({$true})]", - "\t\t[ValidateRange(0,5)]", - "\t\t[int]", - "\t\t$Param2,", - "\t\t", - - "\t\t# Param3 help description", - "\t\t[Parameter(ParameterSetName='Another Parameter Set')]", - "\t\t[ValidatePattern(\"[a-z]*\")]", - "\t\t[ValidateLength(0,15)]", - "\t\t[String]", - "\t\t$Param3", - "\t)", - "\t", - - "\tBegin", - "\t{", - "\t}", - "\tProcess", - "\t{", - "\t\tif ($pscmdlet.ShouldProcess(\"Target\", \"Operation\"))", - "\t\t{", - "\t\t}", - "\t}", - "\tEnd", - "\t{", - "\t}", - "}" - ], - "description": "ScriptCmdlet with all attributes and inline help fields" - }, - "comment block": { - "prefix": "comment", - "body": [ - "<#", - " #", - " #>" - ], - "description": "Comment block" - }, - "DSC Configuration": { - "prefix": "DSC config", - "body": [ - "configuration Name", - "{", - "\t# One can evaluate expressions to get the node list", - "\t# E.g: $AllNodes.Where(\"Role -eq Web\").NodeName", - "\tnode (\"Node1\",\"Node2\",\"Node3\")", - "\t{", - "\t\t# Call Resource Provider", - "\t\t# E.g: WindowsFeature, File", - "\t\tWindowsFeature FriendlyName", - "\t\t{", - "\t\t\tEnsure = \"Present\"", - "\t\t\tName = \"Feature Name\"", - "\t\t}", - "", - "\t\tFile FriendlyName", - "\t\t{", - "\t\t\tEnsure = \"Present\"", - "\t\t\tSourcePath = $SourcePath", - "\t\t\tDestinationPath = $DestinationPath", - "\t\t\tType = \"Directory\"", - "\t\t\tDependsOn = \"[WindowsFeature]FriendlyName\"", - "\t\t}", - "\t}", - "}" - ], - "description": "DSC Configuration that uses built-in resource providers" - }, - "DSC Resource Provider": { - "prefix": "DSC resource", - "body": [ - "Function Get-TargetResource", - "{", - "\t# TODO: Add parameters here", - "\t# Make sure to use the same parameters for", - "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", - "\tparam(", - "\t)", - "}", - - "Function Set-TargetResource", - "{", - "\t# TODO: Add parameters here", - "\t# Make sure to use the same parameters for", - "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", - "\tparam(", - "\t)", - "}", - - "Function Test-TargetResource", - "{", - "\t# TODO: Add parameters here", - "\t# Make sure to use the same parameters for", - "\t# Get-TargetResource, Set-TargetResource, and Test-TargetResource", - "\tparam(", - "\t)", - "}" - ], - "description": "Simple DSC resource provider with functions" - }, - "DSC Resource with class": { - "prefix": "DSC resource class", - "body": [ - "# Defines the values for the resource's Ensure property.", - "enum Ensure", - "{", - "\t# The resource must be absent.", - "\tAbsent", - "\t# The resource must be present.", - "\tPresent", - "}", - "", - "# [DscResource()] indicates the class is a DSC resource.", - "[DscResource()]", - "class NameOfResource", - "{", - "\t# A DSC resource must define at least one key property.", - "\t[DscProperty(Key)]", - "\t[string]$P1", - - "", - "\t# Mandatory indicates the property is required and DSC will guarantee it is set.", - "\t[DscProperty(Mandatory)]", - "\t[Ensure] $P2", - - "", - "\t# NotConfigurable properties return additional information about the state of the resource.", - "\t# For example, a Get() method might return the date a resource was last modified.", - "\t# NOTE: These properties are only used by the Get() method and cannot be set in configuration.", - "\t[DscProperty(NotConfigurable)]", - "\t[Nullable[datetime]] $P3", - - "", - "\t[DscProperty()]", - "\t[ValidateSet(\"val1\", \"val2\")]", - "\t[string] $P4", - - "", - "\t# Sets the desired state of the resource.", - "\t[void] Set()", - "\t{", - "\t}", - - "", - "\t# Tests if the resource is in the desired state.", - "\t[bool] Test()", - "\t{", - "\t\t return $true", - "\t}", - "\t# Gets the resource's current state.", - "\t[NameOfResource] Get()", - "\t{", - "\t\t# NotConfigurable properties are set in the Get method.", - "\t\t$this.P3 = something", - "\t\t# Return this instance or construct a new instance.", - "\t\treturn $this", - "\t}", - "}" - ], - "description": "DSC Resource using classes" - }, - - "do-until": { - "prefix": "do-until", - "body": [ - "do", - "{", - "\t", - "}", - "until ($x -gt 0)" - ], - "description": "do-until loop" - }, - "do-while": { - "prefix": "do-while", - "body": [ - "do", - "{", - "\t", - "}", - "while ($x -gt 0)" - ], - "description": "do-while loop" - }, - "for": { - "prefix": "for", - "body": [ - "for ($i = 1; $i -lt 99; $i++)", - "{", - "\t", - "}" - ], - "description": "for loop" - }, - "foreach": { - "prefix": "foreach", - "body": [ - "foreach ($item in $collection)", - "{", - "\t", - "}" - ], - "description": "foreach loop" - }, - "function": { - "prefix": "function", - "body": [ - "function MyFunction ($param1, $param2)", - "{", - "\t", - "}" - ], - "description": "Simple function with two parameters" - }, - "if": { - "prefix": "if", - "body": [ - "if ($x -gt $y)", - "{", - "\t", - "}" - ], - "description": "if statement" - }, - "if-else": { - "prefix": "if-else", - "body": [ - "if ($x -gt $y)", - "{", - "\t", - "}", - "else", - "{", - "\t", - "}" - ], - "description": "if-else statement" - }, - "switch": { - "prefix": "switch", - "body": [ - "switch ($x)", - "{", - "\t'value1' {}", - "\t{$_ -in 'A','B','C'} {}", - "\t'value3' {}", - "\tDefault {}", - "}" - ], - "description": "switch statement" - }, - "parameter": { - "prefix": "param", - "body": [ - "Param(", - "\t[Parameter(Mandatory=$true)]", - "\t[string]$RequiredInput1,", - "", - "\t[Parameter(Mandatory=$true)]", - "\t[string]$RequiredInput2", - ")" - ], - "description": "Param declaration with mandatory parameters" - }, - "try-catch-finally": { - "prefix": "try-catch-finally", - "body": [ - "try", - "{", - "\t1/0", - "}", - "catch [DivideByZeroException]", - "{", - "\tWrite-Host \"Divide by zero exception\"", - "}", - "catch [System.Net.WebException],[System.Exception]", - "{", - "\tWrite-Host \"Other exception\"", - "}", - "finally", - "{", - "\tWrite-Host \"cleaning up ...\"", - "}" - ], - "description": "try-catch-finally exception handling" - }, - "try-finally": { - "prefix": "try-finally", - "body": [ - "try", - "{", - "\t", - "}", - "finally", - "{", - "\t", - "}" - ], - "description": "try-finally exception handling" - }, - "while": { - "prefix": "while", - "body": [ - "while ($x -gt 0)", - "{", - "\t", - "}" - ], - "description": "while loop" - }, - "Advanced Workflow": { - "prefix": "advanced workflow", - "body": [ - "workflow Verb-Noun", - "{", - "<#", - ".Synopsis", - "\tShort description", - ".DESCRIPTION", - "\tLong description", - ".EXAMPLE", - "\tExample of how to use this workflow", - ".EXAMPLE", - "\tAnother example of how to use this workflow", - ".INPUTS", - "\tInputs to this workflow (if any)", - ".OUTPUTS", - "\tOutput from this workflow (if any)", - ".NOTES", - "\tGeneral notes", - ".FUNCTIONALITY", - "\tThe functionality that best describes this workflow", - "#>", - "", - "\t[CmdletBinding(DefaultParameterSetName='Parameter Set 1',", - "\t\t\t\t HelpUri = 'http://www.microsoft.com/',", - "\t\t\t\t ConfirmImpact='Medium')]", - "\t[Alias()]", - "\t[OutputType([String])]", - "\tParam", - "\t(", - "\t\t# Param1 help description", - "\t\t[Parameter(Mandatory=$true, ", - "\t\t\t\t Position=0,", - "\t\t\t\t ParameterSetName='Parameter Set 1')]", - "\t\t[ValidateNotNull()]", - "\t\t[Alias(\"p1\")] ", - "\t\t$Param1,", - "", - "\t\t# Param2 help description", - "\t\t[int]", - "\t\t$Param2", - "\t)", - "", - "\t# Saves (persists) the current workflow state and output", - "\t# Checkpoint-Workflow", - - "\t# Suspends the workflow", - "\t# Suspend-Workflow", - "", - "\t# Workflow common parameters are available as variables such as:", - "\t$PSPersist ", - "\t$PSComputerName", - "\t$PSCredential", - "\t$PSUseSsl", - "\t$PSAuthentication", - "", - "\t# Workflow runtime information can be accessed by using the following variables:", - "\t$Input", - "\t$PSSenderInfo", - "\t$PSWorkflowRoot", - "\t$JobCommandName", - "\t$ParentCommandName", - "\t$JobId", - "\t$ParentJobId", - "\t$WorkflowInstanceId", - "\t$JobInstanceId", - "\t$ParentJobInstanceId", - "\t$JobName", - "\t$ParentJobName", - - "\t# Set the progress message ParentActivityId", - "\t$PSParentActivityId", - - "\t# Preference variables that control runtime behavior", - "\t$PSRunInProcessPreference", - "\t$PSPersistPreference", - "}" - ], - "description": "Advanced workflow that access common workflow parameters and other pre-defined variables" - }, - "Workflow": { - "prefix": "workflow", - "body": [ - "<#", - ".Synopsis", - "\tShort description", - ".DESCRIPTION", - "\tLong description", - ".EXAMPLE", - "\tExample of how to use this workflow", - ".EXAMPLE", - "\tAnother example of how to use this workflow", - ".INPUTS", - "\tInputs to this workflow (if any)", - ".OUTPUTS", - "\tOutput from this workflow (if any)", - ".NOTES", - "\tGeneral notes", - ".FUNCTIONALITY", - "\tThe functionality that best describes this workflow", - "#>", - "workflow Verb-Noun", - "{", - "\tParam", - "\t(", - "\t\t# Param1 help description", - "\t\t[string]", - "\t\t$Param1,", - - "\t\t# Param2 help description", - "\t\t[int]", - "\t\t$Param2", - "\t)", - "", - "}" - ], - "description": "Basic workflow" - }, - "Workflow ForEachParallel": { - "prefix": "workflow ForEachParallel", - "body": [ - "foreach -parallel ($item in $collection)", - "{", - "", - "}" - ], - "description": "Runs contents of foreach block in parallel" - }, - "Workflow InlineScript": { - "prefix": "workflow InlineScript", - "body": [ - "inlineScript", - "{", - "", - "} # Optional workflow common parameters such as -PSComputerName and -PSCredentialw" - ], - "description": "Runs isolated blocks of PowerShell script" - }, - "Workflow Parallel": { - "prefix": "workflow parallel", - "body": [ - "parallel", - "{", - "", - "}" - ], - "description": "Runs commands in parallel" - }, - "Workflow Sequence": { - "prefix": "workflow sequence", - "body": [ - "sequence", - "{", - "", - "}" - ], - "description": "Runs commands in sequential order" - } -} \ No newline at end of file + "ArgumentCompleterAttribute": { + "prefix": "argument-completer", + "description": "Allows you to add tab completion values to a specific parameter by writing a script block that generates zero or more CompletionResult objects. More: Get-Help about_Functions_Argument_Completion", + "body": [ + "[ArgumentCompleter({", + "\t[OutputType([System.Management.Automation.CompletionResult])]", + "\tparam(", + "\t\t[string] \\$CommandName,", + "\t\t[string] \\$ParameterName,", + "\t\t[string] \\$WordToComplete,", + "\t\t[System.Management.Automation.Language.CommandAst] \\$CommandAst,", + "\t\t[System.Collections.IDictionary] \\$FakeBoundParameters", + "\t)", + "\t", + "\t\\$CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()", + "\t", + "\t${0:$TM_SELECTED_TEXT}", + "\t", + "\treturn \\$CompletionResults", + "})]" + ] + }, + "Calculated Property": { + "prefix": "calculated-property", + "description": "Typically used with Select-Object or Sort-Object. More: Get-Help about_Calculated_Properties", + "body": [ + "@{Name='${1:PropertyName}';Expression={${2:${TM_SELECTED_TEXT:<# Desired result. You can reference this object via \\$_ and \\$PSItem #>}}}}$0" + ] + }, + "Class": { + "prefix": "class", + "description": "A blueprint used to create instances of objects at run time. More: Get-Help about_Classes", + "body": [ + "class ${1:ClassName} {", + "\t${0:${TM_SELECTED_TEXT:<# Define the class. Try constructors, properties, or methods. #>}}", + "}" + ] + }, + "Class Constructor": { + "prefix": ["ctor-class", "class-constructor"], + "description": "Set default values and validate object logic at the moment of creating the instance of the class. Constructors have the same name as the class. Constructors might have arguments, to initialize the data members of the new object. More: Get-Help about_Classes", + "body": [ + "${1:ClassName}(${2:<#OptionalParameters#>}) {", + "\t${0:${TM_SELECTED_TEXT:<# Initialize the class. Use \\$this to reference the properties of the instance you are creating #>}}", + "}" + ] + }, + "Class Method": { + "prefix": "class-method", + "description": "Defines the actions that a class can perform. Methods may take parameters that provide input data. Methods can return output. Data returned by a method can be any defined data type. More: Get-Help about_Classes", + "body": [ + "[${1:void}] ${2:MethodName}($${3:OptionalParameters}) {", + "\t${0:${TM_SELECTED_TEXT:<# Action to perform. You can use $$this to reference the current instance of this class #>}}", + "}" + ] + }, + "Class Property": { + "prefix": "class-property", + "description": "Properties are variables declared at class scope. A property may be of any built-in type or an instance of another class. Classes have no restriction in the number of properties they have. More: Get-Help about_Classes", + "body": ["[${1:propertyType}] $${0:PropertyName}"] + }, + "Comment Block": { + "prefix": ["block-comment"], + "description": "A multi-line comment.", + "body": [ + "$BLOCK_COMMENT_START", + " # ${0:{$TM_SELECTED_TEXT:Enter a comment or description}}", + "$BLOCK_COMMENT_END" + ] + }, + "do-until": { + "prefix": "do-until", + "description": "Runs a statement list repeatedly until a condition is met More: Get-Help about_Do", + "body": [ + "do {", + "\t${0:$TM_SELECTED_TEXT}", + "} until (", + "\t${1:<# Condition that stops the loop if it returns true #>}", + ")" + ] + }, + "do-while": { + "prefix": "do-while", + "description": "Runs a statement list repeatedly as long as a condition is met. More: Get-Help about_Do", + "body": [ + "do {", + "\t${0:$TM_SELECTED_TEXT}", + "} while (", + "\t${1:<# Condition that stops the loop if it returns false #>}", + ")" + ] + }, + "else": { + "prefix": "else", + "description": "else defines what is done when all if and elseif conditions are false. More: Get-Help about_If", + "body": [ + "else {", + "\t${0:${TM_SELECTED_TEXT:<# Action when all if and elseif conditions are false #>}}", + "}" + ] + }, + "elseif": { + "prefix": "elseif", + "description": "elseif provides an alternative path when an if condition is false. More: Get-Help about_If", + "body": [ + "elseif (${1:<#condition#>}) {", + "\t${0:${TM_SELECTED_TEXT:<# Action when this condition is true #>}}", + "}" + ] + }, + "Enum": { + "prefix": "enum", + "description": "An enumeration is a distinct type that consists of a set of named labels called the enumerator list. More: Get-Help about_Enum", + "body": [ + "enum ${1:<#EnumName#>} {", + "\t${0:${TM_SELECTED_TEXT:<# Specify a list of distinct values #>}}", + "}" + ] + }, + "for": { + "prefix": "for", + "description": "Creates a loop that runs commands in a command block while a specified condition evaluates to $true. A typical use of the for loop is to iterate an array of values and to operate on a subset of these values. More: Get-Help about_For", + "body": [ + "for ($${1:i} = 0; $${1:i} -lt $${2:array}.Count; $${1:i}++) {", + "\t${0:${TM_SELECTED_TEXT:<# Action that will repeat until the condition is met #>}}", + "}" + ] + }, + "for-reversed": { + "prefix": "forr", + "description": "reversed for loop snippet", + "body": [ + "for ($${1:i} = $${2:array}.Count - 1; $${1:i} -ge 0 ; $${1:i}--) {", + "\t${0:${$TM_SELECTED_TEXT}}", + "}" + ] + }, + "foreach": { + "prefix": "foreach", + "description": "Iterate through a collection, assigning a variable to the current item on each loop rather than using the automatic variable $PSItem. More: Get-Help about_Foreach", + "body": [ + "foreach ($${1:currentItemName} in $${2:collection}) {", + "\t${0:${TM_SELECTED_TEXT:<# $${1} is the current item #>}}", + "}" + ] + }, + "foreach-item": { + "prefix": "foreach-item", + "description": "Quicker definition of foreach, just highlight the variable name of the collection you want to use and type 'item' then enter then tab. More: Get-Help about_Foreach", + "body": [ + "foreach (${1/(.*)/$1Item/} in ${1:${TM_SELECTED_TEXT:collection}}) {", + "\t${0:${1/(.*)/$1Item/}}", + "}" + ] + }, + "Foreach with Progress": { + "prefix": "foreach-progress", + "description": "Insert a foreach loop with Write-Progress initialized", + "body": [ + "\\$total = \\$${1:array}.count", + "\\$${4:i} = 1", + "\\$progPercent = \"{0:n2}\" -f ([math]::round(\\$${4:i}/\\$total,4) * 100)", + "Write-Progress -Activity \"${3:activityName}\" -Status \"\\$${4:i} of \\$total - \\$progPercent% Complete:\" -PercentComplete \\$progPercent", + "foreach ($${2:item} in $${1:array}) {", + " \\$progPercent = \"{0:n2}\" -f ([math]::round(\\$${4:i}/\\$total,4) * 100)", + " Write-Progress -Activity \"${3:activityName}\" -Status \"\\$${4:i} of \\$total - \\$progPercent% Complete:\" -PercentComplete \\$progPercent", + " # Insert Code Here", + " ${0}", + " ", + " \\$${4:i}++", + "}", + "" + ] + }, + "ForEach-Object -Parallel": { + "prefix": "foreach-parallel", + "description": "[PS 7+] Process multiple objects in parallel using runspaces. This has some limitations compared to a regular ForEach-Object. More: Get-Help ForEach-Object", + "body": [ + "${1:\\$collection} | Foreach-Object -ThrottleLimit ${2:5} -Parallel {", + " ${0:${TM_SELECTED_TEXT:#Action that will run in Parallel. Reference the current object via \\$PSItem and bring in outside variables with \\$USING:varname}}", + "}" + ] + }, + "function": { + "prefix": "function", + "description": "A simple function with a parameter block to specify function arguments. More: Get-Help about_Functions", + "body": [ + "function ${1:FunctionName} {", + "\tparam (", + "\t\t${2:OptionalParameters}", + "\t)", + "\t${0:$TM_SELECTED_TEXT}", + "}" + ] + }, + "Function Help": { + "prefix": ["help-function", "comment-help"], + "description": "Comment-based help for an advanced function. More: Get-Help about_Comment_Based_Help", + "body": [ + "<#", + ".SYNOPSIS", + "\t${1:A short one-line action-based description, e.g. 'Tests if a function is valid'}", + ".DESCRIPTION", + "\t${2:A longer description of the function, its purpose, common use cases, etc.}", + ".NOTES", + "\t${3:Information or caveats about the function e.g. 'This function is not supported in Linux'}", + ".LINK", + "\t${4:Specify a URI to a help page, this will show when Get-Help -Online is used.}", + ".EXAMPLE", + "\t${5:Test-MyTestFunction -Verbose}", + "\t${6:Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines}", + "#>", + "", + "${0:$TM_SELECTED_TEXT}" + ] + }, + "Function-Advanced": { + "prefix": ["function-advanced", "cmdlet"], + "description": "Script advanced function definition snippet. More: Get-Help about_Functions_Advanced", + "body": [ + "function ${1:Verb-Noun} {", + "\t[CmdletBinding()]", + "\tparam (", + "\t\t$0", + "\t)", + "\t", + "\tbegin {", + "\t\t", + "\t}", + "\t", + "\tprocess {", + "\t\t$TM_SELECTED_TEXT", + "\t}", + "\t", + "\tend {", + "\t\t", + "\t}", + "}" + ] + }, + "Function-Advanced-Doc-Full-Example-From-ISE": { + "prefix": ["function-advanced-doc-fromISE", "cmdlet-doc-fromISE"], + "description": "Script advanced function definition with full comment-based help and parameter attributes.", + "body": [ + "function ${1:Verb-Noun} {", + "\t<#", + "\t.SYNOPSIS", + "\t${2:Short description}", + "\t.DESCRIPTION", + "\t${3:Long description}", + "\t.EXAMPLE", + "\t${4:Example of how to use this cmdlet}", + "\t.EXAMPLE", + "\t${5:Another example of how to use this cmdlet}", + "\t.INPUTS", + "\t${6:Inputs to this cmdlet (if any)}", + "\t.OUTPUTS", + "\t${7:Output from this cmdlet (if any)}", + "\t.NOTES", + "\t${8:General notes}", + "\t.COMPONENT", + "\t${9:The component this cmdlet belongs to}", + "\t.ROLE", + "\t${10:The role this cmdlet belongs to}", + "\t.FUNCTIONALITY", + "\t${11:The functionality that best describes this cmdlet}", + "\t#>", + "\t[CmdletBinding(DefaultParameterSetName = '${12:ParameterSet1}',", + "\t\tSupportsShouldProcess,", + "\t\tPositionalBinding,", + "\t\tHelpUri = '${13:http://yourwebsiteforhelp.here}',", + "\t\tConfirmImpact = 'Medium')]", + "\t[Alias('${14:Be-lazyWithThis}','${15:lzy}','${16:Use-OldFunctionName}')]", + "\t[OutputType([${17:String}])]", + "\tparam (", + "\t\t# ${18:Param1} help description", + "\t\t[Parameter(Mandatory,", + "\t\t\tValueFromPipeline,", + "\t\t\tValueFromPipelineByPropertyName,", + "\t\t\tValueFromRemainingArguments,", + "\t\t\tPosition = 0,", + "\t\t\tParameterSetName = '${12:ParameterSet1}')]", + "\t\t[ValidateNotNull()]", + "\t\t[ValidateNotNullOrEmpty()]", + "\t\t[ValidateCount(0, 5)]", + "\t\t[ValidateSet(\"${19:sun}\", \"${20:moon}\", \"${21:earth}\")]", + "\t\t[Alias(\"${22:p1}\")]", + "\t\t$${18:Param1},", + "", + "\t\t# ${24:Param2} help description", + "\t\t[Parameter(ParameterSetName = '${12:ParameterSet1}')]", + "\t\t[AllowNull()]", + "\t\t[AllowEmptyCollection()]", + "\t\t[AllowEmptyString()]", + "\t\t[ValidateScript({ ${25:true} })]", + "\t\t[ValidateRange(0, 5)]", + "\t\t[${26:int}]", + "\t\t$${24:Param2},", + "", + "\t\t# ${28:Param3} help description", + "\t\t[Parameter(ParameterSetName = '${29:Another Parameter Set}')]", + "\t\t[ValidatePattern(\"${30:[a-z]*}\")]", + "\t\t[ValidateLength(0, 15)]", + "\t\t[${31:String}]", + "\t\t$${28:Param3},", + "", + "\t\t# ${33:Param4} help description", + "\t\t# Checkout the docs https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_argument_completion?view=powershell-7.5#argumentcompletions-attribute on different ways to provide Argument Completion", + "\t\t[Parameter(ParameterSetName = '${34:Yet Another Parameter Set}')]", + "\t\t[ArgumentCompleter({'${35:add completer script}'})]", + "\t\t[ValidateLength(0, 15)]", + "\t\t[${36:String}]", + "\t\t$${33:Param4}", + "\t)", + "", + "\tbegin {", + "\t\t${38:#BeginCodeHere}", + "\t}", + "", + "\tprocess {", + "\t\tif (\\$pscmdlet.ShouldProcess(\"${39:Target}\", \"${40:Operation}\")) {", + "\t\t\t${41:#ProcessCodeHere}", + "\t\t}", + "\t}", + "", + "\tend {", + "\t\t${42:#EndCodeHere}", + "\t}", + "", + "\tclean {", + "\t\t${43:#CleanCodeHere} - Added in 7.3 for more information see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_methods?view=powershell-7.5#clean", + "\t}", + "}" + ] + }, + "Function-Inline": { + "prefix": "function-inline", + "description": "Function definition snippet that does not contain a param block, but defines parameters inline. This syntax is commonly used in other languages. More: Get-Help about_Functions", + "body": [ + "function ${1:FunctionName} (${2:OptionalParameters}) {", + "\t${0:$TM_SELECTED_TEXT}", + "}" + ] + }, + "Function: Suppress PSScriptAnalyzer Rule": { + "prefix": ["suppress-message-rule-function", "[SuppressMessageAttribute]"], + "description": "Suppress a PSScriptAnalyzer rule for a function. More: https://docs.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/overview?view=ps-modules#suppressing-rules", + "body": [ + "[Diagnostics.CodeAnalysis.SuppressMessageAttribute(", + "\t<#Category#>'${1:PSProvideDefaultParameterValue}', <#CheckId#>\\$null,", + "\tScope='Function',", + "\tJustification='${0:${TM_SELECTED_TEXT:Reason for suppressing}}'", + ")]" + ] + }, + "Hashtable": { + "prefix": "hashtable", + "description": "A key/value store that are very efficient for finding and retrieving data. More: Get-Help about_Hash_Tables", + "body": ["\\$${1:Var} = @{", "\t${2:Name} = ${3:Value}", "}"] + }, + "Here-String": { + "prefix": ["hs", "here-string"], + "description": "Escape all text but evaluate variables. More: Get-Help about_Quoting_Rules", + "body": ["@\"", "${0:TM_SELECTED_TEXT}", "\"@", ""] + }, + "Here-String (Literal)": { + "prefix": ["hsl", "literal-here-string"], + "description": "Escape all text literally. More: Get-Help about_Quoting_Rules", + "body": ["@'", "${0:TM_SELECTED_TEXT}", "'@", ""] + }, + "Hidden Property": { + "prefix": "class-proph-hidden", + "description": "Useful for creating internal properties and methods within a class that are hidden from users. More: Get-Help about_Hidden", + "body": ["hidden [${1:string}] $${0:PropertyName}"] + }, + "IArgumentCompleter Class": { + "prefix": "iargument-completer", + "description": "Implementation of the IArgumentCompleter interface that can be directly attached to parameters (e.g. [MyCustomArgumentCompleter]). More: Get-Help about_Functions_Argument_Completion", + "body": [ + "class ${1:ArgumentCompleter} : System.Management.Automation.IArgumentCompleter {", + "\t[System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument(", + "\t\t[string] \\$CommandName,", + "\t\t[string] \\$ParameterName,", + "\t\t[string] \\$WordToComplete,", + "\t\t[System.Management.Automation.Language.CommandAst] \\$CommandAst,", + "\t\t[System.Collections.IDictionary] \\$FakeBoundParameters", + "\t) {", + "\t\t\\$CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()", + "\t\t", + "\t\t${0:$TM_SELECTED_TEXT}", + "\t\t", + "\t\treturn \\$CompletionResults", + "\t}", + "}" + ] + }, + "if": { + "prefix": "if", + "description": "Run code blocks if a specified conditional test evaluates to true. More: Get-Help about_If", + "body": [ + "if (${1:condition}) {", + "\t${0:${TM_SELECTED_TEXT:<# Action to perform if the condition is true #>}}", + "}" + ] + }, + "IfShouldProcess": { + "prefix": "if-should-process", + "description": "Defines a condition that only executes if -WhatIf is not set, and returns a message otherwise. More: https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-shouldprocess", + "body": [ + "if (\\$PSCmdlet.ShouldProcess(\"${1:Target}\", \"${2:Operation}\")) {", + "\t${0:$TM_SELECTED_TEXT}", + "}" + ] + }, + "ModuleManifest": { + "prefix": "manifest", + "description": "Basic skeleton for a PowerShell module manifest, complete with PowerShell Gallery metadata. More: https://docs.microsoft.com/en-us/powershell/scripting/developer/module/how-to-write-a-powershell-module-manifest", + "body": [ + "@{", + "\t# If authoring a script module, the RootModule is the name of your .psm1 file", + "\tRootModule = '${module:MyModule}.psm1'", + "", + "\tAuthor = '${author:Cool Person }'", + "", + "\tCompanyName = '${company:Contoso Inc.}'", + "", + "\tModuleVersion = '${ModuleVersion:0.1}'", + "", + "\t# Use the New-Guid command to generate a GUID, and copy/paste into the next line", + "\tGUID = ''", + "", + "\tCopyright = '2017 ${company:Copyright Holder}'", + "", + "\tDescription = '${Description:What does this module do?}'", + "", + "\t# Minimum PowerShell version supported by this module (optional, recommended)", + "\t# PowerShellVersion = ''", + "", + "\t# Which PowerShell Editions does this module work with? (Core, Desktop)", + "\tCompatiblePSEditions = @('Desktop', 'Core')", + "", + "\t# Which PowerShell functions are exported from your module? (eg. Get-CoolObject)", + "\tFunctionsToExport = @('')", + "", + "\t# Which PowerShell aliases are exported from your module? (eg. gco)", + "\tAliasesToExport = @('')", + "", + "\t# Which PowerShell variables are exported from your module? (eg. Fruits, Vegetables)", + "\tVariablesToExport = @('')", + "", + "\t# PowerShell Gallery: Define your module's metadata", + "\tPrivateData = @{", + "\t\tPSData = @{", + "\t\t\t# What keywords represent your PowerShell module? (eg. cloud, tools, framework, vendor)", + "\t\t\tTags = @('${tag1:cooltag1}', '${tag2:cooltag2}')", + "", + "\t\t\t# What software license is your code being released under? (see https://opensource.org/licenses)", + "\t\t\tLicenseUri = ''", + "", + "\t\t\t# What is the URL to your project's website?", + "\t\t\tProjectUri = ''", + "", + "\t\t\t# What is the URI to a custom icon file for your project? (optional)", + "\t\t\tIconUri = ''", + "", + "\t\t\t# What new features, bug fixes, or deprecated features, are part of this release?", + "\t\t\tReleaseNotes = @'", + "'@", + "\t\t}", + "\t}", + "", + "\t# If your module supports updatable help, what is the URI to the help archive? (optional)", + "\t# HelpInfoURI = ''", + "}" + ] + }, + "Parallel Pipeline Function": { + "prefix": "function-parallel-pipeline", + "description": "Collects everything in the process block and does work in the end block. Useful when making a 'fan out' function that acts on multiple items simultaneously because the pipeline only does one item at a time in the process block. More: Get-Help about_Functions_Advanced", + "body": [ + "function $1 {", + " [CmdletBinding()]", + " param(", + " [parameter(ValueFromPipeline)]$$2", + " )", + "", + " begin {", + " [Collections.ArrayList]\\$inputObjects = @()", + " }", + " process {", + " [void]\\$inputObjects.Add($$2)", + " }", + " end {", + " \\$inputObjects | Foreach -Parallel {", + " $0", + " }", + " }", + "}" + ] + }, + "Parameter": { + "prefix": "parameter", + "description": "A parameter definition for a method or function. More: Get-Help about_Functions", + "body": [ + "# ${1:Parameter help description}", + "[Parameter(${2:AttributeValues})]", + "[${3:ParameterType}]", + "$${0:ParameterName}" + ] + }, + "Parameter_Block": { + "prefix": "param-block-advanced-function", + "description": "A parameter block for an advanced function. More: Get-Help about_Functions_Advanced", + "body": [ + "[CmdletBinding()]", + "param (", + " [Parameter()]", + " [${1:TypeName}]", + " $${2:ParameterName}$0", + ")" + ] + }, + "Parameter-LiteralPath": { + "prefix": "parameter-literalpath", + "description": "Parameter declaration snippet for a LiteralPath parameter", + "body": [ + "# Specifies a path to one or more locations. Unlike the Path parameter, the value of the LiteralPath parameter is", + "# used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters,", + "# enclose it in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any", + "# characters as escape sequences.", + "[Parameter(Mandatory=\\$true,", + " Position=${1:0},", + " ParameterSetName=\"${2:LiteralPath}\",", + " ValueFromPipelineByPropertyName=\\$true,", + " HelpMessage=\"Literal path to one or more locations.\")]", + "[Alias(\"PSPath\")]", + "[ValidateNotNullOrEmpty()]", + "[string[]]", + "$${2:LiteralPath}$0" + ] + }, + "Parameter-Path": { + "prefix": "parameter-path", + "description": "Parameter declaration snippet for Path parameter that does not accept wildcards. Do not use with parameter-literalpath.", + "body": [ + "# Specifies a path to one or more locations.", + "[Parameter(Mandatory=\\$true,", + " Position=${1:0},", + " ParameterSetName=\"${2:ParameterSetName}\",", + " ValueFromPipeline=\\$true,", + " ValueFromPipelineByPropertyName=\\$true,", + " HelpMessage=\"Path to one or more locations.\")]", + "[Alias(\"PSPath\")]", + "[ValidateNotNullOrEmpty()]", + "[string[]]", + "$${3:ParameterName}$0" + ] + }, + "Parameter-Path-Wildcards": { + "prefix": "parameter-path-wildcards", + "description": "Parameter declaration snippet for Path parameter that accepts wildcards. Add parameter-literalpath to handle paths with embedded wildcard chars.", + "body": [ + "# Specifies a path to one or more locations. Wildcards are permitted.", + "[Parameter(Mandatory=\\$true,", + " Position=${1:Position},", + " ParameterSetName=\"${2:ParameterSetName}\",", + " ValueFromPipeline=\\$true,", + " ValueFromPipelineByPropertyName=\\$true,", + " HelpMessage=\"Path to one or more locations.\")]", + "[ValidateNotNullOrEmpty()]", + "[SupportsWildcards()]", + "[string[]]", + "$${3:ParameterName}$0" + ] + }, + "Parameter: Suppress PSScriptAnalyzer Rule": { + "prefix": ["suppress-message-rule-parameter", "[SuppressMessageAttribute]"], + "description": "Suppress a PSScriptAnalyzer rule on a parameter. More: https://docs.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/overview?view=ps-modules#suppressing-rules", + "body": [ + "[Diagnostics.CodeAnalysis.SuppressMessageAttribute(", + "\t<#Category#>'${1:PSUseDeclaredVarsMoreThanAssignments}',", + "\t<#ParameterName#>'${2:${TM_SELECTED_TEXT:ParamName}}',", + "\tJustification='${0:Reason for suppressing}'", + ")]" + ] + }, + "Pipeline Function": { + "prefix": "function-pipeline", + "description": "Basic function that accepts pipeline input. More: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipelines", + "body": [ + "function $1 {", + " [CmdletBinding()]", + " param(", + " [parameter(ValueFromPipeline)]$2", + " )", + "", + " process {", + " $0", + " }", + "}" + ] + }, + "PSCustomObject": { + "prefix": ["pscustomobject", "[PSCustomObject]"], + "description": "Create a custom object from a hashtable of properties. More: Get-Help about_PSCustomObject", + "body": ["[PSCustomObject]@{", "\t${1:Name} = ${2:Value}", "}"] + }, + "Region Block": { + "prefix": "region", + "description": "Region block for organizing and folding of your code", + "body": ["#region ${1}", "${0:$TM_SELECTED_TEXT}", "#endregion"] + }, + "Scope: Suppress PSScriptAnalyzer Rule": { + "prefix": ["suppress-message-rule-scope", "[SuppressMessageAttribute]"], + "description": "Suppress a PSScriptAnalyzer rule based on a function/parameter/class/variable/object's name by setting the SuppressMessageAttribute's Target property to a regular expression or a glob pattern. More: https://docs.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/overview?view=ps-modules#suppressing-rules", + "body": [ + "[Diagnostics.CodeAnalysis.SuppressMessageAttribute(", + "\t<#Category#>'${1:PSUseDeclaredVarsMoreThanAssignments}', <#CheckId#>\\$null,", + "\tScope='${2|Function,Parameter,Class,Variable,Object|}',", + "\tTarget='${3:${TM_SELECTED_TEXT:RegexOrGlobPatternToMatchName}}',", + "\tJustification='${0:Reason for suppressing}'", + ")]" + ] + }, + "splat": { + "prefix": "splat", + "description": "Use a hashtable to capture the parameters of a function and then pass them to a function in a concise way. More: Get-Help about_Splatting", + "body": [ + "$${1/[^\\w]/_/}Params = @{", + "\t${2:Parameter} = ${0:Value}", + "}", + "${1:${TM_SELECTED_TEXT}} @${1/[^\\w]/_/}Params" + ] + }, + "Suppress PSScriptAnalyzer Rule": { + "prefix": ["suppress-message-rule", "[SuppressMessageAttribute]"], + "description": "Suppress a PSScriptAnalyzer rule. More: https://docs.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/overview?view=ps-modules#suppressing-rules", + "body": [ + "[Diagnostics.CodeAnalysis.SuppressMessageAttribute(", + "\t<#Category#>'${1:PSUseDeclaredVarsMoreThanAssignments}',<#CheckId#>\\$null,", + "\tJustification = '${0:${TM_SELECTED_TEXT:Reason for suppressing}}'", + ")]" + ] + }, + "switch": { + "prefix": "switch", + "description": "Equivalent to a series of if statements, but it is simpler. The switch statement lists each condition and an optional action. If a condition obtains, the action is performed. More: Get-Help about_Switch", + "body": [ + "switch (${1:\\$x}) {", + "\t${2:condition} { ${0:$TM_SELECTED_TEXT} }", + "\tDefault {}", + "}" + ] + }, + "Ternary Operator": { + "prefix": "ternary", + "description": "[PS 7+] Simplified version of if-else popular in other languages that works in Powershell. More: Get-Help about_If", + "body": [ + "(${1:${TM_SELECTED_TEXT:condition}}) ? $(${2:<#Action if True#>}) : $(${0:<#Action If False#>})" + ] + }, + "try-catch": { + "prefix": "try-catch", + "description": "Attempt a block of code and if a terminating exception occurs, perform another block of code rather than terminate the program More: Get-Help about_Try_Catch_Finally", + "body": [ + "try {", + "\t${0:$TM_SELECTED_TEXT}", + "}", + "catch {", + "\t${1:<#Do this if a terminating exception happens#>}", + "}" + ] + }, + "try-catch-finally": { + "prefix": "try-catch-finally", + "description": "Attempt a block of code and if a terminating exception occurs, perform another block of code, finally performing a final block of code regardless of the outcome. More: Get-Help about_Try_Catch_Finally", + "body": [ + "try {", + "\t${0:$TM_SELECTED_TEXT}", + "}", + "catch {", + "\t${1:<#Do this if a terminating exception happens#>}", + "}", + "finally {", + "\t${2:<#Do this after the try block regardless of whether an exception occurred or not#>}", + "}" + ] + }, + "try-finally": { + "prefix": "try-finally", + "description": "Attempt a block of code and perform an action regardless of the outcome. Useful for cleanup or gracefully disconnecting active sessions even if there was a terminating error. More: Get-Help about_Try_Catch_Finally", + "body": [ + "try {", + "\t${0:$TM_SELECTED_TEXT}", + "}", + "finally {", + "\t${2:<#Do this after the try block regardless of whether an exception occurred or not#>}", + "}" + ] + }, + "while": { + "prefix": "while", + "description": "Repeatedly perform an action after verifying a condition is true first. More: Get-Help about_While", + "body": ["while (${1:condition}) {", "\t${0:$TM_SELECTED_TEXT}", "}"] + } +} diff --git a/src/controls/checkboxQuickPick.ts b/src/controls/checkboxQuickPick.ts new file mode 100644 index 0000000000..2c8bf72c07 --- /dev/null +++ b/src/controls/checkboxQuickPick.ts @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); + +const confirmItemLabel = "$(checklist) Confirm"; +const checkedPrefix = "[ $(check) ]"; +const uncheckedPrefix = "[ ]"; +const defaultPlaceHolder = + "Select 'Confirm' to confirm or press 'Esc' key to cancel"; + +export interface ICheckboxQuickPickItem { + label: string; + description?: string; + isSelected: boolean; +} + +export interface ICheckboxQuickPickOptions { + confirmPlaceHolder: string; +} + +const defaultOptions: ICheckboxQuickPickOptions = { + confirmPlaceHolder: defaultPlaceHolder, +}; + +export async function showCheckboxQuickPick( + items: ICheckboxQuickPickItem[], + options: ICheckboxQuickPickOptions = defaultOptions, +): Promise { + const selectedItem = await showInner(items, options); + return selectedItem !== undefined ? items : undefined; +} + +function getQuickPickItems( + items: ICheckboxQuickPickItem[], +): vscode.QuickPickItem[] { + const quickPickItems: vscode.QuickPickItem[] = []; + quickPickItems.push({ label: confirmItemLabel, description: "" }); + + for (const item of items) { + quickPickItems.push({ + label: convertToCheckBox(item), + description: item.description, + }); + } + + return quickPickItems; +} + +async function showInner( + items: ICheckboxQuickPickItem[], + options: ICheckboxQuickPickOptions, +): Promise { + const selection = await vscode.window.showQuickPick( + getQuickPickItems(items), + { + ignoreFocusOut: true, + matchOnDescription: true, + placeHolder: options.confirmPlaceHolder, + }, + ); + + if (selection === undefined) { + return undefined; + } + + if (selection.label === confirmItemLabel) { + return selection; + } + + const index: number = getItemIndex(items, selection.label); + if (index >= 0) { + toggleSelection(items[index]); + } else { + console.log( + `Couldn't find CheckboxQuickPickItem for label '${selection.label}'`, + ); + } + + return showInner(items, options); +} + +function getItemIndex( + items: ICheckboxQuickPickItem[], + itemLabel: string, +): number { + const trimmedLabel = itemLabel.substring(itemLabel.indexOf("]") + 2); + return items.findIndex((item) => item.label === trimmedLabel); +} + +function toggleSelection(item: ICheckboxQuickPickItem): void { + item.isSelected = !item.isSelected; +} + +function convertToCheckBox(item: ICheckboxQuickPickItem): string { + return `${item.isSelected ? checkedPrefix : uncheckedPrefix} ${item.label}`; +} diff --git a/src/extension.ts b/src/extension.ts new file mode 100644 index 0000000000..d89708440f --- /dev/null +++ b/src/extension.ts @@ -0,0 +1,298 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import TelemetryReporter from "@vscode/extension-telemetry"; +import { DocumentSelector } from "vscode-languageclient"; +import { CodeActionsFeature } from "./features/CodeActions"; +import { ConsoleFeature } from "./features/Console"; +import { + DebugSessionFeature, + SpecifyScriptArgsFeature, +} from "./features/DebugSession"; +import { ExamplesFeature } from "./features/Examples"; +import { ExpandAliasFeature } from "./features/ExpandAlias"; +import { ExtensionCommandsFeature } from "./features/ExtensionCommands"; +import { + ExternalApiFeature, + type IPowerShellExtensionClient, +} from "./features/ExternalApi"; +import { GenerateBugReportFeature } from "./features/GenerateBugReport"; +import { GetCommandsFeature } from "./features/GetCommands"; +import { HelpCompletionFeature } from "./features/HelpCompletion"; +import { ISECompatibilityFeature } from "./features/ISECompatibility"; +import { OpenInISEFeature } from "./features/OpenInISE"; +import { PesterTestsFeature } from "./features/PesterTests"; +import { RemoteFilesFeature } from "./features/RemoteFiles"; +import { ShowHelpFeature } from "./features/ShowHelp"; +import { LanguageClientConsumer } from "./languageClientConsumer"; +import { Logger } from "./logging"; +import { SessionManager } from "./session"; +import { getSettings } from "./settings"; +import { PowerShellLanguageId, sleep } from "./utils"; +// The 1DS telemetry key, which is just shared among all Microsoft extensions +// (and isn't sensitive). +const TELEMETRY_KEY = + "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; + +let languageConfigurationDisposable: vscode.Disposable; +let logger: Logger; +let sessionManager: SessionManager; +let languageClientConsumers: LanguageClientConsumer[] = []; +let commandRegistrations: vscode.Disposable[] = []; +let telemetryReporter: TelemetryReporter; + +const documentSelector: DocumentSelector = [ + { language: "powershell", scheme: "file" }, + { language: "powershell", scheme: "untitled" }, +]; + +export async function activate( + context: vscode.ExtensionContext, +): Promise { + logger = new Logger(); + if (context.extensionMode === vscode.ExtensionMode.Development) { + restartOnExtensionFileChanges(context); + } + + telemetryReporter = new TelemetryReporter(TELEMETRY_KEY); + + const settings = getSettings(); + logger.writeDebug( + `Loaded settings:\n${JSON.stringify(settings, undefined, 2)}`, + ); + + languageConfigurationDisposable = vscode.languages.setLanguageConfiguration( + PowerShellLanguageId, + { + // TODO: Remove the useless escapes + wordPattern: + // eslint-disable-next-line no-useless-escape + /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\'\"\,\.\<\>\/\?\s]+)/g, + + indentationRules: { + // ^(.*\*/)?\s*\}.*$ + decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/, + // ^.*\{[^}"']*$ + increaseIndentPattern: /^.*\{[^}"']*$/, + }, + + comments: { + lineComment: "#", + blockComment: ["<#", "#>"], + }, + + brackets: [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ], + + onEnterRules: [ + { + // e.g. /** | */ + // eslint-disable-next-line no-useless-escape + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { + indentAction: vscode.IndentAction.IndentOutdent, + appendText: " * ", + }, + }, + { + // e.g. /** ...| + // eslint-disable-next-line no-useless-escape + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { + indentAction: vscode.IndentAction.None, + appendText: " * ", + }, + }, + { + // e.g. * ...| + // eslint-disable-next-line no-useless-escape + beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { + indentAction: vscode.IndentAction.None, + appendText: "* ", + }, + }, + { + // e.g. */| + // eslint-disable-next-line no-useless-escape + beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, + action: { + indentAction: vscode.IndentAction.None, + removeText: 1, + }, + }, + { + // e.g. *-----*/| + // eslint-disable-next-line no-useless-escape + beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/, + action: { + indentAction: vscode.IndentAction.None, + removeText: 1, + }, + }, + ], + }, + ); + + interface IPackageInfo { + name: string; + displayName: string; + version: string; + publisher: string; + } + const packageInfo: IPackageInfo = context.extension.packageJSON; + + sessionManager = new SessionManager( + context, + settings, + logger, + documentSelector, + packageInfo.name, + packageInfo.displayName, + packageInfo.version, + packageInfo.publisher, + telemetryReporter, + ); + + // Register commands that do not require Language client + commandRegistrations = [ + new ExamplesFeature(), + new GenerateBugReportFeature(sessionManager), + new ISECompatibilityFeature(), + new OpenInISEFeature(), + new PesterTestsFeature(sessionManager, logger), + new CodeActionsFeature(logger), + new SpecifyScriptArgsFeature(context), + + vscode.commands.registerCommand( + "PowerShell.OpenLogFolder", + async () => { + await vscode.commands.executeCommand( + "vscode.openFolder", + context.logUri, + { forceNewWindow: true }, + ); + }, + ), + vscode.commands.registerCommand("PowerShell.ShowLogs", () => { + logger.showLogPanel(); + }), + vscode.commands.registerCommand( + "GetVsCodeSessionId", + () => vscode.env.sessionId, + ), + // Register a command that waits for the Extension Terminal to be active. Can be used by .NET Attach Tasks. + registerWaitForPsesActivationCommand(context), + ]; + + const externalApi = new ExternalApiFeature(context, sessionManager, logger); + + // Features and command registrations that require language client + languageClientConsumers = [ + new ConsoleFeature(logger), + new ExpandAliasFeature(), + new GetCommandsFeature(), + new ShowHelpFeature(), + new ExtensionCommandsFeature(logger), + new RemoteFilesFeature(), + new DebugSessionFeature(context, sessionManager, logger), + new HelpCompletionFeature(), + ]; + + sessionManager.setLanguageClientConsumers(languageClientConsumers); + + if (settings.startAutomatically) { + await sessionManager.start(); + } + + return { + registerExternalExtension: (id: string, apiVersion = "v1") => + externalApi.registerExternalExtension(id, apiVersion), + unregisterExternalExtension: (uuid) => + externalApi.unregisterExternalExtension(uuid), + getPowerShellVersionDetails: (uuid) => + externalApi.getPowerShellVersionDetails(uuid), + waitUntilStarted: (uuid) => externalApi.waitUntilStarted(uuid), + getStorageUri: () => externalApi.getStorageUri(), + getLogUri: () => externalApi.getLogUri(), + }; +} + +/** Registers a command that waits for PSES Activation and returns the PID, used to auto-attach the PSES debugger */ +function registerWaitForPsesActivationCommand( + context: vscode.ExtensionContext, +): vscode.Disposable { + return vscode.commands.registerCommand( + "PowerShell.WaitForPsesActivationAndReturnProcessId", + async () => { + const pidFileName = `PSES-${vscode.env.sessionId}.pid`; + const pidFile = vscode.Uri.joinPath( + context.globalStorageUri, + "sessions", + pidFileName, + ); + const fs = vscode.workspace.fs; + // Wait for the file to be created + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + while (true) { + try { + const pidContent = await fs.readFile(pidFile); + const pid = parseInt(pidContent.toString(), 10); + try { + // Check if the process is still alive, delete the PID file if not and continue waiting. + // https://nodejs.org/api/process.html#process_process_kill_pid_signal + // "As a special case, a signal of 0 can be used to test for the existence of a process. " + const NODE_TEST_PROCESS_EXISTENCE = 0; + process.kill(pid, NODE_TEST_PROCESS_EXISTENCE); + } catch { + await fs.delete(pidFile); + continue; + } + // VSCode command returns for launch configurations *must* be string type explicitly, will error on number or otherwise. + return pidContent.toString(); + } catch { + // File doesn't exist yet, wait and try again + await sleep(200); + } + } + }, + ); +} + +/** Restarts the extension host when extension file changes are detected. Useful for development. */ +function restartOnExtensionFileChanges(context: vscode.ExtensionContext): void { + const watcher = vscode.workspace.createFileSystemWatcher( + new vscode.RelativePattern(context.extensionPath, "dist/*.js"), + ); + + context.subscriptions.push(watcher); + watcher.onDidChange(({ fsPath }) => { + vscode.window.showInformationMessage( + `${fsPath.split(context.extensionPath, 2)[1]} changed. Reloading Extension Host...`, + ); + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + }); +} + +export async function deactivate(): Promise { + // Clean up all extension features + for (const commandRegistration of commandRegistrations) { + commandRegistration.dispose(); + } + + // Dispose of the current session + await sessionManager.dispose(); + + // Dispose of the logger + logger.dispose(); + + // Dispose of telemetry reporter + await telemetryReporter.dispose(); + + languageConfigurationDisposable.dispose(); +} diff --git a/src/features/CodeActions.ts b/src/features/CodeActions.ts new file mode 100644 index 0000000000..825b7941a9 --- /dev/null +++ b/src/features/CodeActions.ts @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import type { ILogger } from "../logging"; + +export class CodeActionsFeature implements vscode.Disposable { + private command: vscode.Disposable; + + constructor(private log: ILogger) { + // NOTE: While not exposed to the user via package.json, this is + // required as the server's code action sends across a command name. + // + // TODO: In the far future with LSP 3.19 the server can just set a URL + // and this can go away. See https://github.com/microsoft/language-server-protocol/issues/1548 + this.command = vscode.commands.registerCommand( + "PowerShell.ShowCodeActionDocumentation", + async (ruleName: string) => { + await this.showRuleDocumentation(ruleName); + }, + ); + } + + public dispose(): void { + this.command.dispose(); + } + + private async showRuleDocumentation(ruleId: string): Promise { + const pssaDocBaseURL = + "https://docs.microsoft.com/powershell/utility-modules/psscriptanalyzer/rules/"; + + if (!ruleId) { + this.log.writeWarning( + "Cannot show documentation for code action, no ruleName was supplied.", + ); + return; + } + + if (ruleId.startsWith("PS")) { + ruleId = ruleId.substring(2); + } + + await vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.parse(pssaDocBaseURL + ruleId), + ); + } +} diff --git a/src/features/Console.ts b/src/features/Console.ts new file mode 100644 index 0000000000..f7038f5ec1 --- /dev/null +++ b/src/features/Console.ts @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import { NotificationType, RequestType } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { + type ICheckboxQuickPickItem, + showCheckboxQuickPick, +} from "../controls/checkboxQuickPick"; +import { LanguageClientConsumer } from "../languageClientConsumer"; +import type { ILogger } from "../logging"; +import { getSettings } from "../settings"; + +export const EvaluateRequestType = new RequestType< + IEvaluateRequestArguments, + void, + void +>("evaluate"); +export const OutputNotificationType = + new NotificationType("output"); + +export const ShowChoicePromptRequestType = new RequestType< + IShowChoicePromptRequestArgs, + IShowChoicePromptResponseBody, + string +>("powerShell/showChoicePrompt"); + +export const ShowInputPromptRequestType = new RequestType< + IShowInputPromptRequestArgs, + IShowInputPromptResponseBody, + string +>("powerShell/showInputPrompt"); + +export interface IEvaluateRequestArguments { + expression: string; +} + +export interface IOutputNotificationBody { + category: string; + output: string; +} + +interface IChoiceDetails { + label: string; + helpMessage: string; +} + +interface IShowInputPromptRequestArgs { + name: string; + label: string; +} + +interface IShowChoicePromptRequestArgs { + isMultiChoice: boolean; + caption: string; + message: string; + choices: IChoiceDetails[]; + defaultChoices: number[]; +} + +interface IShowChoicePromptResponseBody { + responseText: string | undefined; + promptCancelled: boolean; +} + +interface IShowInputPromptResponseBody { + responseText: string | undefined; + promptCancelled: boolean; +} + +function showChoicePrompt( + promptDetails: IShowChoicePromptRequestArgs, +): Thenable { + let resultThenable: Thenable; + + if (!promptDetails.isMultiChoice) { + let quickPickItems = promptDetails.choices.map( + (choice) => { + return { + label: choice.label, + description: choice.helpMessage, + }; + }, + ); + + if (promptDetails.defaultChoices.length > 0) { + // Shift the default items to the front of the + // array so that the user can select it easily + const defaultChoice = promptDetails.defaultChoices[0]; + if ( + defaultChoice > -1 && + defaultChoice < promptDetails.choices.length + ) { + const defaultChoiceItem = quickPickItems[defaultChoice]; + quickPickItems.splice(defaultChoice, 1); + + // Add the default choice to the head of the array + quickPickItems = [defaultChoiceItem].concat(quickPickItems); + } + } + + resultThenable = vscode.window + .showQuickPick(quickPickItems, { + placeHolder: promptDetails.message, + }) + .then(onItemSelected); + } else { + const checkboxQuickPickItems = + promptDetails.choices.map((choice) => { + return { + label: choice.label, + description: choice.helpMessage, + isSelected: false, + }; + }); + + // Select the defaults + for (const choice of promptDetails.defaultChoices) { + checkboxQuickPickItems[choice].isSelected = true; + } + + resultThenable = showCheckboxQuickPick(checkboxQuickPickItems, { + confirmPlaceHolder: promptDetails.message, + }).then(onItemsSelected); + } + + return resultThenable; +} + +async function showInputPrompt( + promptDetails: IShowInputPromptRequestArgs, +): Promise { + const responseText = await vscode.window.showInputBox({ + placeHolder: promptDetails.name + ": ", + }); + return onInputEntered(responseText); +} + +function onItemsSelected( + chosenItems: ICheckboxQuickPickItem[] | undefined, +): IShowChoicePromptResponseBody { + if (chosenItems !== undefined) { + return { + promptCancelled: false, + responseText: chosenItems + .filter((item) => item.isSelected) + .map((item) => item.label) + .join(", "), + }; + } else { + // User cancelled the prompt, send the cancellation + return { + promptCancelled: true, + responseText: undefined, + }; + } +} + +function onItemSelected( + chosenItem: vscode.QuickPickItem | undefined, +): IShowChoicePromptResponseBody { + if (chosenItem !== undefined) { + return { + promptCancelled: false, + responseText: chosenItem.label, + }; + } else { + // User cancelled the prompt, send the cancellation + return { + promptCancelled: true, + responseText: undefined, + }; + } +} + +function onInputEntered( + responseText: string | undefined, +): IShowInputPromptResponseBody { + if (responseText !== undefined) { + return { + promptCancelled: false, + responseText, + }; + } else { + return { + promptCancelled: true, + responseText: undefined, + }; + } +} + +export class ConsoleFeature extends LanguageClientConsumer { + private commands: vscode.Disposable[]; + private handlers: vscode.Disposable[] = []; + + constructor(private logger: ILogger) { + super(); + this.commands = [ + vscode.commands.registerCommand( + "PowerShell.RunSelection", + async () => { + if ( + vscode.window.activeTerminal && + vscode.window.activeTerminal.name !== + "PowerShell Extension" + ) { + this.logger.write( + "PowerShell Extension Terminal is not active! Running in current terminal using 'runSelectedText'.", + ); + await vscode.commands.executeCommand( + "workbench.action.terminal.runSelectedText", + ); + + // We need to honor the focusConsoleOnExecute setting here too. However, the boolean that `show` + // takes is called `preserveFocus` which when `true` the terminal will not take focus. + // This is the inverse of focusConsoleOnExecute so we have to inverse the boolean. + vscode.window.activeTerminal.show( + !getSettings().integratedConsole + .focusConsoleOnExecute, + ); + await vscode.commands.executeCommand( + "workbench.action.terminal.scrollToBottom", + ); + + return; + } + + const editor = vscode.window.activeTextEditor; + if (editor === undefined) { + return; + } + + let selectionRange: vscode.Range; + + if (!editor.selection.isEmpty) { + selectionRange = new vscode.Range( + editor.selection.start, + editor.selection.end, + ); + } else { + selectionRange = editor.document.lineAt( + editor.selection.start.line, + ).range; + } + const client = + await LanguageClientConsumer.getLanguageClient(); + await client.sendRequest(EvaluateRequestType, { + expression: editor.document.getText(selectionRange), + }); + + // Show the Extension Terminal if it isn't already visible and + // scroll terminal to bottom so new output is visible + await vscode.commands.executeCommand( + "PowerShell.ShowSessionConsole", + true, + ); + await vscode.commands.executeCommand( + "workbench.action.terminal.scrollToBottom", + ); + }, + ), + ]; + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + + for (const handler of this.handlers) { + handler.dispose(); + } + } + + public override onLanguageClientSet(languageClient: LanguageClient): void { + this.handlers = [ + languageClient.onRequest( + ShowChoicePromptRequestType, + (promptDetails) => showChoicePrompt(promptDetails), + ), + + languageClient.onRequest( + ShowInputPromptRequestType, + (promptDetails) => showInputPrompt(promptDetails), + ), + ]; + } +} diff --git a/src/features/DebugSession.ts b/src/features/DebugSession.ts new file mode 100644 index 0000000000..49e964c44e --- /dev/null +++ b/src/features/DebugSession.ts @@ -0,0 +1,977 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import type { DebugProtocol } from "@vscode/debugprotocol"; +import path from "path"; +import { + CancellationTokenSource, + DebugAdapterExecutable, + DebugAdapterNamedPipeServer, + DebugConfigurationProviderTriggerKind, + Disposable, + commands, + debug, + extensions, + window, + workspace, + type CancellationToken, + type DebugAdapterDescriptor, + type DebugAdapterDescriptorFactory, + type DebugAdapterTracker, + type DebugAdapterTrackerFactory, + type DebugConfiguration, + type DebugConfigurationProvider, + type DebugSession, + type ExtensionContext, + type InputBoxOptions, + type LogOutputChannel, + type QuickPickItem, + type QuickPickOptions, + type WorkspaceFolder, +} from "vscode"; +import { NotificationType, RequestType } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; +import type { ILogger } from "../logging"; +import { OperatingSystem, getPlatformDetails } from "../platform"; +import { PowerShellProcess } from "../process"; +import { SessionManager, type IEditorServicesSessionDetails } from "../session"; +import { getSettings } from "../settings"; +import { checkIfFileExists } from "../utils"; + +export const StartDebuggerNotificationType = new NotificationType( + "powerShell/startDebugger", +); + +export const StopDebuggerNotificationType = new NotificationType( + "powerShell/stopDebugger", +); + +export enum DebugConfig { + LaunchCurrentFile, + LaunchScript, + InteractiveSession, + AttachHostProcess, + RunPester, + ModuleInteractiveSession, + BinaryModule, + BinaryModulePester, + WindowsPowerShell, +} + +/** Make the implicit behavior of undefined and null in the debug api more explicit */ +type PREVENT_DEBUG_START = undefined; +type PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG = null; +type ResolveDebugConfigurationResult = + | DebugConfiguration + | PREVENT_DEBUG_START + | PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + +const PREVENT_DEBUG_START = undefined; +const PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG = null; + +/** Represents the various built-in debug configurations that will be advertised to the user if they choose "Add Config" from the launch debug config window */ +// NOTE: These are duplicated with what is in package.json until https://github.com/microsoft/vscode/issues/150663#issuecomment-1506134754 is resolved. +export const DebugConfigurations: Record = { + [DebugConfig.LaunchCurrentFile]: { + name: "PowerShell: Launch Current File", + type: "PowerShell", + request: "launch", + script: "${file}", + args: [], + }, + [DebugConfig.LaunchScript]: { + name: "PowerShell: Launch Script", + type: "PowerShell", + request: "launch", + script: 'Enter path or command to execute, for example: "${workspaceFolder}/src/foo.ps1" or "Invoke-Pester"', + args: [], + }, + [DebugConfig.InteractiveSession]: { + name: "PowerShell: Interactive Session", + type: "PowerShell", + request: "launch", + }, + [DebugConfig.AttachHostProcess]: { + name: "PowerShell: Attach to PowerShell Host Process", + type: "PowerShell", + request: "attach", + }, + [DebugConfig.RunPester]: { + name: "PowerShell: Run Pester Tests", + type: "PowerShell", + request: "launch", + script: "Invoke-Pester", + createTemporaryIntegratedConsole: true, + attachDotnetDebugger: true, + }, + [DebugConfig.ModuleInteractiveSession]: { + name: "PowerShell: Module Interactive Session", + type: "PowerShell", + request: "launch", + script: 'Enter command to import your binary module, for example: "Import-Module -Force ${workspaceFolder}/path/to/module.psd1|dll"', + }, + [DebugConfig.BinaryModule]: { + name: "PowerShell: Binary Module Interactive", + type: "PowerShell", + request: "launch", + script: 'Enter command to import your binary module, for example: "Import-Module -Force ${workspaceFolder}/path/to/module.psd1|dll"', + createTemporaryIntegratedConsole: true, + attachDotnetDebugger: true, + }, + [DebugConfig.BinaryModulePester]: { + name: "PowerShell: Binary Module Pester Tests", + type: "PowerShell", + request: "launch", + script: "Invoke-Pester", + createTemporaryIntegratedConsole: true, + attachDotnetDebugger: true, + }, + [DebugConfig.WindowsPowerShell]: { + name: "PowerShell: Windows PowerShell", + type: "PowerShell", + request: "launch", + sessionName: "Windows PowerShell (x64)", + }, +}; + +export class DebugSessionFeature + extends LanguageClientConsumer + implements DebugConfigurationProvider, DebugAdapterDescriptorFactory +{ + private tempDebugProcess: PowerShellProcess | undefined; + private tempSessionDetails: IEditorServicesSessionDetails | undefined; + private commands: Disposable[] = []; + private handlers: Disposable[] = []; + private adapterName = "PowerShell"; + + constructor( + context: ExtensionContext, + private sessionManager: SessionManager, + private logger: ILogger, + ) { + super(); + + this.activateDebugAdaptor(context); + + // NOTE: While process and runspace IDs are numbers, command + // substitutions in VS Code debug configurations are required to return + // strings. Hence to the `toString()` on these. + this.commands = [ + commands.registerCommand( + "PowerShell.PickPSHostProcess", + async () => { + const processId = await this.pickPSHostProcess(); + return processId?.toString(); + }, + ), + + commands.registerCommand( + "PowerShell.PickRunspace", + async (processId) => { + const runspace = await this.pickRunspace(processId); + return runspace?.toString(); + }, + this, + ), + ]; + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + + for (const handler of this.handlers) { + handler.dispose(); + } + } + + // This "activates" the debug adapter. You can only do this once. + public activateDebugAdaptor(context: ExtensionContext): void { + const triggers = [ + DebugConfigurationProviderTriggerKind.Initial, + DebugConfigurationProviderTriggerKind.Dynamic, + ]; + + for (const triggerKind of triggers) { + context.subscriptions.push( + debug.registerDebugConfigurationProvider( + this.adapterName, + this, + triggerKind, + ), + ); + } + + context.subscriptions.push( + debug.registerDebugAdapterTrackerFactory( + this.adapterName, + new PowerShellDebugAdapterTrackerFactory(this.adapterName), + ), + debug.registerDebugAdapterDescriptorFactory(this.adapterName, this), + ); + } + + public override onLanguageClientSet(languageClient: LanguageClient): void { + this.handlers = [ + languageClient.onNotification( + StartDebuggerNotificationType, + () => + void debug.startDebugging( + undefined, + DebugConfigurations[DebugConfig.InteractiveSession], + ), + ), + + languageClient.onNotification( + StopDebuggerNotificationType, + () => void debug.stopDebugging(undefined), + ), + ]; + } + + public async provideDebugConfigurations( + _folder: WorkspaceFolder | undefined, + _token?: CancellationToken, + ): Promise { + const debugConfigPickItems = [ + { + id: DebugConfig.LaunchCurrentFile, + label: "Launch Current File", + description: + "Launch and debug the file in the currently active editor window", + }, + { + id: DebugConfig.LaunchScript, + label: "Launch Script", + description: "Launch and debug the specified file or command", + }, + { + id: DebugConfig.InteractiveSession, + label: "Interactive Session", + description: + "Debug commands executed from the PowerShell Extension Terminal", + }, + { + id: DebugConfig.AttachHostProcess, + label: "Attach", + description: + "Attach the debugger to a running PowerShell Host Process", + }, + { + id: DebugConfig.RunPester, + label: "Run Pester Tests", + description: + "Debug Pester Tests detected in your current directory (runs Invoke-Pester)", + }, + { + id: DebugConfig.ModuleInteractiveSession, + label: "Interactive Session (Module)", + description: + "Debug commands executed from the PowerShell Extension Terminal after auto-loading your module", + }, + { + id: DebugConfig.BinaryModule, + label: "Interactive Session (Binary Module)", + description: + "Debug a .NET binary or hybrid module loaded into a PowerShell session. Breakpoints you set in your .NET (C#/F#/VB/etc.) code will be hit upon command execution. You may want to add a compile or watch action as a pre-launch task to this configuration.", + }, + { + id: DebugConfig.BinaryModulePester, + label: "Run Pester Tests (Binary Module)", + description: + "Debug a .NET binary or hybrid module by running Pester tests. Breakpoints you set in your .NET (C#/F#/VB/etc.) code will be hit upon command execution. You may want to add a compile or watch action as a pre-launch task to this configuration.", + }, + ]; + + // Only show the Windows PowerShell option if the platform is Windows + const platformDetails = getPlatformDetails(); + if (platformDetails.operatingSystem === OperatingSystem.Windows) { + debugConfigPickItems.push({ + id: DebugConfig.WindowsPowerShell, + label: "Windows PowerShell", + description: + "Launch Windows PowerShell in a temporary integrated console for debugging", + }); + } + + const launchSelection = await window.showQuickPick( + debugConfigPickItems, + { placeHolder: "Select a PowerShell debug configuration" }, + ); + + if (launchSelection) { + return [DebugConfigurations[launchSelection.id]]; + } + + return [DebugConfigurations[DebugConfig.LaunchCurrentFile]]; + } + + // We don't use await here but we are returning a promise and the return syntax is easier in an async function + // eslint-disable-next-line @typescript-eslint/require-await + public async resolveDebugConfiguration( + _folder: WorkspaceFolder | undefined, + config: DebugConfiguration, + _token?: CancellationToken, + ): Promise { + // NOTE: We intentionally do not touch the `cwd` setting of the config. + + if (!config.request) { + // No launch.json, create the default configuration for both unsaved + // (Untitled) and saved documents. + const LaunchCurrentFileConfig = + DebugConfigurations[DebugConfig.LaunchCurrentFile]; + config = { ...config, ...LaunchCurrentFileConfig }; + config.current_document = true; + } + + if ( + config.script === "${file}" || + config.script === "${relativeFile}" + ) { + if (window.activeTextEditor === undefined) { + void this.logger.writeAndShowError( + "To debug the 'Current File', you must first open a PowerShell script file in the editor.", + ); + return PREVENT_DEBUG_START; + } + config.current_document = true; + // Special case using the URI for untitled documents. + const currentDocument = window.activeTextEditor.document; + if (currentDocument.isUntitled) { + config.untitled_document = true; + config.script = currentDocument.uri.toString(); + } + } + + return config; + } + + public async resolveDebugConfigurationWithSubstitutedVariables( + _folder: WorkspaceFolder | undefined, + config: DebugConfiguration, + _token?: CancellationToken, + ): Promise { + let resolvedConfig: ResolveDebugConfigurationResult; + + // Prevent the Debug Console from opening + config.internalConsoleOptions = "neverOpen"; + + const settings = getSettings(); + config.createTemporaryIntegratedConsole ??= + settings.debugging.createTemporaryIntegratedConsole; + config.executeMode ??= settings.debugging.executeMode; + if (config.request === "attach") { + resolvedConfig = await this.resolveAttachDebugConfiguration(config); + } else if (config.request === "launch") { + resolvedConfig = await this.resolveLaunchDebugConfiguration(config); + } else { + void this.logger.writeAndShowError( + `PowerShell debug configuration's request type was invalid: '${config.request}'.`, + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + + return resolvedConfig; + } + + // This is our factory entrypoint hook to when a debug session starts, and + // where we will lazy initialize everything needed to do the debugging such + // as a temporary console if required. + // + // NOTE: A Promise meets the shape of a ProviderResult, which allows us to + // make this method async. + public async createDebugAdapterDescriptor( + session: DebugSession, + _executable: DebugAdapterExecutable | undefined, + ): Promise { + await this.sessionManager.start(); + + const sessionDetails = session.configuration + .createTemporaryIntegratedConsole + ? await this.createTemporaryIntegratedConsole(session) + : this.sessionManager.getSessionDetails(); + + if (sessionDetails === undefined) { + return undefined; + } + + // Create or show the debug terminal (either temporary or session). + this.sessionManager.showDebugTerminal(true); + + this.logger.writeDebug( + `Connecting to pipe: ${sessionDetails.debugServicePipeName}`, + ); + this.logger.writeDebug( + `Debug configuration: ${JSON.stringify(session.configuration, undefined, 2)}`, + ); + + return new DebugAdapterNamedPipeServer( + sessionDetails.debugServicePipeName, + ); + } + + private async resolveLaunchDebugConfiguration( + config: DebugConfiguration, + ): Promise { + // Check the languageId and file extension only for current documents + // (which includes untitled documents). This prevents accidentally + // running the debugger for an open non-PowerShell file. + if (config.current_document) { + const currentDocument = window.activeTextEditor?.document; + if (currentDocument?.languageId !== "powershell") { + void this.logger.writeAndShowError( + `PowerShell does not support debugging this language mode: '${currentDocument?.languageId}'.`, + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + + if (await checkIfFileExists(config.script)) { + const ext = path.extname(config.script).toLowerCase(); + if (!(ext === ".ps1" || ext === ".psm1")) { + void this.logger.writeAndShowError( + `PowerShell does not support debugging this file type: '${path.basename(config.script)}'.`, + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + } + } + + if ( + config.untitled_document && + config.createTemporaryIntegratedConsole + ) { + void this.logger.writeAndShowError( + "PowerShell does not support debugging untitled files in a temporary console.", + ); + return PREVENT_DEBUG_START; + } + + if ( + !config.createTemporaryIntegratedConsole && + config.attachDotnetDebugger + ) { + void this.logger.writeAndShowError( + "dotnet debugging without using a temporary console is currently not supported. Please updated your launch config to include createTemporaryIntegratedConsole: true.", + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + + if (config.sessionName) { + config.createTemporaryIntegratedConsole = true; + } + + if (config.attachDotnetDebugger) { + return this.resolveAttachDotnetDebugConfiguration(config); + } + + config.temporaryConsoleWindowActionOnDebugEnd ??= "keep"; + + return config; + } + + private resolveAttachDotnetDebugConfiguration( + config: DebugConfiguration, + ): ResolveDebugConfigurationResult { + if (!extensions.getExtension("ms-dotnettools.csharp")) { + void this.logger.writeAndShowError( + "You specified attachDotnetDebugger in your PowerShell Launch configuration but the C# extension is not installed. Please install the C# extension and try again.", + ); + return PREVENT_DEBUG_START; + } + + const dotnetDebuggerConfig = this.getDotnetNamedConfigOrDefault( + config.dotnetDebuggerConfigName, + ); + + if (dotnetDebuggerConfig === undefined) { + void this.logger.writeAndShowError( + `You specified dotnetDebuggerConfigName in your PowerShell Launch configuration but a matching launch config was not found. Please ensure you have a coreclr attach config with the name ${config.dotnetDebuggerConfigName} in your launch.json file or remove dotnetDebuggerConfigName from your PowerShell Launch configuration to use the defaults`, + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + + config.dotnetAttachConfig = dotnetDebuggerConfig; + return config; + } + + private async createTemporaryIntegratedConsole( + session: DebugSession, + ): Promise { + const settings = getSettings(); + const previousActiveTerminal = window.activeTerminal; + + this.tempDebugProcess = + await this.sessionManager.createDebugSessionProcess( + settings, + session.configuration.sessionName, + ); + // TODO: Maybe set a timeout on the cancellation token? + const cancellationTokenSource = new CancellationTokenSource(); + this.tempSessionDetails = await this.tempDebugProcess.start( + cancellationTokenSource.token, + ); + + // NOTE: Dotnet attach debugging is only currently supported if a temporary debug terminal is used, otherwise we get lots of lock conflicts from loading the assemblies. + if (session.configuration.attachDotnetDebugger) { + const dotnetAttachConfig = session.configuration.dotnetAttachConfig; + + // Will wait until the process is started and available before attaching + const pid = await this.tempDebugProcess.getPid(); + if (pid === undefined) { + void this.logger.writeAndShowError( + "Attach Dotnet Debugger was specified but the PowerShell temporary debug session failed to start. This is probably a bug.", + ); + return PREVENT_DEBUG_START; + } + dotnetAttachConfig.processId = pid; + + // Ensure the .NET session stops before the PowerShell session so that the .NET debug session doesn't emit an error about the process unexpectedly terminating. + let tempConsoleDotnetAttachSession: DebugSession; + const startDebugEvent = debug.onDidStartDebugSession( + (dotnetAttachSession) => { + if ( + dotnetAttachSession.configuration.name != + dotnetAttachConfig.name + ) { + return; + } + + // Makes the event one-time + // HACK: This seems like you would be calling a method on a variable not assigned yet, but it does work in the flow. + // The dispose shorthand demonry for making an event one-time courtesy of: https://github.com/OmniSharp/omnisharp-vscode/blob/b8b07bb12557b4400198895f82a94895cb90c461/test/integrationTests/launchConfiguration.integration.test.ts#L41-L45 + startDebugEvent.dispose(); + + this.logger.writeDebug( + `Debugger session detected: ${dotnetAttachSession.name} (${dotnetAttachSession.id})`, + ); + + tempConsoleDotnetAttachSession = dotnetAttachSession; + + const stopDebugEvent = debug.onDidTerminateDebugSession( + async (tempConsoleSession) => { + if ( + tempConsoleDotnetAttachSession.parentSession + ?.id !== tempConsoleSession.id + ) { + return; + } + + // Makes the event one-time + stopDebugEvent.dispose(); + + this.logger.writeDebug( + `Debugger session terminated: ${tempConsoleSession.name} (${tempConsoleSession.id})`, + ); + + // HACK: As of 2023-08-17, there is no vscode debug API to request the C# debugger to detach, so we send it a custom DAP request instead. + const disconnectRequest: DebugProtocol.DisconnectRequest = + { + command: "disconnect", + seq: 0, + type: "request", + arguments: { + restart: false, + terminateDebuggee: false, + suspendDebuggee: false, + }, + }; + + try { + await dotnetAttachSession.customRequest( + disconnectRequest.command, + disconnectRequest.arguments, + ); + } catch (err) { + this.logger.writeWarning( + `Disconnect request to dotnet debugger failed: ${err}`, + ); + } + }, + ); + }, + ); + + // Start a child debug session to attach the dotnet debugger + // TODO: Accommodate multi-folder workspaces if the C# code is in a different workspace folder + await debug.startDebugging(undefined, dotnetAttachConfig, session); + this.logger.writeDebug( + `Dotnet attach debug configuration: ${JSON.stringify(dotnetAttachConfig, undefined, 2)}`, + ); + this.logger.writeDebug( + `Attached dotnet debugger to process: ${pid}`, + ); + } + + if ( + session.configuration.temporaryConsoleWindowActionOnDebugEnd !== + "keep" + ) { + const closeDebugEvent = debug.onDidTerminateDebugSession( + (terminatedSession) => { + closeDebugEvent.dispose(); + + if (terminatedSession.id !== session.id) { + return; + } + + if ( + terminatedSession.configuration + .temporaryConsoleWindowActionOnDebugEnd === "close" + ) { + this.tempDebugProcess?.dispose(); + } else if ( + terminatedSession.configuration + .temporaryConsoleWindowActionOnDebugEnd === + "hide" && + previousActiveTerminal && + window.terminals.includes(previousActiveTerminal) + ) { + previousActiveTerminal.show(); + } + }, + ); + } + + return this.tempSessionDetails; + } + + private getDotnetNamedConfigOrDefault( + configName?: string, + ): ResolveDebugConfigurationResult { + if (configName) { + const debugConfigs = this.getLaunchConfigurations(); + return debugConfigs.find( + ({ type, request, name }) => + type === "coreclr" && + request === "attach" && + name === configName, + ); + } + + // Default debugger config if none provided + // TODO: Type this appropriately from the C# extension? + return { + name: "Dotnet Debugger: Temporary Extension Terminal", + type: "coreclr", + request: "attach", + processId: undefined, + logging: { + moduleLoad: false, + }, + }; + } + + /** Fetches all available vscode launch configurations. This is abstracted out for easier testing. */ + private getLaunchConfigurations(): DebugConfiguration[] { + return ( + workspace + .getConfiguration("launch") + .get("configurations") ?? [] + ); + } + + private async resolveAttachDebugConfiguration( + config: DebugConfiguration, + ): Promise { + const platformDetails = getPlatformDetails(); + const versionDetails = + this.sessionManager.getPowerShellVersionDetails(); + if (versionDetails === undefined) { + void this.logger.writeAndShowError( + `PowerShell session version details were not found for '${config.name}'.`, + ); + return PREVENT_DEBUG_START; + } + + // Cross-platform attach to process was added in 6.2.0-preview.4. + if ( + versionDetails.version < "7.0.0" && + platformDetails.operatingSystem !== OperatingSystem.Windows + ) { + void this.logger.writeAndShowError( + `Attaching to a PowerShell Host Process on ${OperatingSystem[platformDetails.operatingSystem]} requires PowerShell 7.0 or higher (Current Version: ${versionDetails.version}).`, + ); + return PREVENT_DEBUG_START; + } + + // If nothing is set, prompt for the processId. + if (!config.customPipeName && !config.processId) { + config.processId = await this.pickPSHostProcess(); + // No process selected. Cancel attach. + if (!config.processId) { + return PREVENT_DEBUG_START; + } + } + + // If we were given a stringified int from the user, or from the picker + // command, we need to parse it here. + if ( + typeof config.processId === "string" && + config.processId != "current" + ) { + config.processId = parseInt(config.processId); + } + + // NOTE: We don't support attaching to the Extension Terminal, even + // though in the past it looked like we did. The implementation was + // half-baked and left things unusable. + if ( + config.processId === "current" || + config.processId === + (await this.sessionManager.getLanguageServerPid()) + ) { + // TODO: When (if ever) it's supported, we need to convert 0 and the + // old notion of "current" to the actual process ID, like this: + // config.processId = await this.sessionManager.getLanguageServerPid(); + void this.logger.writeAndShowError( + "Attaching to the PowerShell Extension terminal is not supported. Please use the 'PowerShell: Interactive Session' debug configuration instead.", + ); + return PREVENT_DEBUG_START_AND_OPEN_DEBUGCONFIG; + } + + if (!config.runspaceId && !config.runspaceName) { + config.runspaceId = await this.pickRunspace(config.processId); + // No runspace selected. Cancel attach. + if (!config.runspaceId) { + return PREVENT_DEBUG_START; + } + } + + config.temporaryConsoleWindowActionOnDebugEnd ??= "keep"; + + return config; + } + + private async pickPSHostProcess(): Promise { + const client = await LanguageClientConsumer.getLanguageClient(); + const response = await client.sendRequest( + GetPSHostProcessesRequestType, + {}, + ); + const items: IProcessItem[] = []; + for (const process of response) { + let windowTitle = ""; + if (process.mainWindowTitle) { + windowTitle = `, ${process.mainWindowTitle}`; + } + + items.push({ + label: process.processName, + description: `PID: ${process.processId.toString()}${windowTitle}`, + processId: process.processId, + }); + } + + if (items.length === 0) { + return Promise.reject( + new Error("There are no PowerShell host processes to attach."), + ); + } + + const options: QuickPickOptions = { + placeHolder: "Select a PowerShell host process to attach.", + matchOnDescription: true, + matchOnDetail: true, + }; + + const item = await window.showQuickPick(items, options); + + return item?.processId ?? undefined; + } + + private async pickRunspace(processId: number): Promise { + const client = await LanguageClientConsumer.getLanguageClient(); + const response = await client.sendRequest(GetRunspaceRequestType, { + processId, + }); + const items: IRunspaceItem[] = []; + for (const runspace of response) { + items.push({ + label: runspace.name, + description: `ID: ${runspace.id} - ${runspace.availability}`, + id: runspace.id, + }); + } + + const options: QuickPickOptions = { + placeHolder: "Select PowerShell runspace to debug", + matchOnDescription: true, + matchOnDetail: true, + }; + + const item = await window.showQuickPick(items, options); + + return item?.id ?? undefined; + } +} + +class PowerShellDebugAdapterTrackerFactory + implements DebugAdapterTrackerFactory, Disposable +{ + disposables: Disposable[] = []; + constructor(private adapterName = "PowerShell") {} + + _log: LogOutputChannel | undefined; + /** Lazily creates a {@link LogOutputChannel} for debug tracing, and presents it only when DAP logging is enabled. + * + * We want to use a shared output log for separate debug sessions as usually only one is running at a time and we + * dont need an output window for every debug session. We also want to leave it active so user can copy and paste + * even on run end. When user changes the setting and disables it getter will return undefined, which will result + * in a noop for the logging activities, effectively pausing logging but not disposing the output channel. If the + * user re-enables, then logging resumes. + */ + get log(): LogOutputChannel | undefined { + if ( + workspace + .getConfiguration("powershell.developer") + .get("traceDap") && + this._log === undefined + ) { + this._log = window.createOutputChannel( + `${this.adapterName}: Trace DAP`, + { log: true }, + ); + this.disposables.push(this._log); + } + return this._log; + } + + // This tracker effectively implements the logging for the debug adapter to a LogOutputChannel + createDebugAdapterTracker(session: DebugSession): DebugAdapterTracker { + const sessionInfo = `${this.adapterName} Debug Session: ${session.name} [${session.id}]`; + return { + onWillStartSession: () => + this.log?.info( + `Starting ${sessionInfo}. Set log level to trace to see DAP messages beyond errors`, + ), + onWillStopSession: () => this.log?.info(`Stopping ${sessionInfo}`), + onExit: (code) => + this.log?.info(`${sessionInfo} exited with code ${code}`), + onWillReceiveMessage: (m): void => { + this.log?.debug(`➡️${m.seq} ${m.type}: ${m.command}`); + if ( + m.arguments && + (Array.isArray(m.arguments) + ? m.arguments.length > 0 + : Object.keys(m.arguments).length > 0) + ) { + this.log?.trace( + `${m.seq}: ` + + JSON.stringify(m.arguments, undefined, 2), + ); + } + }, + onDidSendMessage: (m): void => { + const responseSummary = + m.request_seq !== undefined + ? `${m.success ? "✅" : "❌"}${m.request_seq} ${m.type}(${m.seq}): ${m.command}` + : `⬅️${m.seq} ${m.type}: ${m.event ?? m.command}`; + this.log?.debug(responseSummary); + if ( + m.body && + (Array.isArray(m.body) + ? m.body.length > 0 + : Object.keys(m.body).length > 0) + ) { + this.log?.trace( + `${m.seq}: ` + JSON.stringify(m.body, undefined, 2), + ); + } + }, + onError: (e) => this.log?.error(e), + }; + } + + dispose(): void { + this.disposables.forEach((d) => d.dispose()); + } +} + +export class SpecifyScriptArgsFeature implements Disposable { + private command: Disposable; + private context: ExtensionContext; + + constructor(context: ExtensionContext) { + this.context = context; + + this.command = commands.registerCommand( + "PowerShell.SpecifyScriptArgs", + () => { + return this.specifyScriptArguments(); + }, + ); + } + + public dispose(): void { + this.command.dispose(); + } + + private async specifyScriptArguments(): Promise { + const powerShellDbgScriptArgsKey = "powerShellDebugScriptArgs"; + + const options: InputBoxOptions = { + ignoreFocusOut: true, + placeHolder: + "Enter script arguments or leave empty to pass no args", + }; + + const prevArgs = this.context.workspaceState.get( + powerShellDbgScriptArgsKey, + "", + ); + if (prevArgs.length > 0) { + options.value = prevArgs; + } + + const text = await window.showInputBox(options); + // When user cancel's the input box (by pressing Esc), the text value is undefined. + // Let's not blow away the previous setting. + if (text !== undefined) { + await this.context.workspaceState.update( + powerShellDbgScriptArgsKey, + text, + ); + } + + return text; + } +} + +interface IProcessItem extends QuickPickItem { + processId: number; // payload for the QuickPick UI +} + +interface IGetPSHostProcessesArguments {} + +interface IPSHostProcessInfo { + processName: string; + processId: number; + appDomainName: string; + mainWindowTitle: string; +} + +export const GetPSHostProcessesRequestType = new RequestType< + IGetPSHostProcessesArguments, + IPSHostProcessInfo[], + string +>("powerShell/getPSHostProcesses"); + +interface IRunspaceItem extends QuickPickItem { + id: number; // payload for the QuickPick UI +} + +interface IGetRunspaceRequestArguments {} + +interface IRunspace { + id: number; + name: string; + availability: string; +} + +export const GetRunspaceRequestType = new RequestType< + IGetRunspaceRequestArguments, + IRunspace[], + string +>("powerShell/getRunspace"); diff --git a/src/features/Examples.ts b/src/features/Examples.ts new file mode 100644 index 0000000000..d3c0b0da56 --- /dev/null +++ b/src/features/Examples.ts @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import path = require("path"); +import utils = require("../utils"); +import vscode = require("vscode"); + +export class ExamplesFeature implements vscode.Disposable { + private command: vscode.Disposable; + private examplesPath: vscode.Uri; + + constructor() { + this.examplesPath = vscode.Uri.file( + path.resolve(__dirname, "../examples"), + ); + this.command = vscode.commands.registerCommand( + "PowerShell.OpenExamplesFolder", + async () => { + await vscode.commands.executeCommand( + "vscode.openFolder", + this.examplesPath, + true, + ); + // Return existence of the path for testing. The `vscode.openFolder` + // command should do this, but doesn't (yet). + return utils.checkIfFileExists(this.examplesPath); + }, + ); + } + + public dispose(): void { + this.command.dispose(); + } +} diff --git a/src/features/ExpandAlias.ts b/src/features/ExpandAlias.ts new file mode 100644 index 0000000000..45e86be7e1 --- /dev/null +++ b/src/features/ExpandAlias.ts @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import { RequestType } from "vscode-languageclient"; +import type { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; + +interface IExpandAliasRequestArguments {} + +interface IExpandAliasRequestResponse { + text: string; +} + +export const ExpandAliasRequestType = new RequestType< + IExpandAliasRequestArguments, + IExpandAliasRequestResponse, + void +>("powerShell/expandAlias"); + +export class ExpandAliasFeature extends LanguageClientConsumer { + private command: vscode.Disposable; + + constructor() { + super(); + this.command = vscode.commands.registerCommand( + "PowerShell.ExpandAlias", + async () => { + const editor = vscode.window.activeTextEditor; + if (editor === undefined) { + return; + } + + const document = editor.document; + const selection = editor.selection; + const sls = selection.start; + const sle = selection.end; + + let text: string; + let range: vscode.Range | vscode.Position; + + if (sls.character === sle.character && sls.line === sle.line) { + text = document.getText(); + range = new vscode.Range( + 0, + 0, + document.lineCount, + text.length, + ); + } else { + text = document.getText(selection); + range = new vscode.Range( + sls.line, + sls.character, + sle.line, + sle.character, + ); + } + + const client = await LanguageClientConsumer.getLanguageClient(); + const result = await client.sendRequest( + ExpandAliasRequestType, + { text }, + ); + await editor.edit((editBuilder) => { + editBuilder.replace(range, result.text); + }); + }, + ); + } + + public override onLanguageClientSet( + _languageClient: LanguageClient, + // eslint-disable-next-line @typescript-eslint/no-empty-function + ): void {} + + public dispose(): void { + this.command.dispose(); + } +} diff --git a/src/features/ExtensionCommands.ts b/src/features/ExtensionCommands.ts new file mode 100644 index 0000000000..c4ca7203b0 --- /dev/null +++ b/src/features/ExtensionCommands.ts @@ -0,0 +1,644 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as path from "path"; +import * as vscode from "vscode"; +import { + NotificationType, + NotificationType0, + Position, + Range, + RequestType, +} from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; +import type { ILogger } from "../logging"; +import { getSettings, validateCwdSetting } from "../settings"; +import { DebugConfig, DebugConfigurations } from "./DebugSession"; + +export interface IExtensionCommand { + name: string; + displayName: string; +} + +export interface IExtensionCommandQuickPickItem extends vscode.QuickPickItem { + command: IExtensionCommand; +} + +export const InvokeExtensionCommandRequestType = new RequestType< + IInvokeExtensionCommandRequestArguments, + void, + void +>("powerShell/invokeExtensionCommand"); + +export interface IEditorContext { + currentFileContent: string; + currentFileLanguage: string; + currentFilePath: string; + cursorPosition: Position | undefined | null; + selectionRange: Range | undefined | null; +} + +export interface IInvokeExtensionCommandRequestArguments { + name: string; + context: IEditorContext; +} + +export const ExtensionCommandAddedNotificationType = + new NotificationType( + "powerShell/extensionCommandAdded", + ); + +export interface IExtensionCommandAddedNotificationBody { + name: string; + displayName: string; +} + +function asRange(value: vscode.Range): Range { + return { start: asPosition(value.start), end: asPosition(value.end) }; +} + +function asPosition(value: vscode.Position): Position { + return { line: value.line, character: value.character }; +} + +function asCodePosition(value: Position): vscode.Position { + return new vscode.Position(value.line, value.character); +} + +export const GetEditorContextRequestType = new RequestType< + IGetEditorContextRequestArguments, + IEditorContext, + void +>("editor/getEditorContext"); + +export interface IGetEditorContextRequestArguments {} + +// NOTE: The server at least now expects this response, but it's not used in any +// way. In the future we could actually communicate an error to the user. +enum EditorOperationResponse { + Completed, + Failed, +} + +export const InsertTextRequestType = new RequestType< + IInsertTextRequestArguments, + EditorOperationResponse, + void +>("editor/insertText"); + +export interface IInsertTextRequestArguments { + filePath: string; + insertText: string; + insertRange: Range; +} + +export const SetSelectionRequestType = new RequestType< + ISetSelectionRequestArguments, + EditorOperationResponse, + void +>("editor/setSelection"); + +export interface ISetSelectionRequestArguments { + selectionRange: Range; +} + +export const OpenFileRequestType = new RequestType< + IOpenFileDetails, + EditorOperationResponse, + void +>("editor/openFile"); + +export interface IOpenFileDetails { + filePath: string; + preview: boolean; +} + +export const NewFileRequestType = new RequestType< + string, + EditorOperationResponse, + void +>("editor/newFile"); + +export const CloseFileRequestType = new RequestType< + string, + EditorOperationResponse, + void +>("editor/closeFile"); + +export const SaveFileRequestType = new RequestType< + ISaveFileDetails, + EditorOperationResponse, + void +>("editor/saveFile"); + +export const ShowErrorMessageRequestType = new RequestType< + string, + EditorOperationResponse, + void +>("editor/showErrorMessage"); + +export const ShowWarningMessageRequestType = new RequestType< + string, + EditorOperationResponse, + void +>("editor/showWarningMessage"); + +export const ShowInformationMessageRequestType = new RequestType< + string, + EditorOperationResponse, + void +>("editor/showInformationMessage"); + +export const SetStatusBarMessageRequestType = new RequestType< + IStatusBarMessageDetails, + EditorOperationResponse, + void +>("editor/setStatusBarMessage"); + +export const ClearTerminalNotificationType = new NotificationType0( + "editor/clearTerminal", +); + +export interface ISaveFileDetails { + filePath: string; + newPath?: string; +} + +export interface IStatusBarMessageDetails { + message: string; + timeout?: number; +} + +interface IInvokeRegisteredEditorCommandParameter { + commandName: string; +} + +export class ExtensionCommandsFeature extends LanguageClientConsumer { + private commands: vscode.Disposable[]; + private handlers: vscode.Disposable[] = []; + private statusBarMessages: vscode.Disposable[] = []; + private extensionCommands: IExtensionCommand[] = []; + + constructor(private logger: ILogger) { + super(); + this.commands = [ + vscode.commands.registerCommand( + "PowerShell.ShowAdditionalCommands", + async () => { + await this.showExtensionCommands(); + }, + ), + + vscode.commands.registerCommand( + "PowerShell.InvokeRegisteredEditorCommand", + async (param: IInvokeRegisteredEditorCommandParameter) => { + const commandToExecute = this.extensionCommands.find( + (x) => x.name === param.commandName, + ); + + if (commandToExecute) { + const client = + await LanguageClientConsumer.getLanguageClient(); + await client.sendRequest( + InvokeExtensionCommandRequestType, + { + name: commandToExecute.name, + context: this.getEditorContext(), + }, + ); + } + }, + ), + + vscode.commands.registerCommand( + "PowerShell.ClosePanel", + async () => { + await vscode.commands.executeCommand( + "workbench.action.togglePanel", + ); + }, + ), + + vscode.commands.registerCommand( + "PowerShell.PositionPanelLeft", + async () => { + await vscode.commands.executeCommand( + "workbench.action.positionPanelLeft", + ); + }, + ), + + vscode.commands.registerCommand( + "PowerShell.PositionPanelBottom", + async () => { + await vscode.commands.executeCommand( + "workbench.action.positionPanelBottom", + ); + }, + ), + + vscode.commands.registerCommand( + "PowerShell.Debug.Start", + async () => { + await vscode.debug.startDebugging( + undefined, + DebugConfigurations[DebugConfig.LaunchCurrentFile], + ); + }, + ), + ]; + } + + public override onLanguageClientSet(languageClient: LanguageClient): void { + // Clear the current list of extension commands since they were + // only relevant to the previous session + this.extensionCommands = []; + this.handlers = [ + languageClient.onNotification( + ExtensionCommandAddedNotificationType, + (command) => { + this.addExtensionCommand(command); + }, + ), + + languageClient.onRequest(GetEditorContextRequestType, (_details) => + this.getEditorContext(), + ), + + languageClient.onRequest(InsertTextRequestType, (details) => + this.insertText(details), + ), + + languageClient.onRequest(SetSelectionRequestType, (details) => + this.setSelection(details), + ), + + languageClient.onRequest(NewFileRequestType, (_content) => + this.newFile(_content), + ), + + languageClient.onRequest(OpenFileRequestType, (filePath) => + this.openFile(filePath), + ), + + languageClient.onRequest(CloseFileRequestType, (filePath) => + this.closeFile(filePath), + ), + + languageClient.onRequest(SaveFileRequestType, (saveFileDetails) => + this.saveFile(saveFileDetails), + ), + + languageClient.onRequest( + ShowInformationMessageRequestType, + (message) => this.showInformationMessage(message), + ), + + languageClient.onRequest(ShowErrorMessageRequestType, (message) => + this.showErrorMessage(message), + ), + + languageClient.onRequest(ShowWarningMessageRequestType, (message) => + this.showWarningMessage(message), + ), + + languageClient.onRequest( + SetStatusBarMessageRequestType, + (messageDetails) => this.setStatusBarMessage(messageDetails), + ), + + languageClient.onNotification(ClearTerminalNotificationType, () => { + // We check to see if they have TrueClear on. If not, no-op because the + // overriden Clear-Host already calls [System.Console]::Clear() + if ( + getSettings().integratedConsole.forceClearScrollbackBuffer + ) { + void vscode.commands.executeCommand( + "workbench.action.terminal.clear", + ); + } + }), + ]; + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + for (const handler of this.handlers) { + handler.dispose(); + } + for (const statusBarMessage of this.statusBarMessages) { + statusBarMessage.dispose(); + } + } + + private addExtensionCommand( + command: IExtensionCommandAddedNotificationBody, + ): void { + this.extensionCommands.push({ + name: command.name, + displayName: command.displayName, + }); + + this.extensionCommands.sort( + (a: IExtensionCommand, b: IExtensionCommand) => + a.name.localeCompare(b.name), + ); + } + + private async showExtensionCommands(): Promise { + // If no extension commands are available, show a message + if (this.extensionCommands.length === 0) { + void this.logger.writeAndShowInformation( + "No extension commands have been loaded into the current session.", + ); + return; + } + + const quickPickItems = + this.extensionCommands.map( + (command) => { + return { + label: command.displayName, + description: command.name, + command, + }; + }, + ); + + const selectedCommand = await vscode.window.showQuickPick( + quickPickItems, + { placeHolder: "Select a command..." }, + ); + + return this.onCommandSelected(selectedCommand); + } + + private async onCommandSelected( + chosenItem?: IExtensionCommandQuickPickItem, + ): Promise { + if (chosenItem !== undefined) { + const client = await LanguageClientConsumer.getLanguageClient(); + await client.sendRequest(InvokeExtensionCommandRequestType, { + name: chosenItem.command.name, + context: this.getEditorContext(), + }); + } + } + + private async insertText( + details: IInsertTextRequestArguments, + ): Promise { + const edit = new vscode.WorkspaceEdit(); + + edit.set(vscode.Uri.parse(details.filePath), [ + new vscode.TextEdit( + new vscode.Range( + details.insertRange.start.line, + details.insertRange.start.character, + details.insertRange.end.line, + details.insertRange.end.character, + ), + details.insertText, + ), + ]); + + await vscode.workspace.applyEdit(edit); + + return EditorOperationResponse.Completed; + } + + private getEditorContext(): IEditorContext | undefined { + if (vscode.window.activeTextEditor === undefined) { + return undefined; + } + + return { + currentFileContent: + vscode.window.activeTextEditor.document.getText(), + currentFileLanguage: + vscode.window.activeTextEditor.document.languageId, + currentFilePath: + vscode.window.activeTextEditor.document.uri.toString(), + cursorPosition: asPosition( + vscode.window.activeTextEditor.selection.active, + ), + selectionRange: asRange( + new vscode.Range( + vscode.window.activeTextEditor.selection.start, + vscode.window.activeTextEditor.selection.end, + ), + ), + }; + } + + private async newFile(content: string): Promise { + const doc = await vscode.workspace.openTextDocument({ + language: "powershell", + content: content, + }); + await vscode.window.showTextDocument(doc); + return EditorOperationResponse.Completed; + } + + private async openFile( + openFileDetails: IOpenFileDetails, + ): Promise { + const filePath = await this.resolveFilePathWithCwd( + openFileDetails.filePath, + ); + try { + const doc = await vscode.workspace.openTextDocument(filePath); + await vscode.window.showTextDocument(doc, { + preview: openFileDetails.preview, + }); + } catch { + void this.logger.writeAndShowWarning( + `File to open not found: ${filePath}`, + ); + return EditorOperationResponse.Failed; + } + return EditorOperationResponse.Completed; + } + + private async closeFile( + filePath: string, + ): Promise { + filePath = await this.resolveFilePathWithCwd(filePath); + const doc = vscode.workspace.textDocuments.find( + (x) => x.uri.fsPath === filePath, + ); + if (doc != undefined && !doc.isClosed) { + await vscode.window.showTextDocument(doc); + await vscode.commands.executeCommand( + "workbench.action.closeActiveEditor", + ); + return EditorOperationResponse.Completed; + } + void this.logger.writeAndShowWarning( + `File to close not found or already closed: ${filePath}`, + ); + return EditorOperationResponse.Failed; + } + + /** + * Save a file, possibly to a new path. If the save is not possible, return a completed response + * @param saveFileDetails the object detailing the path of the file to save and optionally its new path to save to + */ + private async saveFile( + saveFileDetails: ISaveFileDetails, + ): Promise { + // Try to interpret the filePath as a URI, defaulting to "file://" if we don't succeed + let currentFileUri: vscode.Uri; + if ( + saveFileDetails.filePath.startsWith("untitled") || + saveFileDetails.filePath.startsWith("file") + ) { + currentFileUri = vscode.Uri.parse(saveFileDetails.filePath); + } else { + const filePath = await this.resolveFilePathWithCwd( + saveFileDetails.filePath, + ); + currentFileUri = vscode.Uri.file(filePath); + } + + const doc = vscode.workspace.textDocuments.find( + (x) => x.uri.fsPath === currentFileUri.fsPath, + ); + if (doc === undefined) { + void this.logger.writeAndShowWarning( + `File to save not found: ${currentFileUri.fsPath}`, + ); + return EditorOperationResponse.Failed; + } + + let newFilePath = saveFileDetails.newPath ?? undefined; // Otherwise it's null. + if (currentFileUri.scheme === "file") { + // If no newFile is given, just save the current file + if (newFilePath === undefined) { + if (doc.isDirty) { + await doc.save(); + } + return EditorOperationResponse.Completed; + } + + // Special case where we interpret a path as relative to the current + // file, not the CWD! + if (!path.isAbsolute(newFilePath)) { + newFilePath = path.join( + path.dirname(currentFileUri.fsPath), + newFilePath, + ); + } + } else if (currentFileUri.scheme === "untitled") { + // We need a new name to save an untitled file + if (newFilePath === undefined) { + void this.logger.writeAndShowWarning( + 'Cannot save untitled file! Try SaveAs("path/to/file.ps1") instead.', + ); + return EditorOperationResponse.Failed; + } + + newFilePath = await this.resolveFilePathWithCwd(newFilePath); + } else { + // Other URI schemes are not supported + const msg = JSON.stringify(saveFileDetails, undefined, 2); + void this.logger.writeAndShowWarning( + `<${ExtensionCommandsFeature.name}>: Saving a document with scheme '${currentFileUri.scheme}' ` + + `is currently unsupported. Message: '${msg}'`, + ); + return EditorOperationResponse.Failed; + } + + return await this.saveFileAs(doc, newFilePath); + } + + /** + * Take a document available to vscode at the given URI and save it to the given absolute path + * @param documentUri the URI of the vscode document to save + * @param filePath the absolute path to save the document contents to + */ + private async saveFileAs( + doc: vscode.TextDocument, + filePath: string, + ): Promise { + // Write the old document's contents to the new document path + const newFileUri = vscode.Uri.file(filePath); + try { + await vscode.workspace.fs.writeFile( + newFileUri, + Buffer.from(doc.getText()), + ); + } catch (err) { + void this.logger.writeAndShowWarning( + `<${ExtensionCommandsFeature.name}>: ` + + `Unable to save file to path '${filePath}': ${err}`, + ); + return EditorOperationResponse.Failed; + } + + // Finally open the new document + const newFile = await vscode.workspace.openTextDocument(newFileUri); + await vscode.window.showTextDocument(newFile, { preview: true }); + return EditorOperationResponse.Completed; + } + + // Resolve file path against user's CWD setting + private async resolveFilePathWithCwd(filePath: string): Promise { + if (!path.isAbsolute(filePath)) { + const cwd = await validateCwdSetting(this.logger); + return path.resolve(cwd, filePath); + } + return filePath; + } + + private setSelection( + details: ISetSelectionRequestArguments, + ): EditorOperationResponse { + if (vscode.window.activeTextEditor !== undefined) { + vscode.window.activeTextEditor.selections = [ + new vscode.Selection( + asCodePosition(details.selectionRange.start), + asCodePosition(details.selectionRange.end), + ), + ]; + return EditorOperationResponse.Completed; + } + return EditorOperationResponse.Failed; + } + + private showInformationMessage(message: string): EditorOperationResponse { + void this.logger.writeAndShowInformation(message); + return EditorOperationResponse.Completed; + } + + private showErrorMessage(message: string): EditorOperationResponse { + void this.logger.writeAndShowError(message); + return EditorOperationResponse.Completed; + } + + private showWarningMessage(message: string): EditorOperationResponse { + void this.logger.writeAndShowWarning(message); + return EditorOperationResponse.Completed; + } + + private setStatusBarMessage( + messageDetails: IStatusBarMessageDetails, + ): EditorOperationResponse { + if (messageDetails.timeout) { + this.statusBarMessages.push( + vscode.window.setStatusBarMessage( + messageDetails.message, + messageDetails.timeout, + ), + ); + } else { + this.statusBarMessages.push( + vscode.window.setStatusBarMessage(messageDetails.message), + ); + } + return EditorOperationResponse.Completed; + } +} diff --git a/src/features/ExternalApi.ts b/src/features/ExternalApi.ts new file mode 100644 index 0000000000..cafd856c26 --- /dev/null +++ b/src/features/ExternalApi.ts @@ -0,0 +1,218 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { v4 as uuidv4 } from "uuid"; +import * as vscode from "vscode"; +import type { ILogger } from "../logging"; +import { SessionManager } from "../session"; + +export interface IExternalPowerShellDetails { + exePath: string; + version: string; + displayName: string; + architecture: string; +} + +export interface IPowerShellExtensionClient { + registerExternalExtension(id: string, apiVersion?: string): string; + unregisterExternalExtension(uuid: string): boolean; + getPowerShellVersionDetails( + uuid: string, + ): Promise; + waitUntilStarted(uuid: string): Promise; + getStorageUri(): vscode.Uri; + getLogUri(): vscode.Uri; +} + +/* +In order to use this in a Visual Studio Code extension, you can do the following: + +const powershellExtension = vscode.extensions.getExtension("ms-vscode.PowerShell-Preview"); +const powerShellExtensionClient = powershellExtension!.exports as IPowerShellExtensionClient; + +NOTE: At some point, we should release a helper npm package that wraps the API and does: +* Discovery of what extension they have installed: PowerShell or PowerShell Preview +* Manages session id for you + +*/ +export class ExternalApiFeature implements IPowerShellExtensionClient { + private static readonly registeredExternalExtension: Map< + string, + IExternalExtension + > = new Map(); + + constructor( + private extensionContext: vscode.ExtensionContext, + private sessionManager: SessionManager, + private logger: ILogger, + ) {} + + /* + DESCRIPTION: + Registers your extension to allow usage of the external API. The returns + a session UUID that will need to be passed in to subsequent API calls. + + USAGE: + powerShellExtensionClient.registerExternalExtension( + "ms-vscode.PesterTestExplorer" // the name of the extension using us + "v1"); // API Version. + + RETURNS: + string session uuid + */ + public registerExternalExtension(id: string, apiVersion = "v1"): string { + this.logger.writeDebug( + `Registering extension '${id}' for use with API version '${apiVersion}'.`, + ); + + for (const [ + _name, + externalExtension, + ] of ExternalApiFeature.registeredExternalExtension) { + if (externalExtension.id === id) { + const message = `The extension '${id}' is already registered.`; + this.logger.writeWarning(message); + throw new Error(message); + } + } + + if (!vscode.extensions.all.some((ext) => ext.id === id)) { + throw new Error( + `No extension installed with id '${id}'. You must use a valid extension id.`, + ); + } + + // Our ID is only only allowed to be used in our unit tests. + if ( + id === "ms-vscode.powershell" && + !(this.extensionContext.extensionMode === vscode.ExtensionMode.Test) + ) { + throw new Error( + "You can't use the PowerShell extension's id in this registration.", + ); + } + + const uuid = uuidv4(); + ExternalApiFeature.registeredExternalExtension.set(uuid, { + id, + apiVersion, + }); + return uuid; + } + + /* + DESCRIPTION: + Unregisters a session that an extension has. This returns + true if it succeeds or throws if it fails. + + USAGE: + powerShellExtensionClient.unregisterExternalExtension( + "uuid"); // the uuid from above for tracking purposes + + RETURNS: + true if it worked, otherwise throws an error. + */ + public unregisterExternalExtension(uuid = ""): boolean { + this.logger.writeDebug( + `Unregistering extension with session UUID: ${uuid}`, + ); + if (!ExternalApiFeature.registeredExternalExtension.delete(uuid)) { + throw new Error( + `No extension registered with session UUID: ${uuid}`, + ); + } + return true; + } + + private getRegisteredExtension(uuid = ""): IExternalExtension { + if (!ExternalApiFeature.registeredExternalExtension.has(uuid)) { + throw new Error( + "UUID provided was invalid, make sure you ran the 'powershellExtensionClient.registerExternalExtension(extensionId)' method and pass in the UUID that it returns to subsequent methods.", + ); + } + + // TODO: When we have more than one API version, make sure to include a check here. + return ExternalApiFeature.registeredExternalExtension.get(uuid)!; + } + + /* + DESCRIPTION: + This will fetch the version details of the PowerShell used to start + PowerShell Editor Services in the PowerShell extension. + + USAGE: + powerShellExtensionClient.getPowerShellVersionDetails( + "uuid"); // the uuid from above for tracking purposes + + RETURNS: + An IPowerShellVersionDetails which consists of: + { + version: string; + displayVersion: string; + edition: string; + architecture: string; + } + */ + public async getPowerShellVersionDetails( + uuid = "", + ): Promise { + const extension = this.getRegisteredExtension(uuid); + this.logger.writeDebug( + `Extension '${extension.id}' called 'getPowerShellVersionDetails'.`, + ); + + await this.sessionManager.waitUntilStarted(); + const versionDetails = + this.sessionManager.getPowerShellVersionDetails(); + + return { + exePath: + this.sessionManager.PowerShellExeDetails?.exePath ?? "unknown", + version: versionDetails?.version ?? "unknown", + displayName: + this.sessionManager.PowerShellExeDetails?.displayName ?? + "unknown", // comes from the Session Menu + architecture: versionDetails?.architecture ?? "unknown", + }; + } + /* + DESCRIPTION: + This will wait until the extension's PowerShell session is started. + + USAGE: + powerShellExtensionClient.waitUntilStarted( + "uuid"); // the uuid from above for tracking purposes + + RETURNS: + A void promise that resolves only once the extension is started. + + If the extension is not started by some mechanism + then this will wait indefinitely. + */ + public async waitUntilStarted(uuid = ""): Promise { + const extension = this.getRegisteredExtension(uuid); + this.logger.writeDebug( + `Extension '${extension.id}' called 'waitUntilStarted'.`, + ); + await this.sessionManager.waitUntilStarted(); + } + + public getStorageUri(): vscode.Uri { + // We have to override the scheme because it defaults to + // 'vscode-userdata' which breaks UNC paths. + return this.extensionContext.globalStorageUri.with({ scheme: "file" }); + } + + public getLogUri(): vscode.Uri { + return this.extensionContext.logUri.with({ scheme: "file" }); + } + + public dispose(): void { + // Nothing to dispose. + } +} + +interface IExternalExtension { + readonly id: string; + readonly apiVersion: string; +} diff --git a/src/features/GenerateBugReport.ts b/src/features/GenerateBugReport.ts new file mode 100644 index 0000000000..6539f978d9 --- /dev/null +++ b/src/features/GenerateBugReport.ts @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import child_process = require("child_process"); +import { SessionManager } from "../session"; + +const issuesUrl = "https://github.com/PowerShell/vscode-powershell/issues/new?"; + +export class GenerateBugReportFeature implements vscode.Disposable { + private command: vscode.Disposable; + + constructor(private sessionManager: SessionManager) { + this.command = vscode.commands.registerCommand( + "PowerShell.GenerateBugReport", + async () => { + const params = [ + "labels=Issue-Bug", + "template=bug-report.yml", + "powershell-version=" + this.getRuntimeInfo(), + "vscode-version=" + vscode.version + "\n" + process.arch, + "extension-version=" + + sessionManager.Publisher + + "." + + sessionManager.HostName + + "@" + + sessionManager.HostVersion, + ]; + const url = vscode.Uri.parse( + issuesUrl + encodeURIComponent(params.join("&")), + ); + await vscode.env.openExternal(url); + }, + ); + } + + public dispose(): void { + this.command.dispose(); + } + + private getRuntimeInfo(): string { + if (this.sessionManager.PowerShellExeDetails === undefined) { + return "Session's PowerShell details are unknown!"; + } + const child = child_process.spawnSync( + this.sessionManager.PowerShellExeDetails.exePath, + [ + "-NoProfile", + "-NoLogo", + "-Command", + "$PSVersionTable | Out-String", + ], + ); + // Replace semicolons as they'll cause the URI component to truncate + return child.stdout.toString().trim().replace(";", ","); + } +} diff --git a/src/features/GetCommands.ts b/src/features/GetCommands.ts new file mode 100644 index 0000000000..52d007532e --- /dev/null +++ b/src/features/GetCommands.ts @@ -0,0 +1,173 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as vscode from "vscode"; +import { RequestType0 } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; +import { getSettings } from "../settings"; + +interface ICommand { + name: string; + moduleName: string; + defaultParameterSet: string; + parameterSets: object; + parameters: object; +} + +/** + * RequestType sent over to PSES. + * Expects: ICommand to be returned + */ +export const GetCommandRequestType = new RequestType0( + "powerShell/getCommand", +); + +/** + * A PowerShell Command listing feature. Implements a treeview control. + */ +export class GetCommandsFeature extends LanguageClientConsumer { + private commands: vscode.Disposable[]; + private commandsExplorerProvider: CommandsExplorerProvider; + private commandsExplorerTreeView: vscode.TreeView; + + constructor() { + super(); + this.commands = [ + vscode.commands.registerCommand( + "PowerShell.RefreshCommandsExplorer", + async () => { + await this.CommandExplorerRefresh(); + }, + ), + vscode.commands.registerCommand( + "PowerShell.InsertCommand", + async (item) => { + await this.InsertCommand(item); + }, + ), + ]; + this.commandsExplorerProvider = new CommandsExplorerProvider(); + + this.commandsExplorerTreeView = vscode.window.createTreeView( + "PowerShellCommands", + { treeDataProvider: this.commandsExplorerProvider }, + ); + + // Refresh the command explorer when the view is visible + this.commandsExplorerTreeView.onDidChangeVisibility(async (e) => { + if (e.visible) { + await this.CommandExplorerRefresh(); + } + }); + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + } + + public override onLanguageClientSet(_languageClient: LanguageClient): void { + if (this.commandsExplorerTreeView.visible) { + void vscode.commands.executeCommand( + "PowerShell.RefreshCommandsExplorer", + ); + } + } + + private async CommandExplorerRefresh(): Promise { + const client = await LanguageClientConsumer.getLanguageClient(); + const result = await client.sendRequest(GetCommandRequestType); + const exclusions = getSettings().sideBar.CommandExplorerExcludeFilter; + const excludeFilter = exclusions.map((filter: string) => + filter.toLowerCase(), + ); + const filteredResult = result.filter( + (command) => + !excludeFilter.includes(command.moduleName.toLowerCase()), + ); + this.commandsExplorerProvider.powerShellCommands = + filteredResult.map(toCommand); + this.commandsExplorerProvider.refresh(); + } + + private async InsertCommand(item: { Name: string }): Promise { + const editor = vscode.window.activeTextEditor; + if (editor === undefined) { + return; + } + + const sls = editor.selection.start; + const sle = editor.selection.end; + const range = new vscode.Range( + sls.line, + sls.character, + sle.line, + sle.character, + ); + await editor.edit((editBuilder) => { + editBuilder.replace(range, item.Name); + }); + } +} + +class CommandsExplorerProvider implements vscode.TreeDataProvider { + public readonly onDidChangeTreeData: vscode.Event; + public powerShellCommands: Command[] = []; + private didChangeTreeData: vscode.EventEmitter = + new vscode.EventEmitter(); + + constructor() { + this.onDidChangeTreeData = this.didChangeTreeData.event; + } + + public refresh(): void { + this.didChangeTreeData.fire(undefined); + } + + public getTreeItem(element: Command): vscode.TreeItem { + return element; + } + + public getChildren(_element?: Command): Thenable { + return Promise.resolve(this.powerShellCommands); + } +} + +function toCommand(command: ICommand): Command { + return new Command( + command.name, + command.moduleName, + command.defaultParameterSet, + command.parameterSets, + command.parameters, + ); +} + +class Command extends vscode.TreeItem { + constructor( + public readonly Name: string, + public readonly ModuleName: string, + public readonly defaultParameterSet: string, + public readonly ParameterSets: object, + public readonly Parameters: object, + public override readonly collapsibleState = vscode + .TreeItemCollapsibleState.None, + ) { + super(Name, collapsibleState); + } + + public getTreeItem(): vscode.TreeItem { + return { + label: this.label, + collapsibleState: this.collapsibleState, + }; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/require-await + public async getChildren(_element?: any): Promise { + // Returning an empty array because we need to return something. + return []; + } +} diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts new file mode 100644 index 0000000000..bf439748d2 --- /dev/null +++ b/src/features/HelpCompletion.ts @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + Disposable, + EndOfLine, + Range, + SnippetString, + type TextDocument, + type TextDocumentChangeEvent, + window, + workspace, +} from "vscode"; +import { RequestType } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; +import { CommentType, getSettings, Settings } from "../settings"; + +interface ICommentHelpRequestArguments {} + +interface ICommentHelpRequestResponse { + content: string[]; +} + +export const CommentHelpRequestType = new RequestType< + ICommentHelpRequestArguments, + ICommentHelpRequestResponse, + void +>("powerShell/getCommentHelp"); + +enum SearchState { + Searching, + Locked, + Found, +} + +export class HelpCompletionFeature extends LanguageClientConsumer { + private helpCompletionProvider: HelpCompletionProvider | undefined; + private disposable: Disposable | undefined; + private settings: Settings; + + constructor() { + super(); + this.settings = getSettings(); + + if (this.settings.helpCompletion !== CommentType.Disabled) { + this.helpCompletionProvider = new HelpCompletionProvider(); + this.disposable = workspace.onDidChangeTextDocument(async (e) => { + await this.onEvent(e); + }); + } + } + + public dispose(): void { + this.disposable?.dispose(); + } + + public override onLanguageClientSet(languageClient: LanguageClient): void { + // Our helper class isn't in the session's list of language client + // consumers since we optionally create it, so we have to set it + // manually. + this.helpCompletionProvider?.onLanguageClientSet(languageClient); + } + + public async onEvent(changeEvent: TextDocumentChangeEvent): Promise { + // If it's not a PowerShell script, we don't care about it. + if (changeEvent.document.languageId !== "powershell") { + return; + } + + if (changeEvent.contentChanges.length > 0) { + this.helpCompletionProvider?.updateState( + changeEvent.document, + changeEvent.contentChanges[0].text, + changeEvent.contentChanges[0].range, + ); + + // TODO: Raise an event when trigger is found, and attach complete() to the event. + if (this.helpCompletionProvider?.triggerFound) { + await this.helpCompletionProvider.complete(); + this.helpCompletionProvider.reset(); + } + } + } +} + +class TriggerFinder { + private state: SearchState; + private document: TextDocument | undefined; + private count: number; + + constructor(private triggerCharacters: string) { + this.state = SearchState.Searching; + this.count = 0; + } + + public get found(): boolean { + return this.state === SearchState.Found; + } + + public updateState(document: TextDocument, changeText: string): void { + switch (this.state) { + case SearchState.Searching: + if ( + changeText.length === 1 && + // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with + changeText[0] === this.triggerCharacters[this.count] + ) { + this.state = SearchState.Locked; + this.document = document; + this.count++; + } + break; + + case SearchState.Locked: + if ( + document === this.document && + changeText.length === 1 && + // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with + changeText[0] === this.triggerCharacters[this.count] + ) { + this.count++; + if (this.count === this.triggerCharacters.length) { + this.state = SearchState.Found; + } + } else { + this.reset(); + } + break; + + default: + this.reset(); + break; + } + } + + public reset(): void { + this.state = SearchState.Searching; + this.count = 0; + } +} + +class HelpCompletionProvider extends LanguageClientConsumer { + private triggerFinderHelpComment: TriggerFinder; + private lastChangeRange: Range | undefined; + private lastDocument: TextDocument | undefined; + private settings: Settings; + + constructor() { + super(); + this.triggerFinderHelpComment = new TriggerFinder("##"); + this.settings = getSettings(); + } + + public get triggerFound(): boolean { + return this.triggerFinderHelpComment.found; + } + + public override onLanguageClientSet( + _languageClient: LanguageClient, + // eslint-disable-next-line @typescript-eslint/no-empty-function + ): void {} + + public updateState( + document: TextDocument, + changeText: string, + changeRange: Range, + ): void { + this.lastDocument = document; + this.lastChangeRange = changeRange; + this.triggerFinderHelpComment.updateState(document, changeText); + } + + public reset(): void { + this.triggerFinderHelpComment.reset(); + } + + public async complete(): Promise { + if ( + this.lastChangeRange === undefined || + this.lastDocument === undefined + ) { + return; + } + + const triggerStartPos = this.lastChangeRange.start; + const doc = this.lastDocument; + + const client = await LanguageClientConsumer.getLanguageClient(); + const result = await client.sendRequest(CommentHelpRequestType, { + documentUri: doc.uri.toString(), + triggerPosition: triggerStartPos, + blockComment: + this.settings.helpCompletion === CommentType.BlockComment, + }); + + if (result.content.length === 0) { + return; + } + + const replaceRange = new Range( + triggerStartPos.translate(0, -1), + triggerStartPos.translate(0, 1), + ); + + // TODO: add indentation level to the help content + // Trim leading whitespace (used by the rule for indentation) as VSCode takes care of the indentation. + // Trim the last empty line and join the strings. + const lines: string[] = result.content; + const text = lines.map((x) => x.trimStart()).join(this.getEOL(doc.eol)); + + const snippetString = new SnippetString(text); + + await window.activeTextEditor?.insertSnippet( + snippetString, + replaceRange, + ); + } + + private getEOL(eol: EndOfLine): string { + // there are only two type of EndOfLine types. + if (eol === EndOfLine.CRLF) { + return "\r\n"; + } + + return "\n"; + } +} diff --git a/src/features/ISECompatibility.ts b/src/features/ISECompatibility.ts new file mode 100644 index 0000000000..747bb4f6f4 --- /dev/null +++ b/src/features/ISECompatibility.ts @@ -0,0 +1,133 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as vscode from "vscode"; + +interface ISetting { + path: string; + name: string; + value: string | boolean; +} + +/** + * A feature to implement commands to make code like the ISE and reset the settings. + */ +export class ISECompatibilityFeature implements vscode.Disposable { + // Marking settings as public so we can use it within the tests without needing to duplicate the list of settings. + public static settings: ISetting[] = [ + { path: "debug", name: "openDebug", value: "neverOpen" }, + { path: "editor", name: "tabCompletion", value: "on" }, + { + path: "powershell.integratedConsole", + name: "focusConsoleOnExecute", + value: false, + }, + { path: "files", name: "defaultLanguage", value: "powershell" }, + { path: "workbench", name: "colorTheme", value: "PowerShell ISE" }, + { + path: "editor", + name: "wordSeparators", + value: "`~!@#%^&*()-=+[{]}\\|;:'\",.<>/?", + }, + { + path: "powershell.buttons", + name: "showPanelMovementButtons", + value: true, + }, + { path: "powershell.codeFolding", name: "showLastLine", value: false }, + { + path: "powershell.sideBar", + name: "CommandExplorerVisibility", + value: true, + }, + ]; + + private commands: vscode.Disposable[] = []; + private iseModeEnabled: boolean; + private originalSettings: Record = {}; + + constructor() { + const testSetting = + ISECompatibilityFeature.settings[ + ISECompatibilityFeature.settings.length - 1 + ]; + this.iseModeEnabled = + vscode.workspace + .getConfiguration(testSetting.path) + .get(testSetting.name) === testSetting.value; + this.commands = [ + vscode.commands.registerCommand( + "PowerShell.EnableISEMode", + async () => { + await this.EnableISEMode(); + }, + ), + vscode.commands.registerCommand( + "PowerShell.DisableISEMode", + async () => { + await this.DisableISEMode(); + }, + ), + vscode.commands.registerCommand( + "PowerShell.ToggleISEMode", + async () => { + await this.ToggleISEMode(); + }, + ), + ]; + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + } + + private async EnableISEMode(): Promise { + this.iseModeEnabled = true; + for (const iseSetting of ISECompatibilityFeature.settings) { + try { + const config = vscode.workspace.getConfiguration( + iseSetting.path, + ); + this.originalSettings[iseSetting.path + iseSetting.name] = + config.get(iseSetting.name); + await config.update(iseSetting.name, iseSetting.value, true); + } catch { + // The `update` call can fail if the setting doesn't exist. This + // happens when the extension runs in Azure Data Studio, which + // doesn't have a debugger, so the `debug` setting can't be + // updated. Unless we catch this exception and allow the + // function to continue, it throws an error to the user. + } + } + + // Show the PowerShell view container which has the Command Explorer view + await vscode.commands.executeCommand( + "workbench.view.extension.PowerShell", + ); + } + + private async DisableISEMode(): Promise { + this.iseModeEnabled = false; + for (const iseSetting of ISECompatibilityFeature.settings) { + const config = vscode.workspace.getConfiguration(iseSetting.path); + const currently = config.get(iseSetting.name); + if (currently === iseSetting.value) { + await config.update( + iseSetting.name, + this.originalSettings[iseSetting.path + iseSetting.name], + true, + ); + } + } + } + + private async ToggleISEMode(): Promise { + if (this.iseModeEnabled) { + await this.DisableISEMode(); + } else { + await this.EnableISEMode(); + } + } +} diff --git a/src/features/OpenInISE.ts b/src/features/OpenInISE.ts new file mode 100644 index 0000000000..808ee59db7 --- /dev/null +++ b/src/features/OpenInISE.ts @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import ChildProcess = require("child_process"); +import vscode = require("vscode"); + +export class OpenInISEFeature implements vscode.Disposable { + private command: vscode.Disposable; + + constructor() { + this.command = vscode.commands.registerCommand( + "PowerShell.OpenInISE", + () => { + const editor = vscode.window.activeTextEditor; + if (editor === undefined) { + return; + } + + const document = editor.document; + const uri = document.uri; + let ISEPath = process.env.windir ?? "C:\\Windows"; + + if (process.env.PROCESSOR_ARCHITEW6432 !== undefined) { + ISEPath += "\\Sysnative"; + } else { + ISEPath += "\\System32"; + } + + ISEPath += "\\WindowsPowerShell\\v1.0\\powershell_ise.exe"; + + ChildProcess.exec(`${ISEPath} -File "${uri.fsPath}"`).unref(); + }, + ); + } + + public dispose(): void { + this.command.dispose(); + } +} diff --git a/src/features/PesterTests.ts b/src/features/PesterTests.ts new file mode 100644 index 0000000000..486bcd8aab --- /dev/null +++ b/src/features/PesterTests.ts @@ -0,0 +1,185 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as path from "path"; +import type { ILogger } from "../logging"; +import { SessionManager } from "../session"; +import { getChosenWorkspace, getSettings } from "../settings"; +import vscode = require("vscode"); +import utils = require("../utils"); + +enum LaunchType { + Debug, + Run, +} + +export class PesterTestsFeature implements vscode.Disposable { + private commands: vscode.Disposable[]; + private invokePesterStubScriptPath: string; + + constructor( + private sessionManager: SessionManager, + private logger: ILogger, + ) { + this.invokePesterStubScriptPath = path.resolve( + __dirname, + "../modules/PowerShellEditorServices/InvokePesterStub.ps1", + ); + this.commands = [ + // File context-menu command - Run Pester Tests + vscode.commands.registerCommand( + "PowerShell.RunPesterTestsFromFile", + (fileUri?) => { + return this.launchAllTestsInActiveEditor( + LaunchType.Run, + fileUri, + ); + }, + ), + + // File context-menu command - Debug Pester Tests + vscode.commands.registerCommand( + "PowerShell.DebugPesterTestsFromFile", + (fileUri?) => { + return this.launchAllTestsInActiveEditor( + LaunchType.Debug, + fileUri, + ); + }, + ), + + // This command is provided for usage by PowerShellEditorServices (PSES) only + vscode.commands.registerCommand( + "PowerShell.RunPesterTests", + ( + uriString, + runInDebugger, + describeBlockName?, + describeBlockLineNumber?, + outputPath?, + ) => { + return this.launchTests( + vscode.Uri.parse(uriString), + runInDebugger, + describeBlockName, + describeBlockLineNumber, + outputPath, + ); + }, + ), + ]; + } + + public dispose(): void { + for (const command of this.commands) { + command.dispose(); + } + } + + private async launchAllTestsInActiveEditor( + launchType: LaunchType, + fileUri?: vscode.Uri, + ): Promise { + fileUri ??= vscode.window.activeTextEditor?.document.uri; + + if (fileUri === undefined) { + return false; + } + + const launchConfig = this.createLaunchConfig(fileUri, launchType); + return this.launch(launchConfig); + } + + private async launchTests( + fileUri: vscode.Uri, + runInDebugger: boolean, + describeBlockName?: string, + describeBlockLineNumber?: number, + outputPath?: string, + ): Promise { + const launchType = runInDebugger ? LaunchType.Debug : LaunchType.Run; + const launchConfig = this.createLaunchConfig( + fileUri, + launchType, + describeBlockName, + describeBlockLineNumber, + outputPath, + ); + return this.launch(launchConfig); + } + + private createLaunchConfig( + fileUri: vscode.Uri, + launchType: LaunchType, + testName?: string, + lineNum?: number, + outputPath?: string, + ): vscode.DebugConfiguration { + const settings = getSettings(); + const launchConfig = { + request: "launch", + type: "PowerShell", + name: "PowerShell: Launch Pester Tests", + script: this.invokePesterStubScriptPath, + args: [ + "-ScriptPath", + `'${utils.escapeSingleQuotes(fileUri.fsPath)}'`, + ], + internalConsoleOptions: "neverOpen", + noDebug: launchType === LaunchType.Run, + createTemporaryIntegratedConsole: + settings.debugging.createTemporaryIntegratedConsole, + }; + + if (lineNum) { + launchConfig.args.push("-LineNumber", `${lineNum}`); + } else if (testName) { + launchConfig.args.push( + "-TestName", + `'${utils.escapeSingleQuotes(testName)}'`, + ); + } else { + launchConfig.args.push("-All"); + } + + if (!settings.pester.useLegacyCodeLens) { + launchConfig.args.push("-MinimumVersion5"); + } + + if (launchType === LaunchType.Debug) { + launchConfig.args.push( + "-Output", + `'${settings.pester.debugOutputVerbosity}'`, + ); + } else { + launchConfig.args.push( + "-Output", + `'${settings.pester.outputVerbosity}'`, + ); + } + + if (outputPath) { + launchConfig.args.push("-OutputPath", `'${outputPath}'`); + } + + return launchConfig; + } + + private async launch( + launchConfig: vscode.DebugConfiguration, + ): Promise { + // Create or show the interactive console + // TODO: #367 Check if "newSession" mode is configured + this.sessionManager.showDebugTerminal(true); + + // Ensure the necessary script exists (for testing). The debugger will + // start regardless, but we also pass its success along. + return ( + (await utils.checkIfFileExists(this.invokePesterStubScriptPath)) && + vscode.debug.startDebugging( + await getChosenWorkspace(this.logger), + launchConfig, + ) + ); + } +} diff --git a/src/features/RemoteFiles.ts b/src/features/RemoteFiles.ts new file mode 100644 index 0000000000..46164b5de4 --- /dev/null +++ b/src/features/RemoteFiles.ts @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); +import { + NotificationType, + TextDocumentIdentifier, +} from "vscode-languageclient"; +import type { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; + +// NOTE: The following two DidSaveTextDocument* types will +// be removed when #593 gets fixed. + +export interface IDidSaveTextDocumentParams { + /** + * The document that was closed. + */ + textDocument: TextDocumentIdentifier; +} + +export const DidSaveTextDocumentNotificationType = + new NotificationType("textDocument/didSave"); + +export class RemoteFilesFeature extends LanguageClientConsumer { + private command: vscode.Disposable; + private tempSessionPathPrefix: string; + + constructor() { + super(); + // Get the common PowerShell Editor Services temporary file path + // so that remote files from previous sessions can be closed. + this.tempSessionPathPrefix = path + .join(os.tmpdir(), "PSES-") + .toLowerCase(); + + // At startup, close any lingering temporary remote files + this.closeRemoteFiles(); + + this.command = vscode.workspace.onDidSaveTextDocument(async (doc) => { + if (this.isDocumentRemote(doc)) { + const client = await LanguageClientConsumer.getLanguageClient(); + await client.sendNotification( + DidSaveTextDocumentNotificationType, + { + textDocument: TextDocumentIdentifier.create( + doc.uri.toString(), + ), + }, + ); + } + }); + } + + public override onLanguageClientSet( + _languageClient: LanguageClient, + // eslint-disable-next-line @typescript-eslint/no-empty-function + ): void {} + + public dispose(): void { + this.command.dispose(); + // Close any leftover remote files before exiting + this.closeRemoteFiles(); + } + + private isDocumentRemote(doc: vscode.TextDocument): boolean { + return doc.fileName + .toLowerCase() + .startsWith(this.tempSessionPathPrefix); + } + + private closeRemoteFiles(): void { + const remoteDocuments = vscode.workspace.textDocuments.filter((doc) => + this.isDocumentRemote(doc), + ); + + async function innerCloseFiles(): Promise { + const doc = remoteDocuments.pop(); + if (doc === undefined) { + return; + } + + await vscode.window.showTextDocument(doc); + await vscode.commands.executeCommand( + "workbench.action.closeActiveEditor", + ); + await innerCloseFiles(); + } + + void innerCloseFiles(); + } +} diff --git a/src/features/ShowHelp.ts b/src/features/ShowHelp.ts new file mode 100644 index 0000000000..6af843e53b --- /dev/null +++ b/src/features/ShowHelp.ts @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import { NotificationType } from "vscode-languageclient"; +import type { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClientConsumer } from "../languageClientConsumer"; + +interface IShowHelpNotificationArguments {} + +export const ShowHelpNotificationType = + new NotificationType("powerShell/showHelp"); + +export class ShowHelpFeature extends LanguageClientConsumer { + private command: vscode.Disposable; + + constructor() { + super(); + this.command = vscode.commands.registerCommand( + "PowerShell.ShowHelp", + async (item?) => { + if (!item?.Name) { + const editor = vscode.window.activeTextEditor; + if (editor === undefined) { + return; + } + + const selection = editor.selection; + const doc = editor.document; + const cwr = doc.getWordRangeAtPosition(selection.active); + const text = doc.getText(cwr); + + const client = + await LanguageClientConsumer.getLanguageClient(); + await client.sendNotification(ShowHelpNotificationType, { + text, + }); + } else { + const client = + await LanguageClientConsumer.getLanguageClient(); + await client.sendNotification(ShowHelpNotificationType, { + text: item.Name, + }); + } + }, + ); + } + + public override onLanguageClientSet( + _languageClient: LanguageClient, + // eslint-disable-next-line @typescript-eslint/no-empty-function + ): void {} + + public dispose(): void { + this.command.dispose(); + } +} diff --git a/src/features/UpdatePowerShell.ts b/src/features/UpdatePowerShell.ts new file mode 100644 index 0000000000..17edea4770 --- /dev/null +++ b/src/features/UpdatePowerShell.ts @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { SemVer } from "semver"; +import vscode = require("vscode"); + +import type { ILogger } from "../logging"; +import type { IPowerShellVersionDetails } from "../session"; +import { changeSetting, Settings } from "../settings"; + +interface IUpdateMessageItem extends vscode.MessageItem { + id: number; +} + +// This attempts to mirror PowerShell's `UpdatesNotification.cs` logic as much as +// possibly, documented at: +// https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_update_notifications +export class UpdatePowerShell { + private static LTSBuildInfoURL = "https://aka.ms/pwsh-buildinfo-lts"; + private static StableBuildInfoURL = "https://aka.ms/pwsh-buildinfo-stable"; + private static PreviewBuildInfoURL = + "https://aka.ms/pwsh-buildinfo-preview"; + private static GitHubWebReleaseURL = + "https://github.com/PowerShell/PowerShell/releases/tag/"; + private static promptOptions: IUpdateMessageItem[] = [ + { + id: 0, + title: "Yes", + }, + { + id: 1, + title: "Not Now", + }, + { + id: 2, + title: "Don't Show Again", + }, + ]; + private localVersion: SemVer; + + constructor( + private sessionSettings: Settings, + private logger: ILogger, + versionDetails: IPowerShellVersionDetails, + ) { + // We use the commit field as it's like + // '7.3.0-preview.3-508-g07175ae0ff8eb7306fe0b0fc7d...' which translates + // to SemVer. The version handler in PSES handles Windows PowerShell and + // just returns the first three fields like '5.1.22621'. + this.localVersion = new SemVer(versionDetails.commit); + } + + private shouldCheckForUpdate(): boolean { + // Respect user setting. + if (!this.sessionSettings.promptToUpdatePowerShell) { + this.logger.writeDebug( + "Setting 'promptToUpdatePowerShell' was false.", + ); + return false; + } + + // Respect environment configuration. + if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "off") { + this.logger.writeDebug( + "Environment variable 'POWERSHELL_UPDATECHECK' was 'Off'.", + ); + return false; + } + + // Skip prompting when using Windows PowerShell for now. + if (this.localVersion.compare("6.0.0") === -1) { + // TODO: Maybe we should announce PowerShell Core? + this.logger.writeDebug( + "Not prompting to update Windows PowerShell.", + ); + return false; + } + + if (this.localVersion.prerelease.length > 1) { + // Daily builds look like '7.3.0-daily20221206.1' which split to + // ['daily20221206', '1'] and development builds look like + // '7.3.0-preview.3-508-g07175...' which splits to ['preview', + // '3-508-g0717...']. The ellipsis is hiding a 40 char hash. + const daily = this.localVersion.prerelease[0].toString(); + const commit = this.localVersion.prerelease[1].toString(); + + // Skip if PowerShell is self-built, that is, this contains a commit hash. + if (commit.length >= 40) { + this.logger.writeDebug( + "Not prompting to update development build.", + ); + return false; + } + + // Skip if preview is a daily build. + if (daily.toLowerCase().startsWith("daily")) { + this.logger.writeDebug("Not prompting to update daily build."); + return false; + } + } + + // TODO: Check if network is available? + // TODO: Only check once a week. + return true; + } + + private async getRemoteVersion(url: string): Promise { + const response = await fetch(url); + if (!response.ok) { + return undefined; + } + // Looks like: + // { + // "ReleaseDate": "2022-10-20T22:01:38Z", + // "BlobName": "v7-2-7", + // "ReleaseTag": "v7.2.7" + // } + const data = await response.json(); + this.logger.writeDebug( + `Received from '${url}':\n${JSON.stringify(data, undefined, 2)}`, + ); + return data.ReleaseTag; + } + + private async maybeGetNewRelease(): Promise { + if (!this.shouldCheckForUpdate()) { + return undefined; + } + + this.logger.writeDebug("Checking for PowerShell update..."); + const tags: string[] = []; + if (process.env.POWERSHELL_UPDATECHECK?.toLowerCase() === "lts") { + // Only check for update to LTS. + this.logger.writeDebug("Checking for LTS update..."); + const tag = await this.getRemoteVersion( + UpdatePowerShell.LTSBuildInfoURL, + ); + if (tag != undefined) { + tags.push(tag); + } + } else { + // Check for update to stable. + this.logger.writeDebug("Checking for stable update..."); + const tag = await this.getRemoteVersion( + UpdatePowerShell.StableBuildInfoURL, + ); + if (tag != undefined) { + tags.push(tag); + } + + // Also check for a preview update. + if (this.localVersion.prerelease.length > 0) { + this.logger.writeDebug("Checking for preview update..."); + const tag = await this.getRemoteVersion( + UpdatePowerShell.PreviewBuildInfoURL, + ); + if (tag != undefined) { + tags.push(tag); + } + } + } + + for (const tag of tags) { + if (this.localVersion.compare(tag) === -1) { + return tag; + } + } + + this.logger.write("PowerShell is up-to-date."); + return undefined; + } + + public async checkForUpdate(): Promise { + try { + const tag = await this.maybeGetNewRelease(); + if (tag) { + await this.promptToUpdate(tag); + return; + } + } catch (err) { + // Best effort. This probably failed to fetch the data from GitHub. + this.logger.writeWarning( + err instanceof Error ? err.message : "unknown", + ); + } + } + + private async openReleaseInBrowser(tag: string): Promise { + const url = vscode.Uri.parse( + UpdatePowerShell.GitHubWebReleaseURL + tag, + ); + await vscode.env.openExternal(url); + } + + private async promptToUpdate(tag: string): Promise { + const releaseVersion = new SemVer(tag); + this.logger.write( + `Prompting to update PowerShell v${this.localVersion.version} to v${releaseVersion.version}.`, + ); + const result = await vscode.window.showInformationMessage( + `PowerShell v${this.localVersion.version} is out-of-date. + The latest version is v${releaseVersion.version}. + Would you like to open the GitHub release in your browser?`, + ...UpdatePowerShell.promptOptions, + ); + + // If the user cancels the notification. + if (!result) { + this.logger.writeDebug("User canceled PowerShell update prompt."); + return; + } + + this.logger.writeDebug( + `User said '${UpdatePowerShell.promptOptions[result.id].title}'.`, + ); + + switch (result.id) { + // Yes + case 0: + await this.openReleaseInBrowser(tag); + break; + // Not Now + case 1: + break; + // Don't Show Again + case 2: + await changeSetting( + "promptToUpdatePowerShell", + false, + true, + this.logger, + ); + break; + default: + break; + } + } +} diff --git a/src/features/configuration.ts b/src/features/configuration.ts deleted file mode 100644 index 24b3e0ff81..0000000000 --- a/src/features/configuration.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------*/ - -'use strict'; - -import vscode = require('vscode'); - -export interface IConfiguration { - editorServicesHostPath?: string; - waitForDebugger?: boolean; - enableLogging?: boolean; -} -export var defaultConfiguration: IConfiguration = { - editorServicesHostPath: undefined, - waitForDebugger: false, - enableLogging: false -} - -export function load(myPluginId: string): IConfiguration { - let configuration = vscode.workspace.getConfiguration(myPluginId); - return { - editorServicesHostPath: configuration.get("editorServicesHostPath", "../bin/Microsoft.PowerShell.EditorServices.Host.exe"), - waitForDebugger: configuration.get("waitForDebugger", false), - enableLogging: configuration.get("enableLogging", false) - } -} diff --git a/src/languageClientConsumer.ts b/src/languageClientConsumer.ts new file mode 100644 index 0000000000..e161f5a34e --- /dev/null +++ b/src/languageClientConsumer.ts @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { ProgressLocation, window } from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; + +export abstract class LanguageClientConsumer { + private static languageClientPromise?: Promise; + private static getLanguageClientResolve?: (value: LanguageClient) => void; + + // Implementations of this class must override this method to register their + // handlers, as its called whenever the client is restarted / replaced. + public abstract onLanguageClientSet(languageClient: LanguageClient): void; + + // This is called in the session manager when the client is started (so we + // can wait for that). It's what actually resolves the promise. + public static onLanguageClientStarted( + languageClient: LanguageClient, + ): void { + // It should have been created earlier, but if not, create and resolve it. + this.languageClientPromise ??= Promise.resolve(languageClient); + this.getLanguageClientResolve?.(languageClient); + } + + // This is called in the session manager when the client exits so we can + // make a new promise. + public static onLanguageClientExited(): void { + this.languageClientPromise = undefined; + this.getLanguageClientResolve = undefined; + } + + // We should have a promise as defined in resetLanguageClient, but if we + // don't, create it. + public static async getLanguageClient(): Promise { + // If it hasn't been created or was rejected, recreate it. + LanguageClientConsumer.languageClientPromise?.catch(() => { + LanguageClientConsumer.languageClientPromise = undefined; + }); + LanguageClientConsumer.languageClientPromise ??= + LanguageClientConsumer.createLanguageClientPromise(); + return LanguageClientConsumer.languageClientPromise; + } + + // This waits for the language client to start and shows a cancellable + // loading message. (It just wrap the static method below.) + private static async createLanguageClientPromise(): Promise { + return window.withProgress( + { + location: ProgressLocation.Notification, + title: "Please wait, starting PowerShell Extension Terminal...", + cancellable: true, + }, + (_progress, token) => { + token.onCancellationRequested(() => { + void window.showErrorMessage( + "Cancelled PowerShell Extension Terminal start-up.", + ); + }); + + // The real promise! + return new Promise((resolve, reject) => { + // Store the resolve function to be called in resetLanguageClient. + LanguageClientConsumer.getLanguageClientResolve = resolve; + // Reject the promise if the operation is cancelled. + token.onCancellationRequested(() => { + reject( + new Error( + "Cancelled PowerShell Extension Terminal start-up.", + ), + ); + }); + }); + }, + ); + } +} diff --git a/src/logging.ts b/src/logging.ts new file mode 100644 index 0000000000..4a9d9fa54d --- /dev/null +++ b/src/logging.ts @@ -0,0 +1,366 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { LogLevel, window, type Event, type LogOutputChannel } from "vscode"; + +/** Interface for logging operations. New features should use this interface for the "type" of logger. + * This will allow for easy mocking of the logger during unit tests. + */ +export interface ILogger { + write(message: string, ...additionalMessages: string[]): void; + writeAndShowInformation( + message: string, + ...additionalMessages: string[] + ): Promise; + writeTrace(message: string, ...additionalMessages: string[]): void; + writeDebug(message: string, ...additionalMessages: string[]): void; + writeWarning(message: string, ...additionalMessages: string[]): void; + writeAndShowWarning( + message: string, + ...additionalMessages: string[] + ): Promise; + writeError(message: string, ...additionalMessages: string[]): void; + writeAndShowError( + message: string, + ...additionalMessages: string[] + ): Promise; + writeAndShowErrorWithActions( + message: string, + actions: { + prompt: string; + action: (() => Promise) | undefined; + }[], + ): Promise; +} + +export class Logger implements ILogger { + // Log output channel handles all the verbosity management so we don't have to. + private logChannel: LogOutputChannel; + public get logLevel(): LogLevel { + return this.logChannel.logLevel; + } + + constructor(logChannel?: LogOutputChannel) { + this.logChannel = + logChannel ?? + window.createOutputChannel("PowerShell", { log: true }); + } + + public dispose(): void { + this.logChannel.dispose(); + } + + private writeAtLevel( + logLevel: LogLevel, + message: string, + ...additionalMessages: string[] + ): void { + if (logLevel >= this.logLevel) { + void this.writeLine(message, logLevel); + + for (const additionalMessage of additionalMessages) { + void this.writeLine(additionalMessage, logLevel); + } + } + } + + public write(message: string, ...additionalMessages: string[]): void { + this.writeAtLevel(LogLevel.Info, message, ...additionalMessages); + } + + public async writeAndShowInformation( + message: string, + ...additionalMessages: string[] + ): Promise { + this.write(message, ...additionalMessages); + + const selection = await window.showInformationMessage( + message, + "Show Logs", + "Okay", + ); + if (selection === "Show Logs") { + this.showLogPanel(); + } + } + + public writeTrace(message: string, ...additionalMessages: string[]): void { + this.writeAtLevel(LogLevel.Trace, message, ...additionalMessages); + } + + public writeDebug(message: string, ...additionalMessages: string[]): void { + this.writeAtLevel(LogLevel.Debug, message, ...additionalMessages); + } + + public writeWarning( + message: string, + ...additionalMessages: string[] + ): void { + this.writeAtLevel(LogLevel.Warning, message, ...additionalMessages); + } + + public async writeAndShowWarning( + message: string, + ...additionalMessages: string[] + ): Promise { + this.writeWarning(message, ...additionalMessages); + + const selection = await window.showWarningMessage(message, "Show Logs"); + if (selection !== undefined) { + this.showLogPanel(); + } + } + + public writeError(message: string, ...additionalMessages: string[]): void { + this.writeAtLevel(LogLevel.Error, message, ...additionalMessages); + } + + public async writeAndShowError( + message: string, + ...additionalMessages: string[] + ): Promise { + this.writeError(message, ...additionalMessages); + + const choice = await window.showErrorMessage(message, "Show Logs"); + if (choice !== undefined) { + this.showLogPanel(); + } + } + + public async writeAndShowErrorWithActions( + message: string, + actions: { + prompt: string; + action: (() => Promise) | undefined; + }[], + ): Promise { + this.writeError(message); + + const fullActions = [ + ...actions, + { + prompt: "Show Logs", + action: (): void => { + this.showLogPanel(); + }, + }, + ]; + + const actionKeys: string[] = fullActions.map((action) => action.prompt); + + const choice = await window.showErrorMessage(message, ...actionKeys); + if (choice) { + for (const action of fullActions) { + if (choice === action.prompt && action.action !== undefined) { + await action.action(); + return; + } + } + } + } + + public showLogPanel(): void { + this.logChannel.show(); + } + + private async writeLine( + message: string, + level: LogLevel = LogLevel.Info, + ): Promise { + return new Promise((resolve) => { + switch (level) { + case LogLevel.Off: + break; + case LogLevel.Trace: + this.logChannel.trace(message); + break; + case LogLevel.Debug: + this.logChannel.debug(message); + break; + case LogLevel.Info: + this.logChannel.info(message); + break; + case LogLevel.Warning: + this.logChannel.warn(message); + break; + case LogLevel.Error: + this.logChannel.error(message); + break; + default: + this.logChannel.appendLine(message); + break; + } + resolve(); + }); + } +} + +/** Parses logs received via the legacy OutputChannel to LogOutputChannel with proper severity. + * + * HACK: This is for legacy compatability and can be removed when https://github.com/microsoft/vscode-languageserver-node/issues/1116 is merged and replaced with a normal LogOutputChannel. We don't use a middleware here because any direct logging calls like client.warn() and server-initiated messages would not be captured by middleware. + */ +export class LanguageClientOutputChannelAdapter implements LogOutputChannel { + private _channel: LogOutputChannel | undefined; + private get channel(): LogOutputChannel { + this._channel ??= window.createOutputChannel(this.channelName, { + log: true, + }); + return this._channel; + } + + /** + * Creates an instance of the logging class. + * + * @param channelName - The name of the output channel. + * @param parser - A function that parses a log message and returns a tuple containing the parsed message and its log level, or undefined if the log should be filtered. + */ + constructor( + private channelName: string, + private parser: ( + message: string, + ) => + | [string, LogLevel] + | undefined = LanguageClientOutputChannelAdapter.omnisharpLspParser.bind( + this, + ), + ) {} + + public appendLine(message: string): void { + this.append(message); + } + + public append(message: string): void { + const parseResult = this.parser(message); + if (parseResult !== undefined) { + this.sendLogMessage(...parseResult); + } + } + + /** Converts from Omnisharp logs since middleware for LogMessage does not currently exist **/ + public static omnisharpLspParser(message: string): [string, LogLevel] { + const logLevelMatch = + /^\[(?Trace|Debug|Info|Warn|Error) +- \d+:\d+:\d+ [AP]M\] (?.+)/.exec( + message, + ); + const logLevel: LogLevel = logLevelMatch?.groups?.level + ? LogLevel[logLevelMatch.groups.level as keyof typeof LogLevel] + : LogLevel.Info; + const logMessage = logLevelMatch?.groups?.message ?? message; + + return [logMessage, logLevel]; + } + + protected sendLogMessage(message: string, level: LogLevel): void { + switch (level) { + case LogLevel.Trace: + this.channel.trace(message); + break; + case LogLevel.Debug: + this.channel.debug(message); + break; + case LogLevel.Info: + this.channel.info(message); + break; + case LogLevel.Warning: + this.channel.warn(message); + break; + case LogLevel.Error: + this.channel.error(message); + break; + default: + this.channel.error("!UNKNOWN LOG LEVEL!: " + message); + break; + } + } + + // #region Passthru Implementation + public get name(): string { + // prevents the window from being created unless we get a log request + return this.channelName; + } + public get logLevel(): LogLevel { + return this.channel.logLevel; + } + replace(value: string): void { + this.channel.replace(value); + } + show(_column?: undefined, preserveFocus?: boolean): void { + this.channel.show(preserveFocus); + } + public get onDidChangeLogLevel(): Event { + return this.channel.onDidChangeLogLevel; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public trace(message: string, ...args: any[]): void { + this.channel.trace(message, ...args); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public debug(message: string, ...args: any[]): void { + this.channel.debug(message, ...args); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public info(message: string, ...args: any[]): void { + this.channel.info(message, ...args); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public warn(message: string, ...args: any[]): void { + this.channel.warn(message, ...args); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public error(message: string, ...args: any[]): void { + this.channel.error(message, ...args); + } + public clear(): void { + this.channel.clear(); + } + public hide(): void { + this.channel.hide(); + } + public dispose(): void { + this.channel.dispose(); + } + // #endregion +} + +/** Special parsing for PowerShell Editor Services LSP messages since the LogLevel cannot be read due to vscode + * LanguageClient Limitations (https://github.com/microsoft/vscode-languageserver-node/issues/1116) + */ +export function PsesParser(message: string): [string, LogLevel] { + const logLevelMatch = + /^<(?Trace|Debug|Info|Warning|Error)>(?.+)/.exec( + message, + ); + const logLevel: LogLevel = logLevelMatch?.groups?.level + ? LogLevel[logLevelMatch.groups.level as keyof typeof LogLevel] + : LogLevel.Info; + const logMessage = logLevelMatch?.groups?.message ?? message; + + return ["[PSES] " + logMessage, logLevel]; +} + +/** Lsp Trace Parser that does some additional parsing and formatting to make it look nicer */ +export function LspTraceParser(message: string): [string, LogLevel] { + let [parsedMessage, level] = + LanguageClientOutputChannelAdapter.omnisharpLspParser(message); + if (parsedMessage.startsWith("Sending ")) { + parsedMessage = parsedMessage.replace("Sending", "➡️"); + level = LogLevel.Debug; + } + if (parsedMessage.startsWith("Received ")) { + parsedMessage = parsedMessage.replace("Received", "⬅️"); + level = LogLevel.Debug; + } + if ( + parsedMessage.startsWith("Params:") || + parsedMessage.startsWith("Result:") + ) { + level = LogLevel.Trace; + } + + // These are PSES messages that get logged to the output channel anyways so we drop these to trace for easy noise filtering + if (parsedMessage.startsWith("⬅️ notification 'window/logMessage'")) { + level = LogLevel.Trace; + } + + return [parsedMessage.trimEnd(), level]; +} diff --git a/src/main.ts b/src/main.ts deleted file mode 100644 index 4ffe4a9edd..0000000000 --- a/src/main.ts +++ /dev/null @@ -1,117 +0,0 @@ -/*--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------*/ - -'use strict'; - -import path = require('path'); -import vscode = require('vscode'); -import configuration = require('./features/configuration'); -import { LanguageClient, LanguageClientOptions, Executable } from 'vscode-languageclient'; - -export function activate(context: vscode.ExtensionContext): void { - - var PowerShellLanguageId = 'PowerShell'; - - vscode.languages.setLanguageConfiguration(PowerShellLanguageId, - { - wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\'\"\,\.\<\>\/\?\s]+)/g, - - indentationRules: { - // ^(.*\*/)?\s*\}.*$ - decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/, - // ^.*\{[^}"']*$ - increaseIndentPattern: /^.*\{[^}"']*$/ - }, - - comments: { - lineComment: '#', - blockComment: ['<#', '#>'] - }, - - brackets: [ - ['{', '}'], - ['[', ']'], - ['(', ')'], - ], - - __electricCharacterSupport: { - brackets: [ - { tokenType:'delimiter.curly.ts', open: '{', close: '}', isElectric: true }, - { tokenType:'delimiter.square.ts', open: '[', close: ']', isElectric: true }, - { tokenType:'delimiter.paren.ts', open: '(', close: ')', isElectric: true } - ], - docComment: { scope:'comment.documentation', open:'/**', lineStart:' * ', close:' */' } - }, - - __characterPairSupport: { - autoClosingPairs: [ - { open: '{', close: '}' }, - { open: '[', close: ']' }, - { open: '(', close: ')' }, - { open: '"', close: '"', notIn: ['string'] }, - { open: '\'', close: '\'', notIn: ['string', 'comment'] } - ] - } - - }); - - let serverPath = resolveLanguageServerPath(); - let serverOptions = { - run: { - command: serverPath, - }, - debug: { - command: serverPath, - args: ['/waitForDebugger'] - } - }; - - let clientOptions: LanguageClientOptions = { - documentSelector: [PowerShellLanguageId], - synchronize: { - configurationSection: PowerShellLanguageId, - //fileEvents: vscode.workspace.createFileSystemWatcher('**/.eslintrc') - } - } - - let client = - new LanguageClient( - 'PowerShell Editor Services', - serverOptions, - clientOptions); - - client.start(); -} - -function resolveLanguageServerPath() : string { - var config = configuration.load('PowerShell'); - var editorServicesHostPath = config.editorServicesHostPath; - - if (config.editorServicesHostPath) - { - console.log("Found Editor Services path from config: " + editorServicesHostPath); - - // Make the path absolute if it's not - editorServicesHostPath = - path.resolve( - __dirname, - config.editorServicesHostPath); - - console.log(" Resolved path to: " + editorServicesHostPath); - } - else - { - // Use the default path in the plugin's 'bin' folder - editorServicesHostPath = - path.join( - __dirname, - '..', - 'bin', - 'Microsoft.PowerShell.EditorServices.Host.exe'); - - console.log("Using default Editor Services path: " + editorServicesHostPath); - } - - return editorServicesHostPath; -} diff --git a/src/platform.ts b/src/platform.ts new file mode 100644 index 0000000000..76ca5992ed --- /dev/null +++ b/src/platform.ts @@ -0,0 +1,792 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as os from "os"; +import * as path from "path"; +import * as process from "process"; +import untildify from "untildify"; +import { integer } from "vscode-languageserver-protocol"; +import type { ILogger } from "./logging"; +import { + changeSetting, + getSettings, + type PowerShellAdditionalExePathSettings, +} from "./settings"; +import * as utils from "./utils"; +import vscode = require("vscode"); + +const WindowsPowerShell64BitLabel = "Windows PowerShell (x64)"; +const WindowsPowerShell32BitLabel = "Windows PowerShell (x86)"; + +const LinuxExePath = "/usr/bin/pwsh"; +const LinuxPreviewExePath = "/usr/bin/pwsh-preview"; + +const SnapExePath = "/snap/bin/pwsh"; +const SnapPreviewExePath = "/snap/bin/pwsh-preview"; + +const MacOSExePath = "/usr/local/bin/pwsh"; +const MacOSPreviewExePath = "/usr/local/bin/pwsh-preview"; + +const MacOSHomebrewExePath = "/opt/homebrew/bin/pwsh"; +const MacOSHomebrewLTSExePath = "/opt/homebrew/bin/pwsh-lts"; +const MacOSHomebrewPreviewExePath = "/opt/homebrew/bin/pwsh-preview"; + +export enum OperatingSystem { + Unknown, + Windows, + MacOS, + Linux, +} + +export interface IPlatformDetails { + operatingSystem: OperatingSystem; + isOS64Bit: boolean; + isProcess64Bit: boolean; +} + +export interface IPowerShellExeDetails { + readonly displayName: string; + readonly exePath: string; + readonly supportsProperArguments: boolean; +} + +export function getPlatformDetails(): IPlatformDetails { + let operatingSystem = OperatingSystem.Unknown; + + if (process.platform === "win32") { + operatingSystem = OperatingSystem.Windows; + } else if (process.platform === "darwin") { + operatingSystem = OperatingSystem.MacOS; + } else if (process.platform === "linux") { + operatingSystem = OperatingSystem.Linux; + } + + const isProcess64Bit = process.arch === "x64" || process.arch === "arm64"; + + return { + operatingSystem, + isOS64Bit: + isProcess64Bit || process.env.PROCESSOR_ARCHITEW6432 !== undefined, + isProcess64Bit, + }; +} + +/** + * Class to lazily find installed PowerShell executables on a machine. + * When given a list of additional PowerShell executables, + * this will also surface those at the end of the list. + */ +export class PowerShellExeFinder { + // This is required, since parseInt("7-preview") will return 7. + private static IntRegex = /^\d+$/; + private static PwshMsixRegex = /^Microsoft.PowerShell_.*/; + private static PwshPreviewMsixRegex = /^Microsoft.PowerShellPreview_.*/; + private winPS: IPossiblePowerShellExe | undefined; + private alternateBitnessWinPS: IPossiblePowerShellExe | undefined; + + /** + * Create a new PowerShellFinder object to discover PowerShell installations. + * @param platformDetails Information about the machine we are running on. + * @param additionalPowerShellExes Additional PowerShell installations as configured in the settings. + */ + constructor( + // The platform details descriptor for the platform we're on + private platformDetails: IPlatformDetails, + // Additional configured PowerShells + private additionalPowerShellExes: PowerShellAdditionalExePathSettings, + private logger?: ILogger, + ) {} + + /** + * Returns the first available PowerShell executable found in the search order. + */ + public async getFirstAvailablePowerShellInstallation(): Promise< + IPowerShellExeDetails | undefined + > { + for await (const pwsh of this.enumeratePowerShellInstallations()) { + return pwsh; + } + return undefined; + } + + /** + * Get an array of all PowerShell executables found when searching for PowerShell installations. + */ + public async getAllAvailablePowerShellInstallations(): Promise< + IPowerShellExeDetails[] + > { + const array: IPowerShellExeDetails[] = []; + for await (const pwsh of this.enumeratePowerShellInstallations()) { + array.push(pwsh); + } + return array; + } + + /** + * Fixes PowerShell paths when Windows PowerShell is set to the non-native bitness. + * @param configuredPowerShellPath the PowerShell path configured by the user. + */ + public fixWindowsPowerShellPath( + configuredPowerShellPath: string, + ): string | undefined { + const altWinPS = this.findWinPS({ useAlternateBitness: true }); + + if (!altWinPS) { + return configuredPowerShellPath; + } + + const lowerAltWinPSPath = altWinPS.exePath.toLocaleLowerCase(); + const lowerConfiguredPath = + configuredPowerShellPath.toLocaleLowerCase(); + + if (lowerConfiguredPath === lowerAltWinPSPath) { + return this.findWinPS()?.exePath; + } + + return configuredPowerShellPath; + } + + /** + * Iterates through PowerShell installations on the machine according + * to configuration passed in through the constructor. + * PowerShell items returned by this object are verified + * to exist on the filesystem. + */ + public async *enumeratePowerShellInstallations(): AsyncIterable { + // Get the default PowerShell installations first + for await (const defaultPwsh of this.enumerateDefaultPowerShellInstallations()) { + if (defaultPwsh && (await defaultPwsh.exists())) { + yield defaultPwsh; + } + } + + // Also show any additionally configured PowerShells + // These may be duplicates of the default installations, but given a different name. + for await (const additionalPwsh of this.enumerateAdditionalPowerShellInstallations()) { + if (await additionalPwsh.exists()) { + yield additionalPwsh; + } else if (!additionalPwsh.suppressWarning) { + const message = `Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`; + this.logger?.writeWarning(message); + + if (!getSettings().suppressAdditionalExeNotFoundWarning) { + const selection = await vscode.window.showWarningMessage( + message, + "Don't Show Again", + ); + if (selection !== undefined) { + await changeSetting( + "suppressAdditionalExeNotFoundWarning", + true, + true, + this.logger, + ); + } + } + } + } + } + + /** + * Iterates through all the possible well-known PowerShell installations on a machine. + * Returned values may not exist, but come with an .exists property + * which will check whether the executable exists. + * TODO: We really need to define the order in which we search for stable/LTS/preview/daily + */ + private async *enumerateDefaultPowerShellInstallations(): AsyncIterable< + IPossiblePowerShellExe | undefined + > { + // Find PSCore stable first + yield this.findPSCoreStable(); + + switch (this.platformDetails.operatingSystem) { + case OperatingSystem.Linux: + // On Linux, find the snap + yield this.findPSCoreStableSnap(); + break; + + case OperatingSystem.Windows: + // Windows may have a 32-bit pwsh.exe + yield this.findPSCoreWindowsInstallation({ + useAlternateBitness: true, + }); + // Also look for the MSIX/UWP installation + yield await this.findPSCoreMsix(); + break; + + case OperatingSystem.MacOS: + // On MacOS, find the Homebrew installations + yield this.findPSCoreHomebrewStable(); + yield this.findPSCoreHomebrewLTS(); + break; + } + + // Look for the .NET global tool + // Some older versions of PowerShell have a bug in this where startup will fail, + // but this is fixed in newer versions + yield this.findPSCoreDotnetGlobalTool(); + + // Look for PSCore preview + yield this.findPSCorePreview(); + + switch (this.platformDetails.operatingSystem) { + // On Linux, there might be a preview snap + case OperatingSystem.Linux: + yield this.findPSCorePreviewSnap(); + break; + + case OperatingSystem.Windows: + // Find a preview MSIX + yield this.findPSCoreMsix({ findPreview: true }); + + // Look for pwsh-preview with the opposite bitness + yield this.findPSCoreWindowsInstallation({ + useAlternateBitness: true, + findPreview: true, + }); + + // Finally, get Windows PowerShell + + // Get the natural Windows PowerShell for the process bitness + yield this.findWinPS(); + + // Get the alternate bitness Windows PowerShell + yield this.findWinPS({ useAlternateBitness: true }); + + break; + + case OperatingSystem.MacOS: + // On MacOS, find the Homebrew preview + yield this.findPSCoreHomebrewPreview(); + break; + } + + // Look for PSCore daily + yield this.findPSCoreDaily(); + } + + /** + * Iterates through the configured additional PowerShell executable locations, + * without checking for their existence. + */ + public async *enumerateAdditionalPowerShellInstallations(): AsyncIterable { + for (const versionName in this.additionalPowerShellExes) { + if ( + Object.prototype.hasOwnProperty.call( + this.additionalPowerShellExes, + versionName, + ) + ) { + let exePath: string | undefined = utils.stripQuotePair( + this.additionalPowerShellExes[versionName], + ); + if (!exePath) { + continue; + } + + exePath = untildify(exePath); + const args: [string, undefined, boolean, boolean] = + // Must be a tuple type and is suppressing the warning + [versionName, undefined, true, true]; + + // Always search for what the user gave us first, but with the warning + // suppressed so we can display it after all possibilities are exhausted + let pwsh = new PossiblePowerShellExe(exePath, ...args); + if (await pwsh.exists()) { + yield pwsh; + continue; + } + + // Also search for `pwsh[.exe]` and `powershell[.exe]` if missing + if ( + this.platformDetails.operatingSystem === + OperatingSystem.Windows + ) { + // Handle Windows where '.exe' and 'powershell' are things + if ( + !exePath.endsWith("pwsh.exe") && + !exePath.endsWith("powershell.exe") + ) { + if ( + exePath.endsWith("pwsh") || + exePath.endsWith("powershell") + ) { + // Add extension if that was missing + pwsh = new PossiblePowerShellExe( + exePath + ".exe", + ...args, + ); + if (await pwsh.exists()) { + yield pwsh; + continue; + } + } + // Also add full exe names (this isn't an else just in case + // the folder was named "pwsh" or "powershell") + pwsh = new PossiblePowerShellExe( + path.join(exePath, "pwsh.exe"), + ...args, + ); + if (await pwsh.exists()) { + yield pwsh; + continue; + } + pwsh = new PossiblePowerShellExe( + path.join(exePath, "powershell.exe"), + ...args, + ); + if (await pwsh.exists()) { + yield pwsh; + continue; + } + } + } else if (!exePath.endsWith("pwsh")) { + // Always just 'pwsh' on non-Windows + pwsh = new PossiblePowerShellExe( + path.join(exePath, "pwsh"), + ...args, + ); + if (await pwsh.exists()) { + yield pwsh; + continue; + } + } + + // If we're still being iterated over, no permutation of the given path existed so yield an object with the warning unsuppressed + yield new PossiblePowerShellExe( + exePath, + versionName, + false, + undefined, + false, + ); + } + } + } + + private async findPSCoreStable(): Promise< + IPossiblePowerShellExe | undefined + > { + switch (this.platformDetails.operatingSystem) { + case OperatingSystem.Linux: + return new PossiblePowerShellExe(LinuxExePath, "PowerShell"); + + case OperatingSystem.MacOS: + return new PossiblePowerShellExe(MacOSExePath, "PowerShell"); + + case OperatingSystem.Windows: + return await this.findPSCoreWindowsInstallation(); + + case OperatingSystem.Unknown: + return undefined; + } + } + + private async findPSCorePreview(): Promise< + IPossiblePowerShellExe | undefined + > { + switch (this.platformDetails.operatingSystem) { + case OperatingSystem.Linux: + return new PossiblePowerShellExe( + LinuxPreviewExePath, + "PowerShell Preview", + ); + + case OperatingSystem.MacOS: + return new PossiblePowerShellExe( + MacOSPreviewExePath, + "PowerShell Preview", + ); + + case OperatingSystem.Windows: + return await this.findPSCoreWindowsInstallation({ + findPreview: true, + }); + + case OperatingSystem.Unknown: + return undefined; + } + } + + /** + * If the daily was installed via 'https://aka.ms/install-powershell.ps1', then + * this is the default installation location: + * + * if ($IsWinEnv) { + * $Destination = "$env:LOCALAPPDATA\Microsoft\powershell" + * } else { + * $Destination = "~/.powershell" + * } + * + * if ($Daily) { + * $Destination = "${Destination}-daily" + * } + * + * TODO: Remove this after the daily is officially no longer supported. + */ + private findPSCoreDaily(): IPossiblePowerShellExe | undefined { + switch (this.platformDetails.operatingSystem) { + case OperatingSystem.Linux: + case OperatingSystem.MacOS: { + const exePath = path.join( + os.homedir(), + ".powershell-daily", + "pwsh", + ); + return new PossiblePowerShellExe(exePath, "PowerShell Daily"); + } + + case OperatingSystem.Windows: { + // We can't proceed if there's no LOCALAPPDATA path + if (!process.env.LOCALAPPDATA) { + return undefined; + } + const exePath = path.join( + process.env.LOCALAPPDATA, + "Microsoft", + "powershell-daily", + "pwsh.exe", + ); + return new PossiblePowerShellExe(exePath, "PowerShell Daily"); + } + + case OperatingSystem.Unknown: + return undefined; + } + } + + // The Homebrew installations of PowerShell on Apple Silicon are no longer in the default PATH. + private findPSCoreHomebrewStable(): IPossiblePowerShellExe { + return new PossiblePowerShellExe( + MacOSHomebrewExePath, + "PowerShell (Homebrew)", + ); + } + + private findPSCoreHomebrewLTS(): IPossiblePowerShellExe { + return new PossiblePowerShellExe( + MacOSHomebrewLTSExePath, + "PowerShell LTS (Homebrew)", + ); + } + + private findPSCoreHomebrewPreview(): IPossiblePowerShellExe { + return new PossiblePowerShellExe( + MacOSHomebrewPreviewExePath, + "PowerShell Preview (Homebrew)", + ); + } + + private findPSCoreDotnetGlobalTool(): IPossiblePowerShellExe { + const exeName: string = + this.platformDetails.operatingSystem === OperatingSystem.Windows + ? "pwsh.exe" + : "pwsh"; + + const dotnetGlobalToolExePath: string = path.join( + os.homedir(), + ".dotnet", + "tools", + exeName, + ); + + // The dotnet installed version of PowerShell does not support proper argument parsing, and so it fails with our multi-line startup banner. + return new PossiblePowerShellExe( + dotnetGlobalToolExePath, + ".NET Core PowerShell Global Tool", + undefined, + false, + ); + } + + private async findPSCoreMsix({ + findPreview, + }: { findPreview?: boolean } = {}): Promise< + IPossiblePowerShellExe | undefined + > { + // We can't proceed if there's no LOCALAPPDATA path + if (!process.env.LOCALAPPDATA) { + return undefined; + } + + // Find the base directory for MSIX application exe shortcuts + const msixAppDir = path.join( + process.env.LOCALAPPDATA, + "Microsoft", + "WindowsApps", + ); + + if (!(await utils.checkIfDirectoryExists(msixAppDir))) { + return undefined; + } + + // Define whether we're looking for the preview or the stable + const { pwshMsixDirRegex, pwshMsixName } = findPreview + ? { + pwshMsixDirRegex: PowerShellExeFinder.PwshPreviewMsixRegex, + pwshMsixName: "PowerShell Preview (Store)", + } + : { + pwshMsixDirRegex: PowerShellExeFinder.PwshMsixRegex, + pwshMsixName: "PowerShell (Store)", + }; + + // We should find only one such application, so return on the first one + for (const name of await utils.readDirectory(msixAppDir)) { + if (pwshMsixDirRegex.test(name)) { + return new PossiblePowerShellExe( + path.join(msixAppDir, name, "pwsh.exe"), + pwshMsixName, + ); + } + } + + return undefined; + } + + // TODO: Are snaps still a thing? + private findPSCoreStableSnap(): IPossiblePowerShellExe { + return new PossiblePowerShellExe(SnapExePath, "PowerShell Snap"); + } + + private findPSCorePreviewSnap(): IPossiblePowerShellExe { + return new PossiblePowerShellExe( + SnapPreviewExePath, + "PowerShell Preview Snap", + ); + } + + private async findPSCoreWindowsInstallation({ + useAlternateBitness = false, + findPreview = false, + }: { useAlternateBitness?: boolean; findPreview?: boolean } = {}): Promise< + IPossiblePowerShellExe | undefined + > { + const programFilesPath = this.getProgramFilesPath({ + useAlternateBitness, + }); + + if (!programFilesPath) { + return undefined; + } + + const powerShellInstallBaseDir = path.join( + programFilesPath, + "PowerShell", + ); + + // Ensure the base directory exists + if (!(await utils.checkIfDirectoryExists(powerShellInstallBaseDir))) { + return undefined; + } + + let highestSeenVersion = -1; + let pwshExePath: string | undefined; + for (const item of await utils.readDirectory( + powerShellInstallBaseDir, + )) { + let currentVersion = -1; + if (findPreview) { + // We are looking for something like "7-preview" + + // Preview dirs all have dashes in them + const dashIndex: integer = item.indexOf("-"); + if (dashIndex < 0) { + continue; + } + + // Verify that the part before the dash is an integer + const intPart: string = item.substring(0, dashIndex); + if (!PowerShellExeFinder.IntRegex.test(intPart)) { + continue; + } + + // Verify that the part after the dash is "preview" + if (item.substring(dashIndex + 1) !== "preview") { + continue; + } + + currentVersion = parseInt(intPart, 10); + } else { + // Search for a directory like "6" or "7" + if (!PowerShellExeFinder.IntRegex.test(item)) { + continue; + } + + currentVersion = parseInt(item, 10); + } + + // Ensure we haven't already seen a higher version + if (currentVersion <= highestSeenVersion) { + continue; + } + + // Now look for the file + const exePath = path.join( + powerShellInstallBaseDir, + item, + "pwsh.exe", + ); + if (!(await utils.checkIfFileExists(exePath))) { + continue; + } + + pwshExePath = exePath; + highestSeenVersion = currentVersion; + } + + if (!pwshExePath) { + return undefined; + } + + const bitness: string = programFilesPath.includes("x86") + ? "(x86)" + : "(x64)"; + + const preview: string = findPreview ? " Preview" : ""; + + return new PossiblePowerShellExe( + pwshExePath, + `PowerShell${preview} ${bitness}`, + ); + } + + private findWinPS({ + useAlternateBitness = false, + }: { useAlternateBitness?: boolean } = {}): + | IPossiblePowerShellExe + | undefined { + // 32-bit OSes only have one WinPS on them + if (!this.platformDetails.isOS64Bit && useAlternateBitness) { + return undefined; + } + + let winPS = useAlternateBitness + ? this.alternateBitnessWinPS + : this.winPS; + if (winPS === undefined) { + const systemFolderPath = this.getSystem32Path({ + useAlternateBitness, + }); + + if (!systemFolderPath) { + return undefined; + } + + const winPSPath = path.join( + systemFolderPath, + "WindowsPowerShell", + "v1.0", + "powershell.exe", + ); + + let displayName: string; + if (this.platformDetails.isProcess64Bit) { + displayName = useAlternateBitness + ? WindowsPowerShell32BitLabel + : WindowsPowerShell64BitLabel; + } else if (this.platformDetails.isOS64Bit) { + displayName = useAlternateBitness + ? WindowsPowerShell64BitLabel + : WindowsPowerShell32BitLabel; + } else { + displayName = WindowsPowerShell32BitLabel; + } + + winPS = new PossiblePowerShellExe(winPSPath, displayName, true); + + if (useAlternateBitness) { + this.alternateBitnessWinPS = winPS; + } else { + this.winPS = winPS; + } + } + + return winPS; + } + + private getProgramFilesPath({ + useAlternateBitness = false, + }: { useAlternateBitness?: boolean } = {}): string | undefined { + if (!useAlternateBitness) { + // Just use the native system bitness + return process.env.ProgramFiles; + } + + // We might be a 64-bit process looking for 32-bit program files + if (this.platformDetails.isProcess64Bit) { + return process.env["ProgramFiles(x86)"]; + } + + // We might be a 32-bit process looking for 64-bit program files + if (this.platformDetails.isOS64Bit) { + return process.env.ProgramW6432; + } + + // We're a 32-bit process on 32-bit Windows, there is no other Program Files dir + return undefined; + } + + private getSystem32Path({ + useAlternateBitness = false, + }: { useAlternateBitness?: boolean } = {}): string | undefined { + const windir = process.env.windir; + + if (!windir) { + return undefined; + } + + if (!useAlternateBitness) { + // Just use the native system bitness + return path.join(windir, "System32"); + } + + // We might be a 64-bit process looking for 32-bit system32 + if (this.platformDetails.isProcess64Bit) { + return path.join(windir, "SysWOW64"); + } + + // We might be a 32-bit process looking for 64-bit system32 + if (this.platformDetails.isOS64Bit) { + return path.join(windir, "Sysnative"); + } + + // We're on a 32-bit Windows, so no alternate bitness + return undefined; + } +} + +export function getWindowsSystemPowerShellPath( + systemFolderName: string, +): string | undefined { + if (process.env.windir === undefined) { + return undefined; + } else + return path.join( + process.env.windir, + systemFolderName, + "WindowsPowerShell", + "v1.0", + "powershell.exe", + ); +} + +interface IPossiblePowerShellExe extends IPowerShellExeDetails { + exists(): Promise; + readonly suppressWarning: boolean; +} + +class PossiblePowerShellExe implements IPossiblePowerShellExe { + constructor( + public readonly exePath: string, + public readonly displayName: string, + private knownToExist?: boolean, + public readonly supportsProperArguments = true, + public readonly suppressWarning = false, + ) {} + + public async exists(): Promise { + this.knownToExist ??= await utils.checkIfFileExists(this.exePath); + return this.knownToExist ?? false; + } +} diff --git a/src/process.ts b/src/process.ts new file mode 100644 index 0000000000..75314d882c --- /dev/null +++ b/src/process.ts @@ -0,0 +1,332 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import cp = require("child_process"); +import path = require("path"); +import vscode = require("vscode"); +import { promisify } from "util"; +import type { ILogger } from "./logging"; +import type { IEditorServicesSessionDetails } from "./session"; +import { Settings, validateCwdSetting } from "./settings"; +import utils = require("./utils"); + +export class PowerShellProcess { + private static title = "PowerShell Extension"; + + public onExited: vscode.Event; + private onExitedEmitter?: vscode.EventEmitter; + + private consoleTerminal?: vscode.Terminal; + private consoleCloseSubscription?: vscode.Disposable; + + private pid?: number; + private pidUpdateEmitter?: vscode.EventEmitter; + + constructor( + public exePath: string, + private bundledModulesPath: string, + private isTemp: boolean, + private shellIntegrationEnabled: boolean, + private logger: ILogger, + private logDirectoryPath: vscode.Uri, + private startPsesArgs: string, + private sessionFilePath: vscode.Uri, + private sessionSettings: Settings, + private devMode = false, + ) { + this.onExitedEmitter = new vscode.EventEmitter(); + this.onExited = this.onExitedEmitter.event; + this.pidUpdateEmitter = new vscode.EventEmitter(); + } + + public async start( + cancellationToken: vscode.CancellationToken, + ): Promise { + const psesModulePath = path.resolve( + __dirname, + this.bundledModulesPath, + "PowerShellEditorServices/PowerShellEditorServices.psd1", + ); + + const featureFlags = + this.sessionSettings.developer.featureFlags.length > 0 + ? this.sessionSettings.developer.featureFlags + .map((f) => `'${f}'`) + .join(", ") + : ""; + + this.startPsesArgs += + `-LogPath '${utils.escapeSingleQuotes(this.logDirectoryPath.fsPath)}' ` + + `-SessionDetailsPath '${utils.escapeSingleQuotes(this.sessionFilePath.fsPath)}' ` + + `-FeatureFlags @(${featureFlags}) `; + + if (this.sessionSettings.integratedConsole.useLegacyReadLine) { + this.startPsesArgs += "-UseLegacyReadLine"; + } + + const powerShellArgs: string[] = []; + + const useLoginShell: boolean = + (utils.isMacOS && this.sessionSettings.startAsLoginShell.osx) || + (utils.isLinux && this.sessionSettings.startAsLoginShell.linux); + + if (useLoginShell && this.isLoginShell(this.exePath)) { + // This MUST be the first argument. + powerShellArgs.push("-Login"); + } + + powerShellArgs.push("-NoProfile"); + + // Only add ExecutionPolicy param on Windows + if ( + utils.isWindows && + this.sessionSettings.developer.setExecutionPolicy + ) { + powerShellArgs.push("-ExecutionPolicy", "Bypass"); + } + + const startEditorServices = + "Import-Module '" + + utils.escapeSingleQuotes(psesModulePath) + + "'; Start-EditorServices " + + this.startPsesArgs; + + // On Windows we unfortunately can't Base64 encode the startup command + // because it annoys some poorly implemented anti-virus scanners. + if (utils.isWindows) { + powerShellArgs.push("-Command", startEditorServices); + } else { + // Otherwise use -EncodedCommand for better quote support. + this.logger.writeDebug( + "Using Base64 -EncodedCommand but logging as -Command equivalent.", + ); + powerShellArgs.push( + "-EncodedCommand", + Buffer.from(startEditorServices, "utf16le").toString("base64"), + ); + } + + this.logger.writeDebug( + `Starting process: ${this.exePath} ${powerShellArgs.slice(0, -2).join(" ")} -Command ${startEditorServices}`, + ); + + // Make sure no old session file exists + await this.deleteSessionFile(this.sessionFilePath); + + // When VS Code shell integration is enabled, the script expects certain + // variables to be added to the environment. + let envMixin = {}; + if (this.shellIntegrationEnabled) { + envMixin = { + VSCODE_INJECTION: "1", + // There is no great way to check if we are running stable VS + // Code. Since this is used to disable experimental features, we + // default to stable unless we're definitely running Insiders. + VSCODE_STABLE: vscode.env.appName.includes("Insiders") + ? "0" + : "1", + // Maybe one day we can set VSCODE_NONCE... + }; + } + + // Enables Hot Reload in .NET for the attached process + // https://devblogs.microsoft.com/devops/net-enc-support-for-lambdas-and-other-improvements-in-visual-studio-2015/ + if (this.devMode) { + (envMixin as Record).COMPLUS_FORCEENC = "1"; + } + + // Launch PowerShell in the integrated terminal + const terminalOptions: vscode.TerminalOptions = { + name: this.isTemp + ? `${PowerShellProcess.title} (TEMP)` + : PowerShellProcess.title, + shellPath: this.exePath, + shellArgs: powerShellArgs, + cwd: await validateCwdSetting(this.logger), + env: envMixin, + iconPath: new vscode.ThemeIcon("terminal-powershell"), + isTransient: true, + hideFromUser: + this.sessionSettings.integratedConsole.startInBackground, + location: + vscode.TerminalLocation[ + this.sessionSettings.integratedConsole.startLocation + ], + }; + + // Subscribe a log event for when the terminal closes (this fires for + // all terminals and the event itself checks if it's our terminal). This + // subscription should happen before we create the terminal so if it + // fails immediately, the event fires. + this.consoleCloseSubscription = vscode.window.onDidCloseTerminal( + (terminal) => { + this.onTerminalClose(terminal); + }, + ); + this.consoleTerminal = vscode.window.createTerminal(terminalOptions); + this.pid = await this.getPid(); + this.logger.write(`PowerShell process started with PID: ${this.pid}`); + this.pidUpdateEmitter?.fire(this.pid); + + if ( + this.sessionSettings.integratedConsole.showOnStartup && + !this.sessionSettings.integratedConsole.startInBackground + ) { + // We still need to run this to set the active terminal to the extension terminal. + this.consoleTerminal.show(true); + } + + return await this.waitForSessionFile(cancellationToken); + } + + // This function is used to clean-up stale PowerShell Extension terminals, + // which can happen with `restartExtensionHost` is called because we are + // unable to finish diposing before we're gone. + public static cleanUpTerminals(): void { + for (const terminal of vscode.window.terminals) { + if (terminal.name.startsWith(PowerShellProcess.title)) { + terminal.dispose(); + } + } + } + + // This function should only be used after a failure has occurred because it is slow! + public async getVersionCli(): Promise { + const exec = promisify(cp.execFile); + const { stdout } = await exec(this.exePath, [ + "-NoProfile", + "-NoLogo", + "-Command", + "$PSVersionTable.PSVersion.ToString()", + ]); + return stdout.trim(); + } + + // Returns the process Id of the consoleTerminal + public async getPid(): Promise { + return await this.consoleTerminal?.processId; + } + + public showTerminal(preserveFocus?: boolean): void { + this.consoleTerminal?.show(preserveFocus); + } + + public dispose(): void { + this.logger.writeDebug( + `Disposing PowerShell process with PID: ${this.pid}`, + ); + + void this.deleteSessionFile(this.sessionFilePath); + + this.onExitedEmitter?.fire(); + this.onExitedEmitter = undefined; + + this.consoleTerminal?.dispose(); + this.consoleTerminal = undefined; + + this.consoleCloseSubscription?.dispose(); + this.consoleCloseSubscription = undefined; + + this.pidUpdateEmitter?.dispose(); + this.pidUpdateEmitter = undefined; + } + + public sendKeyPress(): void { + // NOTE: This is a regular character instead of something like \0 + // because non-printing characters can cause havoc with different + // languages and terminal settings. We discard the character server-side + // anyway, so it doesn't matter what we send. + this.consoleTerminal?.sendText("p", false); + } + + private isLoginShell(pwshPath: string): boolean { + try { + // We can't know what version of PowerShell we have without running it + // So we try to start PowerShell with -Login + // If it exits successfully, we return true + // If it exits unsuccessfully, node throws, we catch, and return false + cp.execFileSync(pwshPath, [ + "-Login", + "-NoProfile", + "-NoLogo", + "-Command", + "exit 0", + ]); + } catch { + return false; + } + return true; + } + + private async readSessionFile( + sessionFilePath: vscode.Uri, + ): Promise { + const fileContents = + await vscode.workspace.fs.readFile(sessionFilePath); + return JSON.parse(fileContents.toString()); + } + + private async deleteSessionFile( + sessionFilePath: vscode.Uri, + ): Promise { + try { + await vscode.workspace.fs.delete(sessionFilePath); + } catch { + // We don't care about any reasons for it to fail. + } + } + + private async waitForSessionFile( + cancellationToken: vscode.CancellationToken, + ): Promise { + const numOfTries = // We sleep for 1/5 of a second each try + 5 * this.sessionSettings.developer.waitForSessionFileTimeoutSeconds; + const warnAt = numOfTries - 5 * 30; // Warn at 30 seconds + + // Check every second. + this.logger.writeDebug( + `Waiting for session file: ${this.sessionFilePath}`, + ); + for (let i = numOfTries; i > 0; i--) { + if (cancellationToken.isCancellationRequested) { + this.logger.writeWarning( + "Canceled while waiting for session file.", + ); + return undefined; + } + + if (this.consoleTerminal === undefined) { + this.logger.writeError("Extension Terminal is undefined."); + return undefined; + } + + if (await utils.checkIfFileExists(this.sessionFilePath)) { + this.logger.writeDebug("Session file found."); + return await this.readSessionFile(this.sessionFilePath); + } + + if (warnAt === i) { + void this.logger.writeAndShowWarning( + "Loading the PowerShell extension is taking longer than expected. If you're using privilege enforcement software, this can affect start up performance.", + ); + } + + // Wait 1/5 of a second and try again + await utils.sleep(200); + } + + this.logger.writeError("Timed out waiting for session file!"); + return undefined; + } + + private onTerminalClose(terminal: vscode.Terminal): void { + if (terminal !== this.consoleTerminal) { + return; + } + + this.logger.writeWarning( + `PowerShell process terminated or Extension Terminal was closed, PID: ${this.pid}`, + ); + this.dispose(); + } +} diff --git a/src/session.ts b/src/session.ts new file mode 100644 index 0000000000..df8fd9fbe9 --- /dev/null +++ b/src/session.ts @@ -0,0 +1,1441 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import net = require("net"); +import path = require("path"); +import vscode = require("vscode"); +import TelemetryReporter, { + type TelemetryEventMeasurements, + type TelemetryEventProperties, +} from "@vscode/extension-telemetry"; +import { Message } from "vscode-jsonrpc"; +import { + type ILogger, + LanguageClientOutputChannelAdapter, + LspTraceParser, + PsesParser, +} from "./logging"; +import { PowerShellProcess } from "./process"; +import { + Settings, + changeSetting, + getEffectiveConfigurationTarget, + getSettings, + validateCwdSetting, +} from "./settings"; +import utils = require("./utils"); + +import { + CloseAction, + type CloseHandlerResult, + DocumentSelector, + ErrorAction, + type ErrorHandlerResult, + type LanguageClientOptions, + type Middleware, + NotificationType, + RequestType0, + type ResolveCodeLensSignature, + RevealOutputChannelOn, +} from "vscode-languageclient"; +import { LanguageClient, type StreamInfo } from "vscode-languageclient/node"; + +import { SemVer, satisfies } from "semver"; +import { UpdatePowerShell } from "./features/UpdatePowerShell"; +import { LanguageClientConsumer } from "./languageClientConsumer"; +import { + type IPlatformDetails, + type IPowerShellExeDetails, + OperatingSystem, + PowerShellExeFinder, + getPlatformDetails, +} from "./platform"; + +enum SessionStatus { + NotStarted = "Not Started", + Starting = "Starting", + Running = "Running", + Busy = "Busy", + Stopping = "Stopping", + Failed = "Failed", +} + +export enum RunspaceType { + Local, + Process, + Remote, +} +export interface IEditorServicesSessionDetails { + status: string; + reason: string; + powerShellVersion: string; + channel: string; + languageServicePort: number; + debugServicePort: number; + languageServicePipeName: string; + debugServicePipeName: string; +} + +export interface IPowerShellVersionDetails { + version: string; + edition: string; + commit: string; + architecture: string; +} + +export type IReadSessionFileCallback = ( + details: IEditorServicesSessionDetails, +) => void; + +export const SendKeyPressNotificationType = new NotificationType( + "powerShell/sendKeyPress", +); + +export const ExecutionBusyStatusNotificationType = + new NotificationType("powerShell/executionBusyStatus"); + +export const PowerShellVersionRequestType = new RequestType0< + IPowerShellVersionDetails, + void +>("powerShell/getVersion"); + +export class SessionManager implements Middleware { + public HostName: string; + public DisplayName: string; + public HostVersion: string; + public Publisher: string; + public PowerShellExeDetails: IPowerShellExeDetails | undefined; + private readonly ShowSessionMenuCommandName = "PowerShell.ShowSessionMenu"; + private debugEventHandler: vscode.Disposable | undefined; + private debugSessionProcess: PowerShellProcess | undefined; + private languageClient: LanguageClient | undefined; + private languageClientConsumers: LanguageClientConsumer[] = []; + private languageServerProcess: PowerShellProcess | undefined; + private languageStatusItem: vscode.LanguageStatusItem; + private platformDetails: IPlatformDetails; + private registeredCommands: vscode.Disposable[] = []; + private registeredHandlers: vscode.Disposable[] = []; + private sessionDetails: IEditorServicesSessionDetails | undefined; + private sessionsFolder: vscode.Uri; + private sessionStatus: SessionStatus = SessionStatus.NotStarted; + private shellIntegrationEnabled = false; + private startCancellationTokenSource: + | vscode.CancellationTokenSource + | undefined; + private suppressRestartPrompt = false; + private versionDetails: IPowerShellVersionDetails | undefined; + private traceLogLevelHandler?: vscode.Disposable; + + constructor( + private extensionContext: vscode.ExtensionContext, + private sessionSettings: Settings, + private logger: ILogger, + private documentSelector: DocumentSelector, + hostName: string, + displayName: string, + hostVersion: string, + publisher: string, + private telemetryReporter: TelemetryReporter, + ) { + // Create the language status item + this.languageStatusItem = this.createStatusBarItem(); + // We have to override the scheme because it defaults to + // 'vscode-userdata' which breaks UNC paths. + this.sessionsFolder = vscode.Uri.joinPath( + extensionContext.globalStorageUri.with({ scheme: "file" }), + "sessions", + ); + + this.platformDetails = getPlatformDetails(); + this.HostName = hostName; + this.DisplayName = displayName; + this.HostVersion = hostVersion; + this.Publisher = publisher; + + const osBitness = this.platformDetails.isOS64Bit ? "64-bit" : "32-bit"; + const procBitness = this.platformDetails.isProcess64Bit + ? "64-bit" + : "32-bit"; + + this.logger.write( + `Visual Studio Code: v${vscode.version} ${procBitness}` + + ` on ${OperatingSystem[this.platformDetails.operatingSystem]} ${osBitness}`, + `${this.DisplayName} Extension: v${this.HostVersion}`, + ); + + // Fix the host version so that PowerShell can consume it. + // This is needed when the extension uses a prerelease + // version string like 0.9.1-insiders-1234. + this.HostVersion = this.HostVersion.split("-")[0]; + + this.registerCommands(); + } + + public async dispose(): Promise { + await this.stop(); // A whole lot of disposals. + + this.languageStatusItem.dispose(); + + for (const handler of this.registeredHandlers) { + handler.dispose(); + } + + for (const command of this.registeredCommands) { + command.dispose(); + } + } + + // The `exeNameOverride` is used by `restartSession` to override ANY other setting. + // We've made this function idempotent, so it can used to ensure the session has started. + public async start(): Promise { + switch (this.sessionStatus) { + case SessionStatus.NotStarted: + // Go ahead and start. + break; + case SessionStatus.Starting: + // A simple lock because this function isn't re-entrant. + this.logger.writeWarning("Re-entered 'start' so waiting..."); + await this.waitWhileStarting(); + return; + case SessionStatus.Running: + // We're started, just return. + this.logger.writeDebug("Already started."); + return; + case SessionStatus.Busy: + // We're started but busy so notify and return. + // TODO: Make a proper notification for this and when IntelliSense is blocked. + this.logger.write( + "The Extension Terminal is currently busy, please wait for your task to finish!", + ); + return; + case SessionStatus.Stopping: + // Wait until done stopping, then start. + this.logger.writeDebug("Still stopping."); + await this.waitWhileStopping(); + break; + case SessionStatus.Failed: + // Try to start again. + this.logger.writeDebug("Previously failed, starting again."); + break; + } + + // This status needs to be set immediately so the above check works + this.setSessionStatus("Starting...", SessionStatus.Starting); + + this.startCancellationTokenSource = + new vscode.CancellationTokenSource(); + const cancellationToken = this.startCancellationTokenSource.token; + + // Create a folder for the session files. + await vscode.workspace.fs.createDirectory(this.sessionsFolder); + + // Migrate things. + await this.migrateWhitespaceAroundPipeSetting(); + + // Update non-PowerShell settings. + this.shellIntegrationEnabled = + vscode.workspace + .getConfiguration("terminal.integrated.shellIntegration") + .get("enabled") ?? false; + + // Find the PowerShell executable to use for the server. + this.PowerShellExeDetails = await this.findPowerShell(); + + if (this.PowerShellExeDetails === undefined) { + const message = + "Unable to find PowerShell!" + + " Do you have it installed?" + + " You can also configure custom installations" + + " with the 'powershell.powerShellAdditionalExePaths' setting."; + void this.setSessionFailedGetPowerShell(message); + return; + } + + // Refresh the status with the found executable details. + this.refreshSessionStatus(); + this.logger.write( + `Starting '${this.PowerShellExeDetails.displayName}' at: ${this.PowerShellExeDetails.exePath}`, + ); + + // Start the server. + this.languageServerProcess = await this.startLanguageServerProcess( + this.PowerShellExeDetails, + cancellationToken, + ); + + // Check that we got session details and that they had a "started" status. + if ( + this.sessionDetails === undefined || + !this.sessionStarted(this.sessionDetails) + ) { + if (!cancellationToken.isCancellationRequested) { + // If it failed but we didn't cancel it, handle the common reasons. + await this.handleFailedProcess(this.languageServerProcess); + } + this.languageServerProcess.dispose(); + this.languageServerProcess = undefined; + return; + } + + // If we got good session details from the server, try to connect to it. + this.languageClient = await this.startLanguageClient( + this.sessionDetails, + ); + + if (this.languageClient.isRunning()) { + this.versionDetails = await this.getVersionDetails(); + if (this.versionDetails === undefined) { + void this.setSessionFailedOpenBug( + "Unable to get version details!", + ); + return; + } + + this.logger.write( + `Started PowerShell v${this.versionDetails.version}.`, + ); + this.setSessionRunningStatus(); // Yay, we made it! + + await this.writePidIfInDevMode(this.languageServerProcess); + + // Fire and forget the updater. + const updater = new UpdatePowerShell( + this.sessionSettings, + this.logger, + this.versionDetails, + ); + void updater.checkForUpdate(); + } else { + void this.setSessionFailedOpenBug("Never finished startup!"); + } + } + + private async stop(): Promise { + this.setSessionStatus("Stopping...", SessionStatus.Stopping); + // Cancel start-up if we're still waiting. + this.startCancellationTokenSource?.cancel(); + + // Stop and dispose the language client. + try { + // If the stop fails, so will the dispose, I think this is a bug in + // the client library. + await this.languageClient?.stop(2000); + await this.languageClient?.dispose(); + } catch (err) { + this.logger.writeError( + `Error occurred while stopping language client:\n${err}`, + ); + } + + this.languageClient = undefined; + + // Stop and dispose the PowerShell process(es). + this.debugSessionProcess?.dispose(); + this.debugSessionProcess = undefined; + this.debugEventHandler?.dispose(); + this.debugEventHandler = undefined; + + this.languageServerProcess?.dispose(); + this.languageServerProcess = undefined; + + // Clean up state to start again. + this.startCancellationTokenSource?.dispose(); + this.startCancellationTokenSource = undefined; + this.sessionDetails = undefined; + this.traceLogLevelHandler?.dispose(); + this.traceLogLevelHandler = undefined; + + this.setSessionStatus("Not Started", SessionStatus.NotStarted); + } + + private async restartSession(exeNameOverride?: string): Promise { + this.logger.write("Restarting session..."); + await this.stop(); + + // Re-load the settings. + this.sessionSettings = getSettings(); + + if (exeNameOverride) { + // Reset the version and PowerShell details since we're launching a + // new executable. + this.logger.writeDebug( + `Starting with executable overriden to: ${exeNameOverride}`, + ); + this.sessionSettings.powerShellDefaultVersion = exeNameOverride; + this.versionDetails = undefined; + this.PowerShellExeDetails = undefined; + } + + await this.start(); + } + + /** In Development mode, write the PID to a file where the parent session can find it, to attach the dotnet debugger. */ + private async writePidIfInDevMode( + pwshProcess: PowerShellProcess, + ): Promise { + if ( + this.extensionContext.extensionMode !== + vscode.ExtensionMode.Development + ) { + return; + } + const parentSessionId = process.env.VSCODE_PARENT_SESSION_ID; + const pidFilePath = vscode.Uri.joinPath( + this.sessionsFolder, + `PSES-${parentSessionId}.pid`, + ); + + if (parentSessionId === undefined) { + return; + } + + const fs = vscode.workspace.fs; + const pid = (await pwshProcess.getPid())!.toString(); + await fs.writeFile(pidFilePath, Buffer.from(pid)); + const deletePidOnExit = pwshProcess.onExited(() => { + deletePidOnExit.dispose(); + fs.delete(pidFilePath, { useTrash: false }); + console.log(`Deleted PID file: ${pidFilePath}`); + }); + this.registeredCommands.push(deletePidOnExit); + this.extensionContext.subscriptions.push(deletePidOnExit); + } + + public getSessionDetails(): IEditorServicesSessionDetails | undefined { + // This is used by the debugger which should have already called `start`. + if (this.sessionDetails === undefined) { + void this.logger.writeAndShowError( + "PowerShell session unavailable for debugging!", + ); + } + return this.sessionDetails; + } + + public async getLanguageServerPid(): Promise { + if (this.languageServerProcess === undefined) { + void this.logger.writeAndShowError( + "PowerShell Extension Terminal unavailable!", + ); + } + return this.languageServerProcess?.getPid(); + } + + public getPowerShellVersionDetails(): + | IPowerShellVersionDetails + | undefined { + return this.versionDetails; + } + + private getNewSessionFilePath(): vscode.Uri { + const uniqueId: number = Math.floor(100000 + Math.random() * 900000); + return vscode.Uri.joinPath( + this.sessionsFolder, + `PSES-VSCode-${process.env.VSCODE_PID}-${uniqueId}.json`, + ); + } + + public setLanguageClientConsumers( + languageClientConsumers: LanguageClientConsumer[], + ): void { + this.languageClientConsumers = languageClientConsumers; + } + + public async createDebugSessionProcess( + settings: Settings, + powershellExeName?: string, + ): Promise { + // NOTE: We only support one temporary Extension Terminal at a time. To + // support more, we need to track each separately, and tie the session + // for the event handler to the right process (and dispose of the event + // handler when the process is disposed). + this.debugSessionProcess?.dispose(); + this.debugEventHandler?.dispose(); + if (this.PowerShellExeDetails === undefined) { + return Promise.reject( + new Error("Required PowerShellExeDetails undefined!"), + ); + } + + const debugPowerShellExeDetails = + powershellExeName === undefined + ? this.PowerShellExeDetails + : ((await this.findPowerShell(powershellExeName)) ?? + this.PowerShellExeDetails); + + // TODO: It might not be totally necessary to update the session + // settings here, but I don't want to accidentally change this behavior + // just yet. Working on getting things to be more idempotent! + this.sessionSettings = settings; + + const bundledModulesPath = await this.getBundledModulesPath(); + this.debugSessionProcess = new PowerShellProcess( + debugPowerShellExeDetails.exePath, + bundledModulesPath, + true, + false, + this.logger, + this.extensionContext.logUri, + this.getEditorServicesArgs( + bundledModulesPath, + this.PowerShellExeDetails, + ) + "-DebugServiceOnly ", + this.getNewSessionFilePath(), + this.sessionSettings, + ); + + // Similar to the regular Extension Terminal, we need to send a key + // press to the process spawned for temporary Extension Terminals when + // the server requests a cancellation os Console.ReadKey. + this.debugEventHandler = + vscode.debug.onDidReceiveDebugSessionCustomEvent((e) => { + if (e.event === "powerShell/sendKeyPress") { + this.debugSessionProcess?.sendKeyPress(); + } + }); + + return this.debugSessionProcess; + } + + public async waitUntilStarted(): Promise { + while (this.sessionStatus !== SessionStatus.Running) { + await utils.sleep(200); + } + } + + // TODO: Is this used by the magic of "Middleware" in the client library? + public resolveCodeLens( + codeLens: vscode.CodeLens, + token: vscode.CancellationToken, + next: ResolveCodeLensSignature, + ): vscode.ProviderResult { + const resolvedCodeLens = next(codeLens, token); + const resolveFunc = ( + codeLensToFix: vscode.CodeLens, + ): vscode.CodeLens => { + if ( + codeLensToFix.command?.command === + "editor.action.showReferences" + ) { + const oldArgs = codeLensToFix.command.arguments; + if (oldArgs === undefined || oldArgs.length < 3) { + this.logger.writeError( + "Code Lens arguments were malformed!", + ); + return codeLensToFix; + } + + // Our JSON objects don't get handled correctly by + // VS Code's built in editor.action.showReferences + // command so we need to convert them into the + // appropriate types to send them as command + // arguments. + + codeLensToFix.command.arguments = [ + vscode.Uri.parse(oldArgs[0]), + new vscode.Position(oldArgs[1].line, oldArgs[1].character), + oldArgs[2].map( + (position: { + uri: string; + range: { + start: { line: number; character: number }; + end: { line: number; character: number }; + }; + }) => { + return new vscode.Location( + vscode.Uri.parse(position.uri), + new vscode.Range( + position.range.start.line, + position.range.start.character, + position.range.end.line, + position.range.end.character, + ), + ); + }, + ), + ]; + } + + return codeLensToFix; + }; + + // TODO: This makes zero sense, but appears to be "working" and copied by others per https://github.com/microsoft/vscode-languageserver-node/issues/495. Thing is, ESLint says these conditionals are always truthy. + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if ((resolvedCodeLens as Thenable).then) { + return (resolvedCodeLens as Thenable).then( + resolveFunc, + ); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + } else if (resolvedCodeLens as vscode.CodeLens) { + return resolveFunc(resolvedCodeLens as vscode.CodeLens); + } + + return resolvedCodeLens; + } + + // TODO: Remove this migration code. Move old setting + // codeFormatting.whitespaceAroundPipe to new setting + // codeFormatting.addWhitespaceAroundPipe. + private async migrateWhitespaceAroundPipeSetting(): Promise { + const configuration = vscode.workspace.getConfiguration( + utils.PowerShellLanguageId, + ); + const deprecatedSetting = "codeFormatting.whitespaceAroundPipe"; + const newSetting = "codeFormatting.addWhitespaceAroundPipe"; + const configurationTargetOfNewSetting = + getEffectiveConfigurationTarget(newSetting); + const configurationTargetOfOldSetting = + getEffectiveConfigurationTarget(deprecatedSetting); + if ( + configurationTargetOfOldSetting !== undefined && + configurationTargetOfNewSetting === undefined + ) { + this.logger.writeWarning( + "Deprecated setting: whitespaceAroundPipe", + ); + const value = configuration.get( + deprecatedSetting, + configurationTargetOfOldSetting, + ); + await changeSetting( + newSetting, + value, + configurationTargetOfOldSetting, + this.logger, + ); + await changeSetting( + deprecatedSetting, + undefined, + configurationTargetOfOldSetting, + this.logger, + ); + } + } + + /** There are some changes we cannot "hot" set, so these require a restart of the session */ + private async restartOnCriticalConfigChange( + changeEvent: vscode.ConfigurationChangeEvent, + ): Promise { + if (this.suppressRestartPrompt) { + return; + } + if (this.sessionStatus !== SessionStatus.Running) { + return; + } + + // Restart not needed if shell integration is enabled but the shell is backgrounded. + const settings = getSettings(); + if ( + changeEvent.affectsConfiguration( + "terminal.integrated.shellIntegration.enabled", + ) + ) { + const shellIntegrationEnabled = + vscode.workspace + .getConfiguration("terminal.integrated.shellIntegration") + .get("enabled") ?? false; + if ( + shellIntegrationEnabled && + !settings.integratedConsole.startInBackground + ) { + return this.restartWithPrompt(); + } + } + + // Early return if the change doesn't affect the PowerShell extension settings from this point forward + if (!changeEvent.affectsConfiguration("powershell")) { + return; + } + + // Detect any setting changes that would affect the session. + const coldRestartSettingNames = [ + "developer.traceLsp", + "developer.traceDap", + "developer.editorServicesLogLevel", + ]; + for (const settingName of coldRestartSettingNames) { + if ( + changeEvent.affectsConfiguration( + "powershell" + "." + settingName, + ) + ) { + return this.restartWithPrompt(); + } + } + + // TODO: Migrate these to affectsConfiguration style above + if ( + settings.cwd !== this.sessionSettings.cwd || + settings.powerShellDefaultVersion !== + this.sessionSettings.powerShellDefaultVersion || + settings.developer.bundledModulesPath !== + this.sessionSettings.developer.bundledModulesPath || + settings.developer.editorServicesWaitForDebugger !== + this.sessionSettings.developer.editorServicesWaitForDebugger || + settings.developer.setExecutionPolicy !== + this.sessionSettings.developer.setExecutionPolicy || + settings.integratedConsole.useLegacyReadLine !== + this.sessionSettings.integratedConsole.useLegacyReadLine || + settings.integratedConsole.startInBackground !== + this.sessionSettings.integratedConsole.startInBackground || + settings.integratedConsole.startLocation !== + this.sessionSettings.integratedConsole.startLocation + ) { + return this.restartWithPrompt(); + } + } + + private async restartWithPrompt(): Promise { + this.logger.writeDebug("Settings changed, prompting to restart..."); + const response = await vscode.window.showInformationMessage( + "The PowerShell runtime configuration has changed, would you like to start a new session?", + "Yes", + "No", + ); + + if (response === "Yes") { + await this.restartSession(); + } + } + + private registerCommands(): void { + this.registeredCommands = [ + vscode.commands.registerCommand( + "PowerShell.RestartSession", + async () => { + await this.restartSession(); + }, + ), + vscode.commands.registerCommand( + this.ShowSessionMenuCommandName, + async () => { + await this.showSessionMenu(); + }, + ), + vscode.workspace.onDidChangeConfiguration((e) => + this.restartOnCriticalConfigChange(e), + ), + vscode.commands.registerCommand( + "PowerShell.ShowSessionConsole", + (isExecute?: boolean) => { + this.showSessionTerminal(isExecute); + }, + ), + ]; + } + + private async findPowerShell( + wantedName?: string, + ): Promise { + this.logger.writeDebug("Finding PowerShell..."); + const powershellExeFinder = new PowerShellExeFinder( + this.platformDetails, + this.sessionSettings.powerShellAdditionalExePaths, + this.logger, + ); + + let foundPowerShell: IPowerShellExeDetails | undefined; + try { + let defaultPowerShell: IPowerShellExeDetails | undefined; + wantedName ??= this.sessionSettings.powerShellDefaultVersion; + if (wantedName !== "") { + for await (const details of powershellExeFinder.enumeratePowerShellInstallations()) { + // Need to compare names case-insensitively, from https://stackoverflow.com/a/2140723 + if ( + wantedName.localeCompare( + details.displayName, + undefined, + { sensitivity: "accent" }, + ) === 0 + ) { + defaultPowerShell = details; + break; + } + } + } + foundPowerShell = + defaultPowerShell ?? + (await powershellExeFinder.getFirstAvailablePowerShellInstallation()); + if ( + wantedName !== "" && + defaultPowerShell === undefined && + foundPowerShell !== undefined + ) { + void this.logger.writeAndShowWarning( + `The 'powerShellDefaultVersion' setting was '${wantedName}' but this was not found!` + + ` Instead using first available installation '${foundPowerShell.displayName}' at '${foundPowerShell.exePath}'!`, + ); + } + } catch (err) { + this.logger.writeError( + `Error occurred while searching for a PowerShell executable:\n${err}`, + ); + } + + return foundPowerShell; + } + + private async startLanguageServerProcess( + powerShellExeDetails: IPowerShellExeDetails, + cancellationToken: vscode.CancellationToken, + ): Promise { + const bundledModulesPath = await this.getBundledModulesPath(); + + // Dispose any stale terminals from previous killed sessions. + PowerShellProcess.cleanUpTerminals(); + const languageServerProcess = new PowerShellProcess( + powerShellExeDetails.exePath, + bundledModulesPath, + false, + this.shellIntegrationEnabled, + this.logger, + this.extensionContext.logUri, + this.getEditorServicesArgs( + bundledModulesPath, + powerShellExeDetails, + ), + this.getNewSessionFilePath(), + this.sessionSettings, + this.extensionContext.extensionMode == + vscode.ExtensionMode.Development, + ); + + languageServerProcess.onExited(() => { + LanguageClientConsumer.onLanguageClientExited(); + + if ( + this.sessionStatus === SessionStatus.Running || + this.sessionStatus === SessionStatus.Busy + ) { + this.setSessionStatus("Session Exited!", SessionStatus.Failed); + void this.promptForRestart(); + } + }); + + this.sessionDetails = + await languageServerProcess.start(cancellationToken); + + return languageServerProcess; + } + + // The process failed to start, so check for common user errors (generally + // out-of-support versions of PowerShell). + private async handleFailedProcess( + powerShellProcess: PowerShellProcess, + ): Promise { + const version = await powerShellProcess.getVersionCli(); + let shouldUpdate = true; + + if (satisfies(version, "<5.1.0")) { + void this.setSessionFailedGetPowerShell( + `PowerShell v${version} is not supported, please update!`, + ); + } else if (satisfies(version, ">=5.1.0 <6.0.0")) { + void this.setSessionFailedGetPowerShell( + "It looks like you're trying to use Windows PowerShell, which is supported on a best-effort basis. Can you try PowerShell 7?", + ); + } else if (satisfies(version, ">=6.0.0 <7.4.0")) { + void this.setSessionFailedGetPowerShell( + `PowerShell v${version} has reached end-of-support, please update!`, + ); + } else { + shouldUpdate = false; + void this.setSessionFailedOpenBug( + "PowerShell Language Server process didn't start!", + ); + } + + if (shouldUpdate) { + // Run the update notifier since it won't run later as we failed + // to start, but we have enough details to do so now. + const versionDetails: IPowerShellVersionDetails = { + version: version, + edition: "", // Unused by UpdatePowerShell + commit: version, // Actually used by UpdatePowerShell + architecture: process.arch, // Best guess based off Code's architecture + }; + const updater = new UpdatePowerShell( + this.sessionSettings, + this.logger, + versionDetails, + ); + void updater.checkForUpdate(); + } + } + + private sessionStarted( + sessionDetails: IEditorServicesSessionDetails, + ): boolean { + this.logger.writeDebug( + `Session details: ${JSON.stringify(sessionDetails, undefined, 2)}`, + ); + if (sessionDetails.status === "started") { + // Successful server start with a session file + return true; + } + if (sessionDetails.status === "failed") { + // Server started but indicated it failed + if (sessionDetails.reason === "powerShellVersion") { + void this.setSessionFailedGetPowerShell( + `PowerShell ${sessionDetails.powerShellVersion} is not supported, please update!`, + ); + } else if (sessionDetails.reason === "dotNetVersion") { + // Only applies to PowerShell 5.1 + void this.setSessionFailedGetDotNet( + ".NET Framework is out-of-date, please install at least 4.8!", + ); + } else { + void this.setSessionFailedOpenBug( + `PowerShell could not be started for an unknown reason: ${sessionDetails.reason}`, + ); + } + } else { + void this.setSessionFailedOpenBug( + `PowerShell could not be started with an unknown status: ${sessionDetails.status}, and reason: ${sessionDetails.reason}`, + ); + } + return false; + } + + private async startLanguageClient( + sessionDetails: IEditorServicesSessionDetails, + ): Promise { + this.logger.writeDebug("Connecting to language service..."); + const connectFunc = (): Promise => { + return new Promise((resolve, _reject) => { + const socket = net.connect( + sessionDetails.languageServicePipeName, + ); + socket.on("connect", () => { + this.logger.writeDebug("Language service connected."); + resolve({ writer: socket, reader: socket }); + }); + }); + }; + + const clientOptions: LanguageClientOptions = { + documentSelector: this.documentSelector, + synchronize: { + // TODO: This is deprecated and they should be pulled by the server. + // backend uses "files" and "search" to ignore references. + configurationSection: [ + utils.PowerShellLanguageId, + "files", + "search", + ], + // TODO: fileEvents: vscode.workspace.createFileSystemWatcher('**/.eslintrc') + }, + // NOTE: Some settings are only applicable on startup, so we send them during initialization. + // When Terminal Shell Integration is enabled, we pass the path to the script that the server should execute. + // Passing an empty string implies integration is disabled. + initializationOptions: { + enableProfileLoading: this.sessionSettings.enableProfileLoading, + initialWorkingDirectory: await validateCwdSetting(this.logger), + shellIntegrationScript: this.shellIntegrationEnabled + ? utils.ShellIntegrationScript + : "", + }, + errorHandler: { + // Override the default error handler to prevent it from + // closing the LanguageClient incorrectly when the socket + // hangs up (ECONNRESET errors). + error: ( + _error: Error, + _message: Message, + _count: number, + ): ErrorHandlerResult => { + // TODO: Is there any error worth terminating on? + this.logger.writeError( + `${_error.name}: ${_error.message} ${_error.cause}`, + ); + return { action: ErrorAction.Continue }; + }, + closed: (): CloseHandlerResult => { + this.logger.write("Language service connection closed."); + // We have our own restart experience + return { + action: CloseAction.DoNotRestart, + message: + "Connection to PowerShell Editor Services (the Extension Terminal) was closed. See below prompt to restart!", + }; + }, + }, + middleware: this, + traceOutputChannel: new LanguageClientOutputChannelAdapter( + "PowerShell: Trace LSP", + LspTraceParser, + ), + // This is named the same as the Client log to merge the logs, but will be handled and disposed separately. + outputChannel: new LanguageClientOutputChannelAdapter( + "PowerShell", + PsesParser, + ), + revealOutputChannelOn: RevealOutputChannelOn.Never, + }; + + const languageClient = new LanguageClient( + "powershell", + "PowerShell Editor Services Client", + connectFunc, + clientOptions, + ); + + // This enables handling Semantic Highlighting messages in PowerShell Editor Services + // TODO: We should only turn this on in preview. + languageClient.registerProposedFeatures(); + + // NOTE: We don't currently send any events from PSES, but may again in + // the future so we're leaving this side wired up. + languageClient.onTelemetry((event) => { + const eventName: string = event.eventName ?? "PSESEvent"; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data: any = event.data ?? event; + this.sendTelemetryEvent(eventName, data); + }); + + // Send the new LanguageClient to extension features + // so that they can register their message handlers + // before the connection is established. + for (const consumer of this.languageClientConsumers) { + consumer.onLanguageClientSet(languageClient); + } + + this.registeredHandlers = [ + // NOTE: This fixes a quirk where PSES has a thread stuck on + // Console.ReadKey, since it's not cancellable. On + // "cancellation" the server asks us to send pretend to + // press a key, thus mitigating all the quirk. + languageClient.onNotification(SendKeyPressNotificationType, () => { + this.languageServerProcess?.sendKeyPress(); + }), + + languageClient.onNotification( + ExecutionBusyStatusNotificationType, + (isBusy: boolean) => { + if (isBusy) { + this.setSessionBusyStatus(); + } else { + this.setSessionRunningStatus(); + } + }, + ), + ]; + + try { + await languageClient.start(); + LanguageClientConsumer.onLanguageClientStarted(languageClient); + } catch (err) { + void this.setSessionFailedOpenBug( + "Language client failed to start: " + + (err instanceof Error ? err.message : "unknown"), + ); + } + + return languageClient; + } + + private async getBundledModulesPath(): Promise { + // Because the extension is always at `/out/main.js` + let bundledModulesPath = path.resolve(__dirname, "../modules"); + + if ( + this.extensionContext.extensionMode === + vscode.ExtensionMode.Development + ) { + const devBundledModulesPath = path.resolve( + __dirname, + this.sessionSettings.developer.bundledModulesPath, + ); + + // Make sure the module's bin path exists + if (await utils.checkIfDirectoryExists(devBundledModulesPath)) { + bundledModulesPath = devBundledModulesPath; + } else { + void this.logger.writeAndShowWarning( + "In development mode but PowerShellEditorServices dev module path cannot be " + + `found (or has not been built yet): ${devBundledModulesPath}\n`, + ); + } + } + + return bundledModulesPath; + } + + private getEditorServicesArgs( + bundledModulesPath: string, + powerShellExeDetails: IPowerShellExeDetails, + ): string { + let editorServicesArgs = + "-HostName 'Visual Studio Code Host' " + + "-HostProfileId 'Microsoft.VSCode' " + + `-HostVersion '${this.HostVersion}' ` + + `-BundledModulesPath '${utils.escapeSingleQuotes(bundledModulesPath)}' ` + + "-EnableConsoleRepl "; + + if (this.sessionSettings.integratedConsole.suppressStartupBanner) { + editorServicesArgs += "-StartupBanner '' "; + } else if ( + utils.isWindows && + !powerShellExeDetails.supportsProperArguments + ) { + // NOTE: On Windows we don't Base64 encode the startup command + // because it annoys some poorly implemented anti-virus scanners. + // Unfortunately this means that for some installs of PowerShell + // (such as through the `dotnet` package manager), we can't include + // a multi-line startup banner as the quotes break the command. + editorServicesArgs += `-StartupBanner '${this.DisplayName} Extension v${this.HostVersion}' `; + } else { + const startupBanner = `${this.DisplayName} Extension v${this.HostVersion} +Copyright (c) Microsoft Corporation. + +https://aka.ms/vscode-powershell +Type 'help' to get help. +`; + editorServicesArgs += `-StartupBanner "${startupBanner}" `; + } + + // We guard this here too out of an abundance of precaution. + if ( + this.sessionSettings.developer.editorServicesWaitForDebugger && + this.extensionContext.extensionMode === + vscode.ExtensionMode.Development + ) { + editorServicesArgs += "-WaitForDebugger "; + } + const logLevel = vscode.workspace + .getConfiguration("powershell.developer") + .get("editorServicesLogLevel"); + editorServicesArgs += `-LogLevel '${logLevel}' `; + + return editorServicesArgs; + } + + private async getVersionDetails(): Promise< + IPowerShellVersionDetails | undefined + > { + // Take one minute to get version details, otherwise cancel and fail. + const timeout = new vscode.CancellationTokenSource(); + setTimeout(() => { + timeout.cancel(); + }, 60 * 1000); + + const versionDetails = await this.languageClient?.sendRequest( + PowerShellVersionRequestType, + timeout.token, + ); + + // This is pretty much the only telemetry event we care about. + // TODO: We actually could send this earlier from PSES itself. + this.sendTelemetryEvent("powershellVersionCheck", { + powershellVersion: versionDetails?.version ?? "unknown", + }); + + return versionDetails; + } + + private async promptForRestart(): Promise { + await this.logger.writeAndShowErrorWithActions( + "The PowerShell Extension Terminal has stopped, would you like to restart it? IntelliSense and other features will not work without it!", + [ + { + prompt: "Yes", + action: async (): Promise => { + await this.restartSession(); + }, + }, + { + prompt: "No", + action: undefined, + }, + ], + ); + } + + private sendTelemetryEvent( + eventName: string, + properties?: TelemetryEventProperties, + measures?: TelemetryEventMeasurements, + ): void { + if ( + this.extensionContext.extensionMode === + vscode.ExtensionMode.Production + ) { + this.telemetryReporter.sendTelemetryEvent( + eventName, + properties, + measures, + ); + } + } + + private createStatusBarItem(): vscode.LanguageStatusItem { + const statusTitle = "Show PowerShell Session Menu"; + const languageStatusItem = vscode.languages.createLanguageStatusItem( + "powershell", + this.documentSelector, + ); + languageStatusItem.command = { + title: statusTitle, + command: this.ShowSessionMenuCommandName, + }; + languageStatusItem.text = "$(terminal-powershell)"; + languageStatusItem.detail = "PowerShell"; + return languageStatusItem; + } + + private async waitWhileStarting(): Promise { + while (this.sessionStatus === SessionStatus.Starting) { + if ( + this.startCancellationTokenSource?.token.isCancellationRequested + ) { + return; + } + await utils.sleep(200); + } + } + + private async waitWhileStopping(): Promise { + while (this.sessionStatus === SessionStatus.Stopping) { + await utils.sleep(200); + } + } + + private setSessionStatus(detail: string, status: SessionStatus): void { + this.logger.writeDebug( + `Session status changing from '${this.sessionStatus}' to '${status}'.`, + ); + this.sessionStatus = status; + this.languageStatusItem.text = "$(terminal-powershell)"; + this.languageStatusItem.detail = "PowerShell"; + + if (this.versionDetails !== undefined) { + const semver = new SemVer(this.versionDetails.version); + this.languageStatusItem.text += ` ${semver.major}.${semver.minor}`; + this.languageStatusItem.detail += ` ${this.versionDetails.commit} (${this.versionDetails.architecture.toLowerCase()})`; + } else if (this.PowerShellExeDetails?.displayName) { + // When it hasn't started yet. + this.languageStatusItem.text += ` ${this.PowerShellExeDetails.displayName}`; + this.languageStatusItem.detail += ` at '${this.PowerShellExeDetails.exePath}'`; + } else if (this.sessionSettings.powerShellDefaultVersion) { + // When it hasn't been found yet. + this.languageStatusItem.text += ` ${this.sessionSettings.powerShellDefaultVersion}`; + this.languageStatusItem.detail = `Looking for '${this.sessionSettings.powerShellDefaultVersion}'...`; + } + + if (detail) { + this.languageStatusItem.detail += ": " + detail; + } + + switch (status) { + case SessionStatus.Running: + case SessionStatus.NotStarted: + this.languageStatusItem.busy = false; + this.languageStatusItem.severity = + vscode.LanguageStatusSeverity.Information; + break; + case SessionStatus.Busy: + this.languageStatusItem.busy = true; + this.languageStatusItem.severity = + vscode.LanguageStatusSeverity.Information; + break; + case SessionStatus.Starting: + case SessionStatus.Stopping: + this.languageStatusItem.busy = true; + this.languageStatusItem.severity = + vscode.LanguageStatusSeverity.Warning; + break; + case SessionStatus.Failed: + this.languageStatusItem.busy = false; + this.languageStatusItem.severity = + vscode.LanguageStatusSeverity.Error; + break; + } + } + + // Refreshes the Language Status Item details with ehe same status. + private refreshSessionStatus(): void { + this.setSessionStatus("", this.sessionStatus); + } + + private setSessionRunningStatus(): void { + this.setSessionStatus("", SessionStatus.Running); + } + + private setSessionBusyStatus(): void { + this.setSessionStatus("Executing...", SessionStatus.Busy); + } + + private async setSessionFailedOpenBug(message: string): Promise { + this.setSessionStatus("Startup Error!", SessionStatus.Failed); + await this.logger.writeAndShowErrorWithActions(message, [ + { + prompt: "Open an Issue", + action: async (): Promise => { + await vscode.commands.executeCommand( + "PowerShell.GenerateBugReport", + ); + }, + }, + ]); + } + + private async setSessionFailedGetPowerShell( + message: string, + ): Promise { + this.setSessionStatus("Startup Error!", SessionStatus.Failed); + await this.logger.writeAndShowErrorWithActions(message, [ + { + prompt: "Open PowerShell Install Documentation", + action: async (): Promise => { + await vscode.env.openExternal( + vscode.Uri.parse( + "https://aka.ms/get-powershell-vscode", + ), + ); + }, + }, + ]); + } + + private async setSessionFailedGetDotNet(message: string): Promise { + this.setSessionStatus("Startup Error!", SessionStatus.Failed); + await this.logger.writeAndShowErrorWithActions(message, [ + { + prompt: "Open .NET Framework Documentation", + action: async (): Promise => { + await vscode.env.openExternal( + vscode.Uri.parse( + "https://dotnet.microsoft.com/en-us/download/dotnet-framework", + ), + ); + }, + }, + ]); + } + + private async changePowerShellDefaultVersion( + exePath: IPowerShellExeDetails, + ): Promise { + this.suppressRestartPrompt = true; + try { + await changeSetting( + "powerShellDefaultVersion", + exePath.displayName, + true, + this.logger, + ); + } finally { + this.suppressRestartPrompt = false; + } + + // We pass in the display name so that we force the extension to use that version + // rather than pull from the settings. The issue we prevent here is when a + // workspace setting is defined which gets priority over user settings which + // is what the change above sets. + await this.restartSession(exePath.displayName); + } + + // Shows the temp debug terminal if it exists, otherwise the session terminal. + public showDebugTerminal(isExecute?: boolean): void { + if (this.debugSessionProcess) { + this.debugSessionProcess.showTerminal( + isExecute && + !this.sessionSettings.integratedConsole + .focusConsoleOnExecute, + ); + } else { + this.languageServerProcess?.showTerminal( + isExecute && + !this.sessionSettings.integratedConsole + .focusConsoleOnExecute, + ); + } + } + + // Always shows the session terminal. + private showSessionTerminal(isExecute?: boolean): void { + this.languageServerProcess?.showTerminal( + isExecute && + !this.sessionSettings.integratedConsole.focusConsoleOnExecute, + ); + } + + private async showSessionMenu(): Promise { + const powershellExeFinder = new PowerShellExeFinder( + this.platformDetails, + // We don't pull from session settings because we want them fresh! + getSettings().powerShellAdditionalExePaths, + this.logger, + ); + const availablePowerShellExes = + await powershellExeFinder.getAllAvailablePowerShellInstallations(); + + const powerShellItems = availablePowerShellExes + .filter( + (item) => + item.displayName !== this.PowerShellExeDetails?.displayName, + ) + .map((item) => { + return new SessionMenuItem( + `Switch to: ${item.displayName}`, + async () => { + await this.changePowerShellDefaultVersion(item); + }, + ); + }); + + const menuItems: SessionMenuItem[] = [ + new SessionMenuItem( + `Current session: ${this.PowerShellExeDetails?.displayName ?? "Unknown"} (click to show logs)`, + async () => { + await vscode.commands.executeCommand("PowerShell.ShowLogs"); + }, + ), + + // Add all of the different PowerShell options + ...powerShellItems, + + new SessionMenuItem("Restart current session", async () => { + // We pass in the display name so we guarantee that the session + // will be the same PowerShell. + if (this.PowerShellExeDetails) { + await this.restartSession( + this.PowerShellExeDetails.displayName, + ); + } else { + await this.restartSession(); + } + }), + + new SessionMenuItem("Open session logs folder", async () => { + await vscode.commands.executeCommand( + "PowerShell.OpenLogFolder", + ); + }), + + new SessionMenuItem( + "Modify list of additional PowerShell locations", + async () => { + await vscode.commands.executeCommand( + "workbench.action.openSettings", + "powerShellAdditionalExePaths", + ); + }, + ), + ]; + + const selectedItem = + await vscode.window.showQuickPick(menuItems); + await selectedItem?.callback(); + } +} + +class SessionMenuItem implements vscode.QuickPickItem { + public description: string | undefined; + + constructor( + public readonly label: string, + + // eslint-disable-next-line @typescript-eslint/no-empty-function + public readonly callback = async (): Promise => {}, + ) {} +} diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 0000000000..9664c10cf1 --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,420 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import vscode = require("vscode"); +import utils = require("./utils"); +import os = require("os"); +import untildify from "untildify"; +import type { ILogger } from "./logging"; +import path = require("path"); + +// TODO: Quite a few of these settings are unused in the client and instead +// exist just for the server. Those settings do not need to be represented in +// this class, as the LSP layers take care of communicating them. Frankly, this +// class is over-engineered and seems to have originally been created to avoid +// using vscode.workspace.getConfiguration() directly. It wasn't a bad idea to +// keep things organized so consistent...but it ended up failing in execution. +// Perhaps we just get rid of this entirely? + +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +class PartialSettings {} + +export class Settings extends PartialSettings { + powerShellAdditionalExePaths: PowerShellAdditionalExePathSettings = {}; + powerShellDefaultVersion = ""; + promptToUpdatePowerShell = true; + suppressAdditionalExeNotFoundWarning = false; + startAsLoginShell = new StartAsLoginShellSettings(); + startAutomatically = true; + enableProfileLoading = true; + helpCompletion = CommentType.BlockComment; + scriptAnalysis = new ScriptAnalysisSettings(); + debugging = new DebuggingSettings(); + developer = new DeveloperSettings(); + codeFormatting = new CodeFormattingSettings(); + integratedConsole = new IntegratedConsoleSettings(); + sideBar = new SideBarSettings(); + pester = new PesterSettings(); + buttons = new ButtonSettings(); + cwd = ""; // NOTE: use validateCwdSetting() instead of this directly! + enableReferencesCodeLens = true; + analyzeOpenDocumentsOnly = false; + // TODO: Add (deprecated) useX86Host (for testing) +} + +export enum CodeFormattingPreset { + Custom = "Custom", + Allman = "Allman", + OTBS = "OTBS", + Stroustrup = "Stroustrup", +} + +export enum PipelineIndentationStyle { + IncreaseIndentationForFirstPipeline = "IncreaseIndentationForFirstPipeline", + IncreaseIndentationAfterEveryPipeline = "IncreaseIndentationAfterEveryPipeline", + NoIndentation = "NoIndentation", + None = "None", +} + +export enum CommentType { + Disabled = "Disabled", + BlockComment = "BlockComment", + LineComment = "LineComment", +} + +export enum StartLocation { + Editor = "Editor", + Panel = "Panel", +} + +export enum ExecuteMode { + Call = "Call", + DotSource = "DotSource", +} + +export type PowerShellAdditionalExePathSettings = Record; + +class CodeFormattingSettings extends PartialSettings { + autoCorrectAliases = false; + avoidSemicolonsAsLineTerminators = false; + preset = CodeFormattingPreset.Custom; + openBraceOnSameLine = true; + newLineAfterOpenBrace = true; + newLineAfterCloseBrace = true; + pipelineIndentationStyle = PipelineIndentationStyle.NoIndentation; + whitespaceBeforeOpenBrace = true; + whitespaceBeforeOpenParen = true; + whitespaceAroundOperator = true; + whitespaceAfterSeparator = true; + whitespaceBetweenParameters = false; + whitespaceInsideBrace = true; + addWhitespaceAroundPipe = true; + trimWhitespaceAroundPipe = false; + ignoreOneLineBlock = true; + alignPropertyValuePairs = true; + useConstantStrings = false; + useCorrectCasing = false; +} + +class ScriptAnalysisSettings extends PartialSettings { + enable = true; + settingsPath = "PSScriptAnalyzerSettings.psd1"; +} + +class DebuggingSettings extends PartialSettings { + createTemporaryIntegratedConsole = false; + executeMode = ExecuteMode.DotSource; +} + +class DeveloperSettings extends PartialSettings { + featureFlags: string[] = []; + // From `/out/main.js` we go to the directory before and + // then into the other repo. + bundledModulesPath = "../../PowerShellEditorServices/module"; + editorServicesWaitForDebugger = false; + setExecutionPolicy = true; + waitForSessionFileTimeoutSeconds = 240; +} + +// We follow the same convention as VS Code - https://github.com/microsoft/vscode/blob/ff00badd955d6cfcb8eab5f25f3edc86b762f49f/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts#L105-L107 +// "Unlike on Linux, ~/.profile is not sourced when logging into a macOS session. This +// is the reason terminals on macOS typically run login shells by default which set up +// the environment. See http://unix.stackexchange.com/a/119675/115410" +class StartAsLoginShellSettings extends PartialSettings { + osx = true; + linux = false; +} + +class IntegratedConsoleSettings extends PartialSettings { + showOnStartup = true; + startInBackground = false; + focusConsoleOnExecute = true; + useLegacyReadLine = false; + forceClearScrollbackBuffer = false; + suppressStartupBanner = false; + startLocation = StartLocation.Panel; +} + +class SideBarSettings extends PartialSettings { + CommandExplorerVisibility = false; + CommandExplorerExcludeFilter: string[] = []; +} + +class PesterSettings extends PartialSettings { + useLegacyCodeLens = true; + outputVerbosity = "FromPreference"; + debugOutputVerbosity = "Diagnostic"; +} + +class ButtonSettings extends PartialSettings { + showRunButtons = true; + showPanelMovementButtons = false; +} + +// This is a recursive function which unpacks a WorkspaceConfiguration into our settings. +function getSetting( + key: string | undefined, + value: TSetting, + configuration: vscode.WorkspaceConfiguration, +): TSetting { + // Base case where we're looking at a primitive type (or our special record). + if (key !== undefined && !(value instanceof PartialSettings)) { + return configuration.get(key, value); + } + + // Otherwise we're looking at one of our interfaces and need to extract. + for (const property in value) { + const subKey = key !== undefined ? `${key}.${property}` : property; + value[property] = getSetting(subKey, value[property], configuration); + } + + return value; +} + +export function getSettings(): Settings { + const configuration: vscode.WorkspaceConfiguration = + vscode.workspace.getConfiguration(utils.PowerShellLanguageId); + + return getSetting(undefined, new Settings(), configuration); +} + +// Get the ConfigurationTarget (read: scope) of where the *effective* setting value comes from +export function getEffectiveConfigurationTarget( + settingName: string, +): vscode.ConfigurationTarget | undefined { + const configuration = vscode.workspace.getConfiguration( + utils.PowerShellLanguageId, + ); + const detail = configuration.inspect(settingName); + if (detail === undefined) { + return undefined; + } else if (typeof detail.workspaceFolderValue !== "undefined") { + return vscode.ConfigurationTarget.WorkspaceFolder; + } else if (typeof detail.workspaceValue !== "undefined") { + return vscode.ConfigurationTarget.Workspace; + } else if (typeof detail.globalValue !== "undefined") { + return vscode.ConfigurationTarget.Global; + } + return undefined; +} + +export async function changeSetting( + settingName: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + newValue: any, + configurationTarget: vscode.ConfigurationTarget | boolean | undefined, + logger: ILogger | undefined, +): Promise { + logger?.writeDebug( + `Changing '${settingName}' at scope '${configurationTarget}' to '${newValue}'.`, + ); + + try { + const configuration = vscode.workspace.getConfiguration( + utils.PowerShellLanguageId, + ); + await configuration.update(settingName, newValue, configurationTarget); + } catch (err) { + logger?.writeError(`Failed to change setting: ${err}`); + } +} + +// We don't want to query the user more than once, so this is idempotent. +let hasChosen = false; +let chosenWorkspace: vscode.WorkspaceFolder | undefined = undefined; +export async function getChosenWorkspace( + logger: ILogger | undefined, +): Promise { + if (hasChosen) { + return chosenWorkspace; + } + + // If there is no workspace, or there is but it has no folders, fallback. + if ( + vscode.workspace.workspaceFolders === undefined || + vscode.workspace.workspaceFolders.length === 0 + ) { + chosenWorkspace = undefined; + // If there is exactly one workspace folder, use that. + } else if (vscode.workspace.workspaceFolders.length === 1) { + chosenWorkspace = vscode.workspace.workspaceFolders[0]; + // If there is more than one workspace folder, prompt the user once. + } else if (vscode.workspace.workspaceFolders.length > 1) { + const options: vscode.WorkspaceFolderPickOptions = { + placeHolder: + "Select a workspace folder to use for the PowerShell Extension.", + }; + + chosenWorkspace = await vscode.window.showWorkspaceFolderPick(options); + + logger?.writeDebug( + `User selected workspace: '${chosenWorkspace?.name}'`, + ); + if (chosenWorkspace === undefined) { + chosenWorkspace = vscode.workspace.workspaceFolders[0]; + } else { + const response = await vscode.window.showInformationMessage( + `Would you like to save this choice by setting this workspace's 'powershell.cwd' value to '${chosenWorkspace.name}'?`, + "Yes", + "No", + ); + + if (response === "Yes") { + await changeSetting( + "cwd", + chosenWorkspace.name, + vscode.ConfigurationTarget.Workspace, + logger, + ); + } + } + } + + // NOTE: We don't rely on checking if `chosenWorkspace` is undefined because + // that may be the case if the user dismissed the prompt, and we don't want + // to show it again this session. + hasChosen = true; + return chosenWorkspace; +} + +export async function validateCwdSetting( + logger: ILogger | undefined, +): Promise { + let cwd = + utils.stripQuotePair( + vscode.workspace + .getConfiguration(utils.PowerShellLanguageId) + .get("cwd"), + ) ?? ""; + + // Replace ~ with home directory. + cwd = untildify(cwd); + + // Use the cwd setting if it's absolute and exists. We don't use or resolve + // relative paths here because it'll be relative to the Code process's cwd, + // which is not what the user is expecting. + if (path.isAbsolute(cwd) && (await utils.checkIfDirectoryExists(cwd))) { + return cwd; + } + + // If the cwd matches the name of a workspace folder, use it. Essentially + // "choose" a workspace folder based off the cwd path, and so set the state + // appropriately for `getChosenWorkspace`. + if (vscode.workspace.workspaceFolders) { + for (const workspaceFolder of vscode.workspace.workspaceFolders) { + // TODO: With some more work, we could support paths relative to a + // workspace folder name too. + if (cwd === workspaceFolder.name) { + hasChosen = true; + chosenWorkspace = workspaceFolder; + cwd = ""; + } + } + } + + // Otherwise get a cwd from the workspace, if possible. + const workspace = await getChosenWorkspace(logger); + if (workspace === undefined) { + logger?.writeDebug("Workspace was undefined, using homedir!"); + return os.homedir(); + } + + const workspacePath = workspace.uri.fsPath; + + // Use the chosen workspace's root to resolve the cwd. + const relativePath = path.join(workspacePath, cwd); + if (await utils.checkIfDirectoryExists(relativePath)) { + return relativePath; + } + + // Just use the workspace path. + if (await utils.checkIfDirectoryExists(workspacePath)) { + return workspacePath; + } + + // If all else fails, use the home directory. + return os.homedir(); +} + +/** + * Options for the `onSettingChange` function. + * @param scope the scope in which the vscode setting should be evaluated. + * @param run Indicates whether the function should be run now in addition to when settings change, or if it should be run only once and stop listening after a single change. If this is undefined, the function will be run only when the setting changes. + */ +interface onSettingChangeOptions { + scope?: vscode.ConfigurationScope; + run?: "now" | "once"; +} + +/** + * Invokes the specified action when a setting changes + * @param section the section of the vscode settings to evaluate. Defaults to `powershell` + * @param setting a string representation of the setting you wish to evaluate, e.g. `trace.server` + * @param action the action to take when the setting changes + * @param scope the scope in which the vscode setting should be evaluated. + * @returns a Disposable object that can be used to stop listening for changes with dispose() + * @example + * onSettingChange("powershell", "settingName", (newValue) => console.log(newValue)); + */ + +// Because we actually do use the constraint in the callback +// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters +export function onSettingChange( + section: string, + setting: string, + action: (newValue: T | undefined) => void, + options?: onSettingChangeOptions, +): vscode.Disposable { + const settingPath = `${section}.${setting}`; + const disposable = vscode.workspace.onDidChangeConfiguration((e) => { + if (!e.affectsConfiguration(settingPath, options?.scope)) { + return; + } + + doOnSettingsChange(section, setting, action, options?.scope); + if (options?.run === "once") { + disposable.dispose(); // Javascript black magic, referring to an outer reference before it exists + } + }); + if (options?.run === "now") { + doOnSettingsChange(section, setting, action, options.scope); + } + return disposable; +} + +/** Implementation is separate to avoid duplicate code for run now */ + +// Because we actually do use the constraint in the callback +// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters +function doOnSettingsChange( + section: string, + setting: string, + action: (newValue: T | undefined) => void, + scope?: vscode.ConfigurationScope, +): void { + const value = vscode.workspace + .getConfiguration(section, scope) + .get(setting); + action(value); +} + +/** + * Invokes the specified action when a PowerShell setting changes. Convenience function for `onSettingChange` + * @param setting a string representation of the setting you wish to evaluate, e.g. `trace.server` + * @param action the action to take when the setting changes + * @param scope the scope in which the vscode setting should be evaluated.n + * @returns a Disposable object that can be used to stop listening for changes + * @example + * onPowerShellSettingChange("settingName", (newValue) => console.log(newValue)); + */ + +// Because we actually do use the constraint in the callback +// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters +export function onPowerShellSettingChange( + setting: string, + action: (newValue: T | undefined) => void, + options?: onSettingChangeOptions, +): vscode.Disposable { + const section = "powershell"; + return onSettingChange(section, setting, action, options); +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000000..a3236ebceb --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); + +export const PowerShellLanguageId = "powershell"; + +// Path to the shell integration script in the VS Code installation. +// See commit 21114288b if it moves again. +export const ShellIntegrationScript = path.join( + vscode.env.appRoot, + "out", + "vs", + "workbench", + "contrib", + "terminal", + "common", + "scripts", + "shellIntegration.ps1", +); + +export function escapeSingleQuotes(p: string): string { + return p.replace(new RegExp("'", "g"), "''"); +} + +export function stripQuotePair(p: string | undefined): string | undefined { + if (p === undefined) { + return p; + } + + // Remove matching surrounding quotes from p (without regex) + if ( + (p.startsWith("'") && p.endsWith("'")) || + (p.startsWith('"') && p.endsWith('"')) + ) { + return p.slice(1, -1); + } + + return p; +} + +export function getPipePath(pipeName: string): string { + if (os.platform() === "win32") { + return "\\\\.\\pipe\\" + pipeName; + } else { + // Windows uses NamedPipes where non-Windows platforms use Unix Domain Sockets. + // This requires connecting to the pipe file in different locations on Windows vs non-Windows. + return path.join(os.tmpdir(), `CoreFxPipe_${pipeName}`); + } +} + +// Check that the file or directory exists in an asynchronous manner that relies +// solely on the VS Code API, not Node's fs library, ignoring symlinks. +async function checkIfFileOrDirectoryExists( + targetPath: string | vscode.Uri, + type: vscode.FileType, +): Promise { + if (targetPath === "") { + return false; + } + try { + const stat: vscode.FileStat = await vscode.workspace.fs.stat( + targetPath instanceof vscode.Uri + ? targetPath + : vscode.Uri.file(targetPath), + ); + return (stat.type & type) !== 0; + } catch { + return false; + } +} + +export async function checkIfFileExists( + filePath: string | vscode.Uri, +): Promise { + return await checkIfFileOrDirectoryExists(filePath, vscode.FileType.File); +} + +export async function checkIfDirectoryExists( + directoryPath: string | vscode.Uri, +): Promise { + return await checkIfFileOrDirectoryExists( + directoryPath, + vscode.FileType.Directory, + ); +} + +export async function readDirectory( + directoryPath: string | vscode.Uri, +): Promise { + const items = await vscode.workspace.fs.readDirectory( + directoryPath instanceof vscode.Uri + ? directoryPath + : vscode.Uri.file(directoryPath), + ); + return items.map(([name, _type]) => name); +} + +export function getTimestampString(): string { + const time = new Date(); + return `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}]`; +} + +export function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export const isMacOS: boolean = process.platform === "darwin"; +export const isWindows: boolean = process.platform === "win32"; +export const isLinux: boolean = !isMacOS && !isWindows; diff --git a/syntaxes/PowerShell.tmLanguage b/syntaxes/PowerShell.tmLanguage deleted file mode 100644 index d9e7c46b12..0000000000 --- a/syntaxes/PowerShell.tmLanguage +++ /dev/null @@ -1,1181 +0,0 @@ - - - - - fileTypes - - ps1 - psm1 - psd1 - - name - PowerShell - patterns - - - begin - <# - beginCaptures - - 0 - - name - punctuation.start.definition.comment.block.powershell - - - end - #> - endCaptures - - 0 - - name - punctuation.end.definition.comment.block.powershell - - - name - comment.block.powershell - patterns - - - include - #commentEmbeddedDocs - - - - - begin - (?<![\\-])# - end - $ - name - comment.line.number-sign.powershell - patterns - - - include - #commentEmbeddedDocs - - - - - match - [2-6]>&1|>>|>|<<|<|>|>\||[1-6]>|[1-6]>> - name - keyword.operator.redirection.powershell - - - include - #commands - - - include - #variable - - - include - #interpolatedStringContent - - - include - #function - - - include - #attribute - - - include - #type - - - begin - (?<!(?<!`)")" - end - "(?!") - name - string.quoted.double.powershell - patterns - - - include - #variableNoProperty - - - include - #doubleQuotedStringEscapes - - - include - #interpolation - - - match - `\s*$ - name - keyword.other.powershell - - - - - comment - Needed to parse stuff correctly in 'argument mode'. (See about_parsing.) - include - #doubleQuotedStringEscapes - - - begin - (?<!')' - end - '(?!') - name - string.quoted.single.powershell - patterns - - - match - '' - name - constant.character.escape.powershell - - - - - begin - \@"(?=$) - end - ^"@ - name - string.quoted.double.heredoc.powershell - patterns - - - include - #variableNoProperty - - - include - #doubleQuotedStringEscapes - - - include - #interpolation - - - - - begin - \@'(?=$) - end - ^'@ - name - string.quoted.single.heredoc.powershell - patterns - - - match - '' - name - constant.character.escape.powershell - - - - - include - #numericConstant - - - begin - @\( - captures - - 0 - - name - keyword.other.powershell - - - end - \) - name - meta.group.array-expression.powershell - patterns - - - include - $self - - - - - begin - \$\( - captures - - 0 - - name - keyword.other.powershell - - - comment - TODO: move to repo; make recursive. - end - \) - name - meta.group.complex.subexpression.powershell - patterns - - - include - $self - - - - - match - (?<!\w)-([ci]?[lg][te]|eq|ne) - name - keyword.operator.logical.powershell - - - match - (?i:[a-z][a-z0-9]+-?[a-z][a-z0-9]+)(?i:\.(?i:exe|cmd|bat|ps1)) - name - support.function.powershell - - - match - (?<!\w)((?i:begin|break|catch|continue|data|define|do|dynamicparam|else|elseif|end|exit|finally|for|foreach(?!-object)|from|if|in|inlinescript|parallel|param|process|return|switch|throw|trap|try|until|using|var|where(?!=-object)|while)|%|\?)(?!\w) - name - keyword.control.powershell - - - captures - - 1 - - name - storage.type.powershell - - 2 - - name - entity.name.function - - - comment - capture should be entity.name.type, but it doesn't provide a good color in the default schema. - match - (?<!\w)((?i:class)|%|\?)(?:\s)+((?:\p{L}|\d|_|-|)+)\b - - - match - (?<!\w)-(?i:is(?:not)?|as)\b - name - keyword.operator.comparison.powershell - - - match - (?<!\w)-(?i:[ic]?(?:eq|ne|[gl][te]|(?:not)?(?:like|match|contains|in)|replace))(?!\p{L}) - name - keyword.operator.comparison.powershell - - - match - (?<!\w)-(?i:join|split)(?!\p{L})|! - name - keyword.operator.unary.powershell - - - match - (?<!\w)-(?i:and|or|not|xor)(?!\p{L})|! - name - keyword.operator.logical.powershell - - - match - (?<!\w)-(?i:band|bor|bnot|bxor)(?!\p{L}) - name - keyword.operator.bitwise.powershell - - - match - (?<!\w)-(?i:f)(?!\p{L}) - name - keyword.operator.string-format.powershell - - - match - [+%*/-]?=|[+/*%-] - name - keyword.operator.assignment.powershell - - - match - \|{2}|&{2}|; - name - keyword.other.statement-separator.powershell - - - match - &|(?<!\w)\.(?= )|`|,|\| - name - keyword.operator.other.powershell - - - comment - This is very imprecise, is there a syntax for 'must come after...' - match - (?<!\s|^)\.\.(?=\d|\(|\$) - name - keyword.operator.range.powershell - - - repository - - attribute - - begin - \[(\p{L}|\.|``\d+)+(?=\() - beginCaptures - - 0 - - name - entity.name.tag - - 1 - - name - entity.name.tag - - - end - \] - endCaptures - - 0 - - name - entity.name.tag - - - patterns - - - begin - \( - end - \) - name - entity.other.attribute-name - patterns - - - captures - - 0 - - name - entity.other.attribute.parameter.powershell - - 1 - - name - constant.language.powershell - - 2 - - name - variable.other.powershell - - - comment - really we should match the known attributes first - match - (\w+)\s*=?([^"']*?|'[^']*?'|"[^"]*?")?(?=,|\)) - name - entity.other.attribute-name.powershell - - - include - #variable - - - - - - commands - - patterns - - - comment - Verb-Noun pattern: - match - (?:(\p{L}|\d|_|-|\\|\:)*\\)?\b(?i:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Write)\-.+?(?:\.(?i:exe|cmd|bat|ps1))?\b - name - support.function.powershell - - - comment - Builtin cmdlets with reserved verbs - match - (?<!\w)(?i:foreach-object)(?!\w) - name - support.function.powershell - - - - commentEmbeddedDocs - - patterns - - - captures - - 1 - - name - constant.string.documentation.powershell - - 2 - - name - keyword.operator.documentation.powershell - - - match - (?i:\s*(\.)(SYNOPSIS|DESCRIPTION|EXAMPLE|INPUTS|OUTPUTS|NOTES|LINK|COMPONENT|FUNCTIONALITY)) - name - comment.documentation.embedded.powershell - - - captures - - 1 - - name - constant.string.documentation.powershell - - 2 - - name - keyword.operator.documentation.powershell - - 3 - - name - keyword.operator.documentation.powershell - - - match - (?i:\s*(\.)(PARAMETER|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP)\s+([a-z0-9-_]+)) - name - comment.documentation.embedded.powershell - - - captures - - 1 - - name - constant.string.documentation.powershell - - 2 - - name - keyword.operator.documentation.powershell - - 3 - - name - string.quoted.double.heredoc.powershell - - - match - (?i:requires\s+-(Version\s+\d(.\d+)?|Assembly\s+(.*)|Module\s+(.*)|PsSnapIn\s+(.*)|ShellId\s+(.*))) - name - comment.documentation.embedded.powershell - - - - doubleQuotedStringEscapes - - patterns - - - match - `[0abnfrvt"'$`] - name - constant.character.escape.powershell - - - match - "" - name - constant.character.escape.powershell - - - - function - - begin - ((?i:function|filter|configuration|workflow))\s+((?:\p{L}|\d|_|-|\.)+) - beginCaptures - - 0 - - name - meta.function - - 1 - - name - storage.type - - 2 - - name - entity.name.function - - - end - \{|\( - - interpolatedStringContent - - begin - \( - beginCaptures - - 0 - - name - keyword.other.powershell - - - contentName - interpolated.simple.source.powershell - end - \) - endCaptures - - 0 - - name - keyword.other.powershell - - - patterns - - - include - $self - - - include - #interpolation - - - include - #interpolatedStringContent - - - - interpolation - - begin - (\$)\( - beginCaptures - - 0 - - name - keyword.other.powershell - - - contentName - interpolated.complex.source.powershell - end - \) - endCaptures - - 0 - - name - keyword.other.powershell - - - patterns - - - include - $self - - - include - #interpolation - - - include - #interpolatedStringContent - - - - numericConstant - - patterns - - - captures - - 1 - - name - keyword.operator.math.powershell - - 2 - - name - support.constant.powershell - - 3 - - name - keyword.other.powershell - - - match - (?<!\w)(?i:(0x)([a-f0-9]+)((?i:L)?(?i:[kmgtp]b)?))(?!\w) - name - constant.numeric.hexadecimal.powershell - - - captures - - 1 - - name - support.constant.powershell - - 2 - - name - keyword.operator.math.powershell - - 3 - - name - support.constant.powershell - - 4 - - name - keyword.other.powershell - - 5 - - name - keyword.other.powershell - - - match - (?<!\w)(?i:(\d*\.?\d+)(?:((?i:E)[+-]?)(\d+))?((?i:[DL])?)((?i:[kmgtp]b)?))(?!\w) - name - constant.numeric.scientific.powershell - - - - scriptblock - - begin - \{ - end - \} - name - meta.scriptblock.powershell - patterns - - - include - $self - - - - type - - begin - \[ - beginCaptures - - 0 - - name - entity.other.attribute-name - - - comment - name should be entity.name.type but default schema doesn't have a good color for it - end - \] - endCaptures - - 0 - - name - entity.other.attribute-name - - - patterns - - - match - (\p{L}|\.|``\d+)+? - name - entity.other.attribute-name - - - include - $self - - - - variable - - patterns - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - constant.language.powershell - - - comment - These are special constants. - match - (\$)(?i:(False|Null|True))\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.constant.variable.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - These are the other built-in constants. - match - (\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))((?:\.(?:\p{L}|\d|_)+)*\b)?\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.constant.automatic.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - Automatic variables are not constants, but they are read-only. In monokai (default) color schema support.variable doesn't have color, so we use constant. - match - (\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))((?:\.(?:\p{L}|\d|_)+)*\b)?\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - variable.language.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - Style preference variables as language variables so that they stand out. - match - (\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))((?:\.(?:\p{L}|\d|_)+)*\b)?\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - storage.modifier.scope.powershell - - 3 - - name - variable.other.normal.powershell - - 4 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)? - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - storage.modifier.scope.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - keyword.other.powershell - - 5 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)? - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.variable.drive.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)? - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.variable.drive.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - keyword.other.powershell - - 5 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)? - - - - variableNoProperty - - patterns - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - constant.language.powershell - - - comment - These are special constants. - match - (\$)(?i:(False|Null|True))\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.constant.variable.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - These are the other built-in constants. - match - (\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.variable.automatic.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - Automatic variables are not constants, but they are read-only... - match - (\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - variable.language.powershell - - 3 - - name - entity.name.function.invocation.powershell - - - comment - Style preference variables as language variables so that they stand out. - match - (\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))\b - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - storage.modifier.scope.powershell - - 3 - - name - variable.other.normal.powershell - - 4 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+)) - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - storage.modifier.scope.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - keyword.other.powershell - - 5 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\})) - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.variable.drive.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+)) - - - captures - - 1 - - name - keyword.other.powershell - - 2 - - name - support.variable.drive.powershell - - 3 - - name - variable.other.readwrite.powershell - - 4 - - name - keyword.other.powershell - - 5 - - name - entity.name.function.invocation.powershell - - - match - (?i:(\$\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\})) - - - - - scopeName - source.powershell - uuid - f8f5ffb0-503e-11df-9879-0800200c9a66 - - \ No newline at end of file diff --git a/test/OneBranch.code-workspace b/test/OneBranch.code-workspace new file mode 100644 index 0000000000..d17440aded --- /dev/null +++ b/test/OneBranch.code-workspace @@ -0,0 +1,18 @@ +{ + // A simple test environment that suppresses some first start warnings we don't care about. + "folders": [ + { + "path": "mocks", + }, + ], + "settings": { + "git.openRepositoryInParentFolders": "never", + "csharp.suppressDotnetRestoreNotification": true, + "extensions.ignoreRecommendations": true, + // The settings tests account for this fix + "powershell.powerShellAdditionalExePaths": { + "OneBranch": "C:\\powershell-7\\pwsh.exe", + }, + "powershell.powerShellDefaultVersion": "OneBranch", + }, +} diff --git a/test/TestEnvironment.code-workspace b/test/TestEnvironment.code-workspace new file mode 100644 index 0000000000..4915d16693 --- /dev/null +++ b/test/TestEnvironment.code-workspace @@ -0,0 +1,13 @@ +{ + // A simple test environment that suppresses some first start warnings we don't care about. + "folders": [ + { + "path": "mocks", + }, + ], + "settings": { + "git.openRepositoryInParentFolders": "never", + "csharp.suppressDotnetRestoreNotification": true, + "extensions.ignoreRecommendations": true, + }, +} diff --git a/test/core/paths.test.ts b/test/core/paths.test.ts new file mode 100644 index 0000000000..e68fc1a88b --- /dev/null +++ b/test/core/paths.test.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import assert from "assert"; +import * as vscode from "vscode"; +import type { IPowerShellExtensionClient } from "../../src/features/ExternalApi"; +import { + checkIfDirectoryExists, + checkIfFileExists, + ShellIntegrationScript, +} from "../../src/utils"; +import utils = require("../utils"); + +describe("Path assumptions", function () { + let globalStorageUri: vscode.Uri; + let logUri: vscode.Uri; + before(async () => { + const extension: IPowerShellExtensionClient = + await utils.ensureEditorServicesIsConnected(); + globalStorageUri = extension.getStorageUri(); + logUri = extension.getLogUri(); + }); + + it("Creates the session folder at the correct path", async function () { + assert( + await checkIfDirectoryExists( + vscode.Uri.joinPath(globalStorageUri, "sessions"), + ), + ); + }); + + it("Creates the log folder at the correct path", async function () { + assert(await checkIfDirectoryExists(logUri)); + }); + + it("Finds the Terminal Shell Integration Script", async function () { + // If VS Code changes the location of the script, we need to know ASAP (as it's not a public API). + assert(await checkIfFileExists(ShellIntegrationScript)); + }); +}); diff --git a/test/core/platform.test.ts b/test/core/platform.test.ts new file mode 100644 index 0000000000..e6de6a5f3a --- /dev/null +++ b/test/core/platform.test.ts @@ -0,0 +1,1067 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as assert from "assert"; +import * as os from "os"; +import * as path from "path"; +import * as sinon from "sinon"; +import * as platform from "../../src/platform"; +import mockFS = require("mock-fs"); +import FileSystem = require("mock-fs/lib/filesystem"); + +/** + * Describes a platform on which the PowerShell extension should work, + * including the test conditions (filesystem, environment variables). + */ +interface ITestPlatform { + name: string; + platformDetails: platform.IPlatformDetails; + filesystem: FileSystem.DirectoryItems; + environmentVars: Record; +} + +/** + * A platform where the extension should find a PowerShell, + * including the sequence of PowerShell installations that should be found. + * The expected default PowerShell is the first installation. + */ +interface ITestPlatformSuccessCase extends ITestPlatform { + expectedPowerShellSequence: platform.IPowerShellExeDetails[]; +} + +// Platform configurations where we expect to find a set of PowerShells +let successTestCases: ITestPlatformSuccessCase[]; + +// Platform configurations for testing the powerShellAdditionalExePaths setting +let additionalPowerShellExes: Record; +let successAdditionalTestCases: ITestPlatformSuccessCase[]; + +if (process.platform === "win32") { + const msixAppDir = path.join( + process.env.LOCALAPPDATA!, + "Microsoft", + "WindowsApps", + ); + const pwshMsixPath = path.join( + msixAppDir, + "Microsoft.PowerShell_8wekyb3d8bbwe", + "pwsh.exe", + ); + const pwshPreviewMsixPath = path.join( + msixAppDir, + "Microsoft.PowerShellPreview_8wekyb3d8bbwe", + "pwsh.exe", + ); + + successTestCases = [ + { + name: "Windows 64-bit, 64-bit VSCode (all installations)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: "C:\\Program Files\\PowerShell\\6\\pwsh.exe", + displayName: "PowerShell (x64)", + supportsProperArguments: true, + }, + { + exePath: "C:\\Program Files (x86)\\PowerShell\\6\\pwsh.exe", + displayName: "PowerShell (x86)", + supportsProperArguments: true, + }, + { + exePath: pwshMsixPath, + displayName: "PowerShell (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe", + displayName: "PowerShell Preview (x64)", + supportsProperArguments: true, + }, + { + exePath: pwshPreviewMsixPath, + displayName: "PowerShell Preview (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\Program Files (x86)\\PowerShell\\7-preview\\pwsh.exe", + displayName: "PowerShell Preview (x86)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x64)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\Program Files\\PowerShell": { + "6": { + "pwsh.exe": "", + }, + "7-preview": { + "pwsh.exe": "", + }, + }, + "C:\\Program Files (x86)\\PowerShell": { + "6": { + "pwsh.exe": "", + }, + "7-preview": { + "pwsh.exe": "", + }, + }, + [msixAppDir]: { + "Microsoft.PowerShell_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + "Microsoft.PowerShellPreview_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + }, + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + "C:\\WINDOWS\\SysWOW64\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows 64-bit, 64-bit VSCode (only Windows PowerShell)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x64)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + "C:\\WINDOWS\\SysWOW64\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows 64-bit, 32-bit VSCode (all installations)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: false, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files (x86)", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: "C:\\Program Files (x86)\\PowerShell\\6\\pwsh.exe", + displayName: "PowerShell (x86)", + supportsProperArguments: true, + }, + { + exePath: "C:\\Program Files\\PowerShell\\6\\pwsh.exe", + displayName: "PowerShell (x64)", + supportsProperArguments: true, + }, + { + exePath: pwshMsixPath, + displayName: "PowerShell (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\Program Files (x86)\\PowerShell\\7-preview\\pwsh.exe", + displayName: "PowerShell Preview (x86)", + supportsProperArguments: true, + }, + { + exePath: pwshPreviewMsixPath, + displayName: "PowerShell Preview (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe", + displayName: "PowerShell Preview (x64)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x64)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\Program Files\\PowerShell": { + "6": { + "pwsh.exe": "", + }, + "7-preview": { + "pwsh.exe": "", + }, + }, + "C:\\Program Files (x86)\\PowerShell": { + "6": { + "pwsh.exe": "", + }, + "7-preview": { + "pwsh.exe": "", + }, + }, + [msixAppDir]: { + "Microsoft.PowerShell_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + "Microsoft.PowerShellPreview_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + }, + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + "C:\\WINDOWS\\Sysnative\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows 64-bit, 32-bit VSCode (Windows PowerShell only)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: false, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files (x86)", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x64)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + "C:\\WINDOWS\\Sysnative\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows 32-bit, 32-bit VSCode (all installations)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: false, + isProcess64Bit: false, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files (x86)", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: "C:\\Program Files (x86)\\PowerShell\\6\\pwsh.exe", + displayName: "PowerShell (x86)", + supportsProperArguments: true, + }, + { + exePath: pwshMsixPath, + displayName: "PowerShell (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\Program Files (x86)\\PowerShell\\7-preview\\pwsh.exe", + displayName: "PowerShell Preview (x86)", + supportsProperArguments: true, + }, + { + exePath: pwshPreviewMsixPath, + displayName: "PowerShell Preview (Store)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\Program Files (x86)\\PowerShell": { + "6": { + "pwsh.exe": "", + }, + "7-preview": { + "pwsh.exe": "", + }, + }, + [msixAppDir]: { + "Microsoft.PowerShell_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + "Microsoft.PowerShellPreview_8wekyb3d8bbwe": { + "pwsh.exe": "", + }, + }, + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows 32-bit, 32-bit VSCode (Windows PowerShell only)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: false, + isProcess64Bit: false, + }, + environmentVars: { + ProgramFiles: "C:\\Program Files (x86)", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0": { + "powershell.exe": "", + }, + }, + }, + { + name: "Windows (dotnet)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + USERNAME: "test", + USERPROFILE: "C:\\Users\\test", + ProgramFiles: "C:\\Program Files", + "ProgramFiles(x86)": "C:\\Program Files (x86)", + windir: "C:\\WINDOWS", + }, + expectedPowerShellSequence: [ + { + exePath: "C:\\Users\\test\\.dotnet\\tools\\pwsh.exe", + displayName: ".NET Core PowerShell Global Tool", + supportsProperArguments: false, + }, + { + exePath: + "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x64)", + supportsProperArguments: true, + }, + { + exePath: + "C:\\WINDOWS\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe", + displayName: "Windows PowerShell (x86)", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\Users\\test\\.dotnet\\tools": { + "pwsh.exe": "", + }, + }, + }, + ]; + + additionalPowerShellExes = { + pwsh: "C:\\Users\\test\\pwsh\\pwsh.exe", + "pwsh-tilde": "~\\pwsh\\pwsh.exe", + "pwsh-no-exe": "C:\\Users\\test\\pwsh\\pwsh", + "pwsh-folder": "C:\\Users\\test\\pwsh\\", + "pwsh-folder-no-slash": "C:\\Users\\test\\pwsh", + "pwsh-single-quotes": "'C:\\Users\\test\\pwsh\\pwsh.exe'", + "pwsh-double-quotes": '"C:\\Users\\test\\pwsh\\pwsh.exe"', + }; + + successAdditionalTestCases = [ + { + name: "Windows (Additional PowerShell Executables)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Windows, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + USERNAME: "test", + USERPROFILE: "C:\\Users\\test", + }, + expectedPowerShellSequence: [ + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh", + supportsProperArguments: true, + }, + { + exePath: path.join(os.homedir(), "pwsh", "pwsh.exe"), + displayName: "pwsh-tilde", + supportsProperArguments: true, + }, + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh-no-exe", + supportsProperArguments: true, + }, + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh-folder", + supportsProperArguments: true, + }, + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh-folder-no-slash", + supportsProperArguments: true, + }, + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh-single-quotes", + supportsProperArguments: true, + }, + { + exePath: "C:\\Users\\test\\pwsh\\pwsh.exe", + displayName: "pwsh-double-quotes", + supportsProperArguments: true, + }, + ], + filesystem: { + "C:\\Users\\test\\pwsh": { + "pwsh.exe": "", + }, + [path.join(os.homedir(), "pwsh")]: { + "pwsh.exe": "", + }, + }, + }, + ]; +} else { + successTestCases = [ + { + name: "Linux (all installations)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + expectedPowerShellSequence: [ + { + exePath: "/usr/bin/pwsh", + displayName: "PowerShell", + supportsProperArguments: true, + }, + { + exePath: "/snap/bin/pwsh", + displayName: "PowerShell Snap", + supportsProperArguments: true, + }, + { + exePath: "/usr/bin/pwsh-preview", + displayName: "PowerShell Preview", + supportsProperArguments: true, + }, + { + exePath: "/snap/bin/pwsh-preview", + displayName: "PowerShell Preview Snap", + supportsProperArguments: true, + }, + ], + filesystem: { + "/usr/bin": { + pwsh: "", + "pwsh-preview": "", + }, + "/snap/bin": { + pwsh: "", + "pwsh-preview": "", + }, + }, + }, + { + name: "MacOS (all installations)", + platformDetails: { + operatingSystem: platform.OperatingSystem.MacOS, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + expectedPowerShellSequence: [ + { + exePath: "/usr/local/bin/pwsh", + displayName: "PowerShell", + supportsProperArguments: true, + }, + { + exePath: "/opt/homebrew/bin/pwsh", + displayName: "PowerShell (Homebrew)", + supportsProperArguments: true, + }, + { + exePath: "/opt/homebrew/bin/pwsh-lts", + displayName: "PowerShell LTS (Homebrew)", + supportsProperArguments: true, + }, + { + exePath: "/usr/local/bin/pwsh-preview", + displayName: "PowerShell Preview", + supportsProperArguments: true, + }, + { + exePath: "/opt/homebrew/bin/pwsh-preview", + displayName: "PowerShell Preview (Homebrew)", + supportsProperArguments: true, + }, + ], + filesystem: { + "/usr/local/bin": { + pwsh: "", + "pwsh-preview": "", + }, + "/opt/homebrew/bin/": { + pwsh: "", + "pwsh-lts": "", + "pwsh-preview": "", + }, + }, + }, + { + name: "Linux (stable only)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + expectedPowerShellSequence: [ + { + exePath: "/usr/bin/pwsh", + displayName: "PowerShell", + supportsProperArguments: true, + }, + ], + filesystem: { + "/usr/bin": { + pwsh: "", + }, + }, + }, + { + name: "Linux (stable snap only)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + expectedPowerShellSequence: [ + { + exePath: "/snap/bin/pwsh", + displayName: "PowerShell Snap", + supportsProperArguments: true, + }, + ], + filesystem: { + "/snap/bin": { + pwsh: "", + }, + }, + }, + { + name: "MacOS (stable only)", + platformDetails: { + operatingSystem: platform.OperatingSystem.MacOS, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + expectedPowerShellSequence: [ + { + exePath: "/usr/local/bin/pwsh", + displayName: "PowerShell", + supportsProperArguments: true, + }, + ], + filesystem: { + "/usr/local/bin": { + pwsh: "", + }, + }, + }, + { + name: "MacOS (dotnet)", + platformDetails: { + operatingSystem: platform.OperatingSystem.MacOS, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + USER: "test", + HOME: "/Users/test", + }, + expectedPowerShellSequence: [ + { + exePath: "/Users/test/.dotnet/tools/pwsh", + displayName: ".NET Core PowerShell Global Tool", + supportsProperArguments: false, + }, + ], + filesystem: { + "/Users/test/.dotnet/tools": { + pwsh: "", + }, + }, + }, + { + name: "Linux (dotnet)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + USER: "test", + HOME: "/home/test", + }, + expectedPowerShellSequence: [ + { + exePath: "/home/test/.dotnet/tools/pwsh", + displayName: ".NET Core PowerShell Global Tool", + supportsProperArguments: false, + }, + ], + filesystem: { + "/home/test/.dotnet/tools": { + pwsh: "", + }, + }, + }, + ]; + + additionalPowerShellExes = { + pwsh: "/home/test/bin/pwsh", + "pwsh-tilde": "~/bin/pwsh", + "pwsh-folder": "/home/test/bin/", + "pwsh-folder-no-slash": "/home/test/bin", + "pwsh-single-quotes": "'/home/test/bin/pwsh'", + "pwsh-double-quotes": '"/home/test/bin/pwsh"', + }; + + successAdditionalTestCases = [ + { + name: "Linux/macOS (Additional PowerShell Executables)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: { + USER: "test", + HOME: "/home/test", + }, + expectedPowerShellSequence: [ + { + exePath: "/home/test/bin/pwsh", + displayName: "pwsh", + supportsProperArguments: true, + }, + { + // untildify ignores the HOME mock so this is platform-dependent + exePath: path.join(os.homedir(), "bin", "pwsh"), + displayName: "pwsh-tilde", + supportsProperArguments: true, + }, + { + exePath: "/home/test/bin/pwsh", + displayName: "pwsh-folder", + supportsProperArguments: true, + }, + { + exePath: "/home/test/bin/pwsh", + displayName: "pwsh-folder-no-slash", + supportsProperArguments: true, + }, + { + exePath: "/home/test/bin/pwsh", + displayName: "pwsh-single-quotes", + supportsProperArguments: true, + }, + { + exePath: "/home/test/bin/pwsh", + displayName: "pwsh-double-quotes", + supportsProperArguments: true, + }, + ], + filesystem: { + "/home/test/bin": { + pwsh: "", + }, + [path.join(os.homedir(), "bin")]: { + pwsh: "", + }, + }, + }, + ]; +} + +const errorTestCases: ITestPlatform[] = [ + { + name: "Linux (no PowerShell)", + platformDetails: { + operatingSystem: platform.OperatingSystem.Linux, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + filesystem: {}, + }, + { + name: "MacOS (no PowerShell)", + platformDetails: { + operatingSystem: platform.OperatingSystem.MacOS, + isOS64Bit: true, + isProcess64Bit: true, + }, + environmentVars: {}, + filesystem: {}, + }, +]; + +function setupTestEnvironment(testPlatform: ITestPlatform): void { + mockFS(testPlatform.filesystem); + + for (const envVar of Object.keys(testPlatform.environmentVars)) { + sinon + .stub(process.env, envVar) + .value(testPlatform.environmentVars[envVar]); + } +} + +describe("Platform module", function () { + afterEach(function () { + mockFS.restore(); + }); + + it("Gets the correct platform details", function () { + const platformDetails: platform.IPlatformDetails = + platform.getPlatformDetails(); + switch (process.platform) { + case "darwin": + assert.strictEqual( + platformDetails.operatingSystem, + platform.OperatingSystem.MacOS, + "Platform details operating system should be MacOS", + ); + assert.strictEqual( + platformDetails.isProcess64Bit, + true, + "VSCode on darwin should be 64-bit", + ); + assert.strictEqual( + platformDetails.isOS64Bit, + true, + "Darwin is 64-bit only", + ); + break; + + case "linux": + assert.strictEqual( + platformDetails.operatingSystem, + platform.OperatingSystem.Linux, + "Platform details operating system should be Linux", + ); + assert.strictEqual( + platformDetails.isProcess64Bit, + true, + "Only 64-bit VSCode supported on Linux", + ); + assert.strictEqual( + platformDetails.isOS64Bit, + true, + "Only 64-bit Linux supported by PowerShell", + ); + return; + + case "win32": + assert.strictEqual( + platformDetails.operatingSystem, + platform.OperatingSystem.Windows, + "Platform details operating system should be Windows", + ); + assert.strictEqual( + platformDetails.isProcess64Bit, + process.arch === "x64" || process.arch === "arm64", + "Windows process bitness should match process arch", + ); + assert.strictEqual( + platformDetails.isOS64Bit, + !!( + platformDetails.isProcess64Bit || + process.env.ProgramW6432 + ), + "Windows OS arch should match process bitness unless 64-bit env var set", + ); + return; + + default: + assert.fail("This platform is unsupported"); + } + }); + + describe("Default PowerShell installation", function () { + for (const testPlatform of successTestCases) { + it(`Finds it on ${testPlatform.name}`, async function () { + setupTestEnvironment(testPlatform); + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + {}, + ); + + const defaultPowerShell = + await powerShellExeFinder.getFirstAvailablePowerShellInstallation(); + const expectedPowerShell = + testPlatform.expectedPowerShellSequence[0]; + + assert.strictEqual( + defaultPowerShell!.exePath, + expectedPowerShell.exePath, + ); + assert.strictEqual( + defaultPowerShell!.displayName, + expectedPowerShell.displayName, + ); + assert.strictEqual( + defaultPowerShell!.supportsProperArguments, + expectedPowerShell.supportsProperArguments, + ); + }); + } + + for (const testPlatform of errorTestCases) { + it(`Fails gracefully on ${testPlatform.name}`, async function () { + setupTestEnvironment(testPlatform); + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + {}, + ); + + const defaultPowerShell = + await powerShellExeFinder.getFirstAvailablePowerShellInstallation(); + assert.strictEqual(defaultPowerShell, undefined); + }); + } + }); + + describe("Expected PowerShell installation list", function () { + for (const testPlatform of successTestCases) { + it(`Finds them on ${testPlatform.name}`, async function () { + setupTestEnvironment(testPlatform); + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + {}, + ); + + const foundPowerShells = + await powerShellExeFinder.getAllAvailablePowerShellInstallations(); + + for ( + let i = 0; + i < testPlatform.expectedPowerShellSequence.length; + i++ + ) { + const foundPowerShell = foundPowerShells[i]; + const expectedPowerShell = + testPlatform.expectedPowerShellSequence[i]; + + assert.strictEqual( + foundPowerShell.exePath, + expectedPowerShell.exePath, + ); + assert.strictEqual( + foundPowerShell.displayName, + expectedPowerShell.displayName, + ); + assert.strictEqual( + foundPowerShell.supportsProperArguments, + expectedPowerShell.supportsProperArguments, + ); + } + + assert.strictEqual( + foundPowerShells.length, + testPlatform.expectedPowerShellSequence.length, + "Number of expected PowerShells found does not match", + ); + }); + } + + for (const testPlatform of errorTestCases) { + it(`Fails gracefully on ${testPlatform.name}`, async function () { + setupTestEnvironment(testPlatform); + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + {}, + ); + + const foundPowerShells = + await powerShellExeFinder.getAllAvailablePowerShellInstallations(); + assert.strictEqual(foundPowerShells.length, 0); + }); + } + }); + + describe("Windows PowerShell path fix", function () { + for (const testPlatform of successTestCases.filter( + (tp) => + tp.platformDetails.operatingSystem === + platform.OperatingSystem.Windows, + )) { + it(`Corrects the Windows PowerShell path on ${testPlatform.name}`, function () { + setupTestEnvironment(testPlatform); + + function getWinPSPath(systemDir: string): string { + return path.join( + testPlatform.environmentVars.windir, + systemDir, + "WindowsPowerShell", + "v1.0", + "powershell.exe", + ); + } + + const winPSPath = getWinPSPath("System32"); + + let altWinPSPath; + if (testPlatform.platformDetails.isProcess64Bit) { + altWinPSPath = getWinPSPath("SysWOW64"); + } else if (testPlatform.platformDetails.isOS64Bit) { + altWinPSPath = getWinPSPath("Sysnative"); + } else { + altWinPSPath = null; + } + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + {}, + ); + + assert.strictEqual( + powerShellExeFinder.fixWindowsPowerShellPath(winPSPath), + winPSPath, + ); + + if (altWinPSPath) { + assert.strictEqual( + powerShellExeFinder.fixWindowsPowerShellPath( + altWinPSPath, + ), + winPSPath, + ); + } + }); + } + }); + + describe("PowerShell executables from 'powerShellAdditionalExePaths' are found", function () { + for (const testPlatform of successAdditionalTestCases) { + it(`Guesses for ${testPlatform.name}`, async function () { + setupTestEnvironment(testPlatform); + + const powerShellExeFinder = new platform.PowerShellExeFinder( + testPlatform.platformDetails, + additionalPowerShellExes, + ); + + let i = 0; + for await (const additionalPwsh of powerShellExeFinder.enumerateAdditionalPowerShellInstallations()) { + const expectedPowerShell = + testPlatform.expectedPowerShellSequence[i]; + i++; + + assert.strictEqual( + additionalPwsh.exePath, + expectedPowerShell.exePath, + ); + assert.strictEqual( + additionalPwsh.displayName, + expectedPowerShell.displayName, + ); + } + }); + } + }); +}); diff --git a/test/core/settings.test.ts b/test/core/settings.test.ts new file mode 100644 index 0000000000..117035a390 --- /dev/null +++ b/test/core/settings.test.ts @@ -0,0 +1,138 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as assert from "assert"; +import { existsSync } from "fs"; +import * as os from "os"; +import path from "path"; +import * as vscode from "vscode"; +import { + changeSetting, + CommentType, + getEffectiveConfigurationTarget, + getSettings, + Settings, + validateCwdSetting, +} from "../../src/settings"; +import { ensureEditorServicesIsConnected } from "../utils"; + +describe("Settings E2E", function () { + async function changeCwdSetting(cwd: string | undefined): Promise { + await changeSetting( + "cwd", + cwd, + vscode.ConfigurationTarget.Workspace, + undefined, + ); + } + + async function resetCwdSetting(): Promise { + await changeCwdSetting(undefined); + } + + describe("The 'getSettings' method loads the 'Settings' class", function () { + before(resetCwdSetting); + + it("Loads without error", function () { + assert.doesNotThrow(getSettings); + }); + + it("Loads the correct defaults", function () { + const testSettings = new Settings(); + if (existsSync("C:\\powershell-7\\pwsh.exe")) { + testSettings.powerShellAdditionalExePaths = { + OneBranch: "C:\\powershell-7\\pwsh.exe", + }; + testSettings.powerShellDefaultVersion = "OneBranch"; + } + const actualSettings = getSettings(); + assert.deepStrictEqual(actualSettings, testSettings); + }); + }); + + describe("The 'changeSetting' method", function () { + it("Updates correctly", async function () { + await changeSetting( + "helpCompletion", + CommentType.LineComment, + vscode.ConfigurationTarget.Workspace, + undefined, + ); + assert.strictEqual( + getSettings().helpCompletion, + CommentType.LineComment, + ); + }); + }); + + describe("The 'getEffectiveConfigurationTarget' method'", function () { + it("Works for 'Workspace' target", async function () { + await changeSetting( + "helpCompletion", + CommentType.LineComment, + vscode.ConfigurationTarget.Workspace, + undefined, + ); + const target = getEffectiveConfigurationTarget("helpCompletion"); + assert.strictEqual(target, vscode.ConfigurationTarget.Workspace); + }); + + it("Works for 'undefined' target", async function () { + await changeSetting( + "helpCompletion", + undefined, + vscode.ConfigurationTarget.Workspace, + undefined, + ); + const target = getEffectiveConfigurationTarget("helpCompletion"); + assert.strictEqual(target, undefined); + }); + }); + + describe("The CWD setting", function () { + // We're relying on this to be sure that the workspace is loaded. + before(ensureEditorServicesIsConnected); + before(resetCwdSetting); + afterEach(resetCwdSetting); + + const workspace = vscode.workspace.workspaceFolders![0].uri.fsPath; + + it("Defaults to the 'mocks' workspace folder", async function () { + assert.strictEqual(await validateCwdSetting(undefined), workspace); + }); + + it("Uses the default when given a non-existent folder", async function () { + await changeCwdSetting("/a/totally/fake/folder"); + assert.strictEqual(await validateCwdSetting(undefined), workspace); + }); + + it("Uses the given folder when it exists", async function () { + // A different than default folder that definitely exists + const cwd = path.resolve(path.join(process.cwd(), "..")); + await changeCwdSetting(cwd); + assert.strictEqual(await validateCwdSetting(undefined), cwd); + }); + + it("Uses the home folder for ~ (tilde)", async function () { + await changeCwdSetting("~"); + assert.strictEqual( + await validateCwdSetting(undefined), + os.homedir(), + ); + }); + + it("Accepts relative paths", async function () { + // A different than default folder that definitely exists and is relative + const cwd = path.join("~", "somewhere", ".."); + const expected = path.join(os.homedir(), "somewhere", ".."); + await changeCwdSetting(cwd); + assert.strictEqual(await validateCwdSetting(undefined), expected); + }); + + it("Handles relative paths", async function () { + await changeCwdSetting("./BinaryModule"); + const expected = path.join(workspace, "./BinaryModule"); + assert.strictEqual(await validateCwdSetting(undefined), expected); + }); + }); +}); diff --git a/test/features/DebugSession.test.ts b/test/features/DebugSession.test.ts new file mode 100644 index 0000000000..986fbd45f7 --- /dev/null +++ b/test/features/DebugSession.test.ts @@ -0,0 +1,817 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import structuredClone from "@ungap/structured-clone"; //Polyfill for structuredClone which will be present in Node 17. +import * as assert from "assert"; +import Sinon from "sinon"; +import { + DebugAdapterNamedPipeServer, + type DebugConfiguration, + type DebugSession, + type Extension, + type ExtensionContext, + Range, + SourceBreakpoint, + type TextDocument, + type TextEditor, + Uri, + commands, + debug, + extensions, + window, + workspace, +} from "vscode"; +import { Disposable } from "vscode-languageserver-protocol"; +import { + DebugConfig, + DebugConfigurations, + DebugSessionFeature, +} from "../../src/features/DebugSession"; +import type { IPowerShellExtensionClient } from "../../src/features/ExternalApi"; +import type { IPlatformDetails } from "../../src/platform"; +import * as platform from "../../src/platform"; +import { + type IEditorServicesSessionDetails, + type IPowerShellVersionDetails, + SessionManager, +} from "../../src/session"; +import * as utils from "../../src/utils"; +import { + BuildBinaryModuleMock, + WaitEvent, + ensureEditorServicesIsConnected, + stubInterface, + testLogger, +} from "../utils"; + +const TEST_NUMBER = 7357; // 7357 = TEST. Get it? :) + +let defaultDebugConfig: DebugConfiguration; +beforeEach(() => { + // This prevents state from creeping into the template between test runs + defaultDebugConfig = structuredClone( + DebugConfigurations[DebugConfig.LaunchCurrentFile], + ); +}); + +describe("DebugSessionFeature", () => { + // These constructor stubs are required for all tests so we don't interfere with the E2E vscode instance + let registerProviderStub: Sinon.SinonStub; + let registerFactoryStub: Sinon.SinonStub; + + /** + * Convenience function for creating a DebugSessionFeature with stubbed dependencies. We want the actual methods and Sinon.stubInstance is awkward because it stubs all methods and the constructor, and we just want to stub the constructor basically. + */ + function createDebugSessionFeatureStub({ + context = stubInterface({ + subscriptions: Array(), //Needed for constructor + }), + sessionManager = Sinon.createStubInstance(SessionManager), + logger = testLogger, + }): DebugSessionFeature { + return new DebugSessionFeature(context, sessionManager, logger); + } + + /** Representation of an untitled powershell document window in the Editor */ + const untitledEditor = stubInterface({ + document: stubInterface({ + uri: Uri.parse("file:///fakeUntitled.ps1"), + languageId: "powershell", + isUntitled: true, + }), + }); + + beforeEach(() => { + // Because we recreate DebugSessionFeature constantly, we need to avoid registering the same commands over and over. + Sinon.stub(commands, "registerCommand").returns( + Disposable.create(() => { + "Stubbed"; + }), + ); + registerProviderStub = Sinon.stub( + debug, + "registerDebugConfigurationProvider", + ).returns( + Disposable.create(() => { + "Stubbed"; + }), + ); + registerFactoryStub = Sinon.stub( + debug, + "registerDebugAdapterDescriptorFactory", + ).returns( + Disposable.create(() => { + "Stubbed"; + }), + ); + }); + + afterEach(() => { + Sinon.restore(); + }); + + describe("Constructor", () => { + it("Registers debug configuration provider and factory", () => { + const context = stubInterface({ + subscriptions: Array(), + }); + + createDebugSessionFeatureStub({ context: context }); + assert.ok( + registerFactoryStub.calledOnce, + "Debug adapter factory method called", + ); + assert.ok( + registerProviderStub.calledTwice, + "Debug config provider registered for both Initial and Dynamic", + ); + assert.equal( + context.subscriptions.length, + 4, + "DebugSessionFeature disposables populated", + ); + // TODO: Validate the registration content, such as the language name + }); + }); + + describe("resolveDebugConfiguration", () => { + it("Defaults to LaunchCurrentFile if no request type was specified", async () => { + const noRequestConfig: DebugConfiguration = defaultDebugConfig; + noRequestConfig.request = ""; + // Need to have an editor window "open" for this not to error out + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfiguration(undefined, noRequestConfig); + + assert.equal(actual!.current_document, true); + assert.equal( + actual!.request, + DebugConfigurations[DebugConfig.LaunchCurrentFile].request, + ); + }); + + it("Errors if current file config was specified but no file is open in the editor", async () => { + Sinon.stub(window, "activeTextEditor").value(undefined); + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfiguration(undefined, defaultDebugConfig); + + assert.equal(actual!, undefined); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /you must first open a PowerShell script file/, + ); + }); + + it("Detects an untitled document", async () => { + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfiguration(undefined, defaultDebugConfig); + + assert.equal(actual!.untitled_document, true); + assert.equal(actual!.script, "file:///fakeUntitled.ps1"); + }); + }); + + describe("resolveDebugConfigurationWithSubstitutedVariables", () => { + it("Sets internalConsoleOptions to neverOpen", async () => { + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + defaultDebugConfig, + ); + + assert.equal(actual!.internalConsoleOptions, "neverOpen"); + }); + it("Rejects invalid request type", async () => { + const invalidRequestConfig: DebugConfiguration = defaultDebugConfig; + invalidRequestConfig.request = "notAttachOrLaunch"; + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + invalidRequestConfig, + ); + + assert.equal(actual, null); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /request type was invalid/, + ); + }); + + it("Uses createTemporaryIntegratedConsole config setting if not explicitly specified", async () => { + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + assert.equal( + defaultDebugConfig.createTemporaryIntegratedConsole, + undefined, + "Default config should have no temp integrated console setting", + ); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + defaultDebugConfig, + ); + + assert.notEqual( + actual!.createTemporaryIntegratedConsole, + undefined, + "createTemporaryIntegratedConsole should have received a value from the settings and no longer be undefined", + ); + }); + + it("LaunchCurrentFile: Rejects non-Powershell language active editor", async () => { + const nonPSEditor = stubInterface({ + document: stubInterface({ + uri: Uri.parse("file:///fakeUntitled.ps1"), + languageId: "NotPowerShell", + isUntitled: true, + }), + }); + const currentDocConfig: DebugConfiguration = defaultDebugConfig; + currentDocConfig.current_document = true; + Sinon.stub(window, "activeTextEditor").value(nonPSEditor); + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + currentDocConfig, + ); + + assert.equal(actual, undefined, "Debug session should end"); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /debugging this language mode/, + ); + }); + + // Skipped until we can fix the stub + it.skip("LaunchScript: Rejects scripts without a powershell script extension", async () => { + const currentDocConfig: DebugConfiguration = defaultDebugConfig; + currentDocConfig.current_document = true; + currentDocConfig.script = "file:///notPowerShell.txt"; + // This check is currently dependent on the languageID check which is why this is needed still + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + Sinon.stub(utils, "checkIfFileExists").resolves(true); + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + currentDocConfig, + ); + + assert.equal(actual, undefined); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /debugging this file type/, + ); + Sinon.restore(); + }); + + it("Prevents debugging untitled files in a temp console", async () => { + const currentDocConfig: DebugConfiguration = defaultDebugConfig; + currentDocConfig.untitled_document = true; + currentDocConfig.createTemporaryIntegratedConsole = true; + Sinon.stub(window, "activeTextEditor").value(untitledEditor); + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + currentDocConfig, + ); + + assert.equal(actual, undefined); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /debugging untitled/, + ); + }); + + it("Attach: Exits if session version details cannot be retrieved", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + const logger = Sinon.stub(testLogger); + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + sessionManager.getPowerShellVersionDetails.returns(undefined); + + const actual = await createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual, undefined); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /session version details were not found/, + ); + assert.ok(sessionManager.getPowerShellVersionDetails.calledOnce); + }); + + // Skipped until we can fix the stub + it.skip("Attach: Prevents attach on non-windows if not PS7.0 or higher", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + const logger = Sinon.stub(testLogger); + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + Sinon.stub(platform, "getPlatformDetails").returns( + stubInterface({ + operatingSystem: platform.OperatingSystem.MacOS, + }), + ); + sessionManager.getPowerShellVersionDetails.returns( + stubInterface({ + version: "6.2.3", + }), + ); + + const actual = await createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual, undefined); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /requires PowerShell 7/, + ); + assert.ok(sessionManager.getPowerShellVersionDetails.calledOnce); + }); + + it("Attach: Prompts for PS Process if not specified", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + // This effectively skips this check + attachConfig.runspaceId = TEST_NUMBER; + attachConfig.runspaceName = "TEST"; + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + sessionManager.getPowerShellVersionDetails.returns( + stubInterface({ + version: "7.2.3", + }), + ); + const debugSessionFeatureStub = createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }); + + const pickPSHostProcessStub = Sinon.stub( + debugSessionFeatureStub, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "pickPSHostProcess" as any, + ).resolves(7357); + + const actual = + await debugSessionFeatureStub.resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual!.processId, TEST_NUMBER); + assert.ok(pickPSHostProcessStub.calledOnce); + }); + + it("Attach: Exits if process was not selected from the picker", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + // This effectively skips this check + attachConfig.runspaceId = TEST_NUMBER; + attachConfig.runspaceName = "TEST"; + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + sessionManager.getPowerShellVersionDetails.returns( + stubInterface({ + version: "7.2.3", + }), + ); + const debugSessionFeatureStub = createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }); + + const pickPSHostProcessStub = Sinon.stub( + debugSessionFeatureStub, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "pickPSHostProcess" as any, + ).resolves(undefined); + + const actual = + await debugSessionFeatureStub.resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual, undefined); + assert.ok(pickPSHostProcessStub.calledOnce); + }); + + it("Attach: Prompts for Runspace if not specified", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + // This effectively skips this check + attachConfig.processId = TEST_NUMBER; + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + sessionManager.getPowerShellVersionDetails.returns( + stubInterface({ + version: "7.2.3", + }), + ); + const debugSessionFeatureStub = createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }); + + const pickRunspaceStub = Sinon.stub( + debugSessionFeatureStub, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "pickRunspace" as any, + ).resolves(TEST_NUMBER); + + const actual = + await debugSessionFeatureStub.resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual!.runspaceId, TEST_NUMBER); + assert.ok(pickRunspaceStub.calledOnceWith(TEST_NUMBER)); + }); + + it("Attach: Exits if runspace was not selected from the picker", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.request = "attach"; + // This effectively skips this check + attachConfig.processId = TEST_NUMBER; + const sessionManager = Sinon.createStubInstance(SessionManager, {}); + sessionManager.getPowerShellVersionDetails.returns( + stubInterface({ + version: "7.2.3", + }), + ); + const debugSessionFeatureStub = createDebugSessionFeatureStub({ + sessionManager: sessionManager, + }); + + const pickRunspaceStub = Sinon.stub( + debugSessionFeatureStub, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "pickRunspace" as any, + ).resolves(undefined); + + const actual = + await debugSessionFeatureStub.resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + assert.equal(actual, undefined); + assert.ok(pickRunspaceStub.calledOnceWith(TEST_NUMBER)); + }); + + it("Starts dotnet attach debug session with default config", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.script = "test.ps1"; // This bypasses the ${file} logic + attachConfig.createTemporaryIntegratedConsole = true; + attachConfig.attachDotnetDebugger = true; + Sinon.stub(extensions, "getExtension").returns( + stubInterface>(), + ); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + const dotnetAttachConfig = actual!.dotnetAttachConfig; + assert.equal( + dotnetAttachConfig.name, + "Dotnet Debugger: Temporary Extension Terminal", + ); + assert.equal(dotnetAttachConfig.request, "attach"); + assert.equal(dotnetAttachConfig.type, "coreclr"); + assert.equal(dotnetAttachConfig.processId, undefined); + assert.equal(dotnetAttachConfig.logging.moduleLoad, false); + }); + + it("Prevents dotnet attach session if terminal is not temporary", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.script = "test.ps1"; // This bypasses the ${file} logic + attachConfig.attachDotnetDebugger = true; + const logger = Sinon.stub(testLogger); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual!, null); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /dotnet debugging without using a temporary console/, + ); + }); + + it("Errors if dotnetDebuggerConfigName was provided but the config was not found", async () => { + const attachConfig: DebugConfiguration = defaultDebugConfig; + attachConfig.script = "test.ps1"; // This bypasses the ${file} logic + attachConfig.createTemporaryIntegratedConsole = true; + attachConfig.attachDotnetDebugger = true; + attachConfig.dotnetDebuggerConfigName = "not a real config"; + const logger = Sinon.stub(testLogger); + Sinon.stub(extensions, "getExtension").returns( + stubInterface>(), + ); + + const actual = await createDebugSessionFeatureStub( + {}, + ).resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + assert.equal(actual!, null); + assert.match( + logger.writeAndShowError.firstCall.args[0], + /matching launch config was not found/, + ); + }); + + it("Finds the correct dotnetDebuggerConfigName", async () => { + const foundDotnetConfig: DebugConfiguration = { + name: "TestDotnetAttachConfig", + request: "attach", + type: "coreclr", + }; + const candidateDotnetConfigs: DebugConfiguration[] = [ + { + name: "BadCandidate1", + type: "powershell", + request: "attach", + }, + { + name: "BadCandidate2", + type: "coreclr", + request: "attach", + }, + { + // This one has launch instead of attach and even tho it has same name, should not be matched + name: foundDotnetConfig.name, + type: "coreclr", + request: "launch", + }, + foundDotnetConfig, //This is the one we want to match + { + name: foundDotnetConfig.name, + type: "notcoreclrExactly", + request: "attach", + }, + { + name: `${foundDotnetConfig.name}notexactlythisname`, + type: "coreclr", + request: "attach", + }, + ]; + const attachConfig = defaultDebugConfig; + attachConfig.script = "test.ps1"; // This bypasses the ${file} logic + attachConfig.createTemporaryIntegratedConsole = true; + attachConfig.attachDotnetDebugger = true; + attachConfig.dotnetDebuggerConfigName = foundDotnetConfig.name; + const debugSessionFeature = createDebugSessionFeatureStub({}); + + Sinon.stub( + debugSessionFeature, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "getLaunchConfigurations" as any, + ).returns(candidateDotnetConfigs); + + const config = + await debugSessionFeature.resolveDebugConfigurationWithSubstitutedVariables( + undefined, + attachConfig, + ); + + // This config will only be present if the C# extension is installed. + if (extensions.getExtension("ms-dotnettools.csharp")) { + assert.ok(config); + assert.deepStrictEqual( + config.dotnetAttachConfig, + foundDotnetConfig, + ); + } else { + assert.ok(!config); + } + }); + }); + + describe("createDebugAdapterDescriptor", () => { + it("Creates a named pipe server for the debug adapter", async () => { + const debugSessionFeature = createDebugSessionFeatureStub({ + sessionManager: Sinon.createStubInstance(SessionManager, { + getSessionDetails: + stubInterface({ + debugServicePipeName: "testPipeName", + }), + }), + }); + const debugSession = stubInterface({ + configuration: stubInterface({ + createTemporaryIntegratedConsole: false, + }), + }); + + const debugAdapterDescriptor = + await debugSessionFeature.createDebugAdapterDescriptor( + debugSession, + undefined, + ); + + // Confirm debugAdapterDescriptor is of type debugadapternamedpipeserver + assert.ok( + debugAdapterDescriptor instanceof DebugAdapterNamedPipeServer, + ); + assert.equal(debugAdapterDescriptor.path, "testPipeName"); + }); + }); +}); + +describe("DebugSessionFeature E2E", function () { + before(async () => { + // Registers and warms up the debug adapter and the PowerShell Extension Terminal + await ensureEditorServicesIsConnected(); + }); + + it("Starts and stops a debugging session", async () => { + // Inspect the debug session via the started events to ensure it is correct + const startDebugSession = new Promise((resolve) => { + const event = debug.onDidStartDebugSession((session) => { + resolve(session); + event.dispose(); + }); + }); + const stopDebugSession = new Promise((resolve) => { + const event = debug.onDidTerminateDebugSession((session) => { + resolve(session); + event.dispose(); + }); + }); + + const config = DebugConfigurations[DebugConfig.InteractiveSession]; + assert.ok( + await debug.startDebugging(undefined, config), + "Debug session should start", + ); + assert.equal( + (await startDebugSession).name, + config.name, + "Debug session name should match when started", + ); + + await debug.stopDebugging(await startDebugSession); + assert.ok(await stopDebugSession, "Debug session should stop"); + assert.equal( + (await stopDebugSession).name, + config.name, + "Debug session name should match when stopped", + ); + assert.equal( + (await stopDebugSession).configuration.internalConsoleOptions, + "neverOpen", + "Debug session should always have neverOpen internalConsoleOptions", + ); + }); + + describe("Binary Modules", () => { + let binaryModulePath: Uri; + + before(async function binarySetup() { + if (!extensions.getExtension("ms-dotnettools.csharp")) { + // These tests require that extension to be installed in the test environment. + this.skip(); + } + binaryModulePath = Uri.joinPath( + workspace.workspaceFolders![0].uri, + "BinaryModule", + ); + BuildBinaryModuleMock(); + await ensureEditorServicesIsConnected(); + }); + + afterEach(async () => { + // Cleanup E2E testing state + await debug.stopDebugging(undefined); + // Close all editors + await commands.executeCommand("workbench.action.closeAllEditors"); + }); + + it("Debugs a binary module script", async () => { + const launchScriptConfig = structuredClone( + DebugConfigurations[DebugConfig.LaunchScript], + ); + launchScriptConfig.script = Uri.joinPath( + binaryModulePath, + "BinaryModuleTest.ps1", + ).fsPath; + launchScriptConfig.attachDotnetDebugger = true; + launchScriptConfig.createTemporaryIntegratedConsole = true; + const startDebugging = Sinon.spy(debug, "startDebugging"); + + const debugStarted = await debug.startDebugging( + undefined, + launchScriptConfig, + ); + assert.ok(debugStarted); + + await debug.stopDebugging(undefined); + + assert.ok(startDebugging.calledTwice); + assert.ok(startDebugging.calledWith(undefined, launchScriptConfig)); + // The C# child process + assert.ok( + startDebugging.calledWithMatch( + undefined, + Sinon.match.has("type", "coreclr"), // The new child debugger + Sinon.match.has("type", "PowerShell"), // The parent session + ), + "The C# debugger child process is created with the PowerShell debugger as the parent", + ); + }); + + it("Stops at a binary module breakpoint", async () => { + const launchScriptConfig = structuredClone( + DebugConfigurations[DebugConfig.LaunchCurrentFile], + ); + launchScriptConfig.attachDotnetDebugger = true; + launchScriptConfig.createTemporaryIntegratedConsole = true; + const testScriptPath = Uri.joinPath( + binaryModulePath, + "BinaryModuleTest.ps1", + ); + const cmdletSourcePath = Uri.joinPath( + binaryModulePath, + "TestSampleCmdletCommand.cs", + ); + const testScriptDocument = + await workspace.openTextDocument(testScriptPath); + await window.showTextDocument(testScriptDocument); + + // We cant see when a breakpoint is hit because the code we would spy on is in the C# extension or is vscode private, but we can see if the debug session changes which should only happen when the debug session context switches to C#, so that's good enough. + + //We wire this up before starting the debug session so the event is registered + const dotnetDebugSessionActive = WaitEvent( + debug.onDidChangeActiveDebugSession, + (session) => { + return !!session?.name.match(/Dotnet Debugger/); + }, + ); + + // Break at beginProcessing of the cmdlet + debug.addBreakpoints([ + new SourceBreakpoint( + { + uri: cmdletSourcePath, + range: new Range(26, 0, 26, 0), //BeginProcessing + }, + true, + undefined, + undefined, + "TEST-BinaryModuleBreakpoint", + ), + ]); + + const debugStarted = await debug.startDebugging( + undefined, + launchScriptConfig, + ); + console.log(debug.breakpoints); + const dotnetDebugSession = await dotnetDebugSessionActive; + console.log(debug.activeDebugSession); + console.log(debug.breakpoints); + + await debug.stopDebugging(undefined); + + assert.ok(debugStarted); + assert.ok(dotnetDebugSession); + }); + }); +}); diff --git a/test/features/ExternalApi.test.ts b/test/features/ExternalApi.test.ts new file mode 100644 index 0000000000..d0b3e56641 --- /dev/null +++ b/test/features/ExternalApi.test.ts @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as assert from "assert"; +import type { + IExternalPowerShellDetails, + IPowerShellExtensionClient, +} from "../../src/features/ExternalApi"; +import utils = require("../utils"); + +describe("ExternalApi feature", function () { + describe("External extension registration", function () { + let extension: IPowerShellExtensionClient; + before(async function () { + extension = await utils.ensureExtensionIsActivated(); + }); + + it("Registers and unregisters an extension", function () { + const sessionId: string = extension.registerExternalExtension( + utils.extensionId, + ); + assert.notStrictEqual(sessionId, ""); + assert.notStrictEqual(sessionId, null); + assert.strictEqual( + extension.unregisterExternalExtension(sessionId), + true, + ); + }); + + it("Registers and unregisters an extension with a version", function () { + const sessionId: string = extension.registerExternalExtension( + utils.extensionId, + "v2", + ); + assert.notStrictEqual(sessionId, ""); + assert.notStrictEqual(sessionId, null); + assert.strictEqual( + extension.unregisterExternalExtension(sessionId), + true, + ); + }); + + it("Rejects if not registered", async function () { + await assert.rejects( + async () => await extension.getPowerShellVersionDetails(""), + ); + }); + + it("Throws if attempting to register an extension more than once", function () { + const sessionId: string = extension.registerExternalExtension( + utils.extensionId, + ); + try { + assert.throws( + () => + extension.registerExternalExtension(utils.extensionId), + { + message: `The extension '${utils.extensionId}' is already registered.`, + }, + ); + } finally { + extension.unregisterExternalExtension(sessionId); + } + }); + + it("Throws when unregistering an extension that isn't registered", function () { + assert.throws( + () => extension.unregisterExternalExtension("not-real"), + { + message: + "No extension registered with session UUID: not-real", + }, + ); + }); + }); + + describe("PowerShell version details", () => { + let sessionId: string; + let extension: IPowerShellExtensionClient; + + before(async function () { + extension = await utils.ensureExtensionIsActivated(); + sessionId = extension.registerExternalExtension(utils.extensionId); + }); + + after(function () { + extension.unregisterExternalExtension(sessionId); + }); + + it("Gets non-empty version details from the PowerShell Editor Services", async function () { + const versionDetails: IExternalPowerShellDetails = + await extension.getPowerShellVersionDetails(sessionId); + + assert.notStrictEqual(versionDetails.architecture, ""); + assert.notStrictEqual(versionDetails.architecture, null); + + assert.notStrictEqual(versionDetails.displayName, ""); + assert.notStrictEqual(versionDetails.displayName, null); + + assert.notStrictEqual(versionDetails.exePath, ""); + assert.notStrictEqual(versionDetails.exePath, null); + + assert.notStrictEqual(versionDetails.version, ""); + assert.notStrictEqual(versionDetails.version, null); + }); + }); +}); diff --git a/test/features/ISECompatibility.test.ts b/test/features/ISECompatibility.test.ts new file mode 100644 index 0000000000..19a768c56a --- /dev/null +++ b/test/features/ISECompatibility.test.ts @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as assert from "assert"; +import * as vscode from "vscode"; +import { ISECompatibilityFeature } from "../../src/features/ISECompatibility"; +import utils = require("../utils"); + +describe("ISE compatibility feature", function () { + let currentTheme: string | undefined; + + async function enableISEMode(): Promise { + await vscode.commands.executeCommand("PowerShell.EnableISEMode"); + } + async function disableISEMode(): Promise { + await vscode.commands.executeCommand("PowerShell.DisableISEMode"); + } + async function toggleISEMode(): Promise { + await vscode.commands.executeCommand("PowerShell.ToggleISEMode"); + } + + before(async function () { + // Save user's current theme. + currentTheme = await vscode.workspace + .getConfiguration("workbench") + .get("colorTheme"); + await utils.ensureEditorServicesIsConnected(); + }); + + after(async function () { + // Reset user's current theme. + await vscode.workspace + .getConfiguration("workbench") + .update("colorTheme", currentTheme, true); + assert.strictEqual( + vscode.workspace.getConfiguration("workbench").get("colorTheme"), + currentTheme, + ); + }); + + describe("Enable ISE Mode updates expected settings", function () { + before(enableISEMode); + after(disableISEMode); + for (const iseSetting of ISECompatibilityFeature.settings) { + it(`Sets ${iseSetting.name} correctly`, function () { + const currently = vscode.workspace + .getConfiguration(iseSetting.path) + .get(iseSetting.name); + assert.strictEqual(currently, iseSetting.value); + }); + } + }); + + describe("Disable ISE Mode reverts expected settings", function () { + before(enableISEMode); + before(disableISEMode); + after(disableISEMode); + for (const iseSetting of ISECompatibilityFeature.settings) { + it(`Reverts ${iseSetting.name} correctly`, function () { + const currently = vscode.workspace + .getConfiguration(iseSetting.path) + .get(iseSetting.name); + assert.notStrictEqual(currently, iseSetting.value); + }); + } + }); + + describe("Toggle switches from enabled to disabled", function () { + before(enableISEMode); + before(toggleISEMode); + after(disableISEMode); + for (const iseSetting of ISECompatibilityFeature.settings) { + it(`Reverts ${iseSetting.name} correctly`, function () { + const currently = vscode.workspace + .getConfiguration(iseSetting.path) + .get(iseSetting.name); + assert.notStrictEqual(currently, iseSetting.value); + }); + } + }); + + describe("Toggle switches from disabled to enabled", function () { + before(disableISEMode); + before(toggleISEMode); + after(disableISEMode); + for (const iseSetting of ISECompatibilityFeature.settings) { + it(`Sets ${iseSetting.name} correctly`, function () { + const currently = vscode.workspace + .getConfiguration(iseSetting.path) + .get(iseSetting.name); + assert.strictEqual(currently, iseSetting.value); + }); + } + }); + + describe("Color theme interactions", function () { + beforeEach(enableISEMode); + + function assertISESettings(): void { + for (const iseSetting of ISECompatibilityFeature.settings) { + const currently = vscode.workspace + .getConfiguration(iseSetting.path) + .get(iseSetting.name); + assert.notStrictEqual(currently, iseSetting.value); + } + } + + it("Changes the theme back from PowerShell ISE", async function () { + // Change state to something that DisableISEMode will change + await vscode.workspace + .getConfiguration("workbench") + .update("colorTheme", "PowerShell ISE", true); + assert.strictEqual( + vscode.workspace + .getConfiguration("workbench") + .get("colorTheme"), + "PowerShell ISE", + ); + await disableISEMode(); + assertISESettings(); + }); + + it("Doesn't change theme if it was manually changed", async function () { + assert.strictEqual( + vscode.workspace + .getConfiguration("workbench") + .get("colorTheme"), + "PowerShell ISE", + ); + // "Manually" change theme after enabling ISE mode. Use a built-in theme but not the default. + await vscode.workspace + .getConfiguration("workbench") + .update("colorTheme", "Monokai", true); + assert.strictEqual( + vscode.workspace + .getConfiguration("workbench") + .get("colorTheme"), + "Monokai", + ); + await disableISEMode(); + assertISESettings(); + assert.strictEqual( + vscode.workspace + .getConfiguration("workbench") + .get("colorTheme"), + "Monokai", + ); + }); + }); +}); diff --git a/test/features/UpdatePowerShell.test.ts b/test/features/UpdatePowerShell.test.ts new file mode 100644 index 0000000000..ef5049b43e --- /dev/null +++ b/test/features/UpdatePowerShell.test.ts @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import assert from "assert"; +import { UpdatePowerShell } from "../../src/features/UpdatePowerShell"; +import type { IPowerShellVersionDetails } from "../../src/session"; +import { Settings } from "../../src/settings"; +import { testLogger } from "../utils"; + +describe("UpdatePowerShell feature", function () { + let currentUpdateSetting: string | undefined; + const settings = new Settings(); + + before(function () { + currentUpdateSetting = process.env.POWERSHELL_UPDATECHECK; + }); + + beforeEach(function () { + settings.promptToUpdatePowerShell = true; + process.env.POWERSHELL_UPDATECHECK = "Default"; + }); + + after(function () { + process.env.POWERSHELL_UPDATECHECK = currentUpdateSetting; + }); + + describe("When it should check for an update", function () { + it("Won't check if 'promptToUpdatePowerShell' is false", function () { + settings.promptToUpdatePowerShell = false; + const version: IPowerShellVersionDetails = { + version: "7.3.0", + edition: "Core", + commit: "7.3.0", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(!updater.shouldCheckForUpdate()); + }); + + it("Won't check for Windows PowerShell", function () { + const version: IPowerShellVersionDetails = { + version: "5.1.22621", + edition: "Desktop", + commit: "5.1.22621", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(!updater.shouldCheckForUpdate()); + }); + + it("Won't check for a development build of PowerShell", function () { + const version: IPowerShellVersionDetails = { + version: "7.3.0-preview.3", + edition: "Core", + commit: "7.3.0-preview.3-508-g07175ae0ff8eb7306fe0b0fc7d19bdef4fbf2d67", + architecture: "Arm64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(!updater.shouldCheckForUpdate()); + }); + + it("Won't check for a daily build of PowerShell", function () { + const version: IPowerShellVersionDetails = { + version: "7.3.0-daily20221206.1", + edition: "Core", + commit: "7.3.0-daily20221206.1", + architecture: "Arm64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(!updater.shouldCheckForUpdate()); + }); + + it("Won't check if POWERSHELL_UPDATECHECK is 'Off'", function () { + process.env.POWERSHELL_UPDATECHECK = "Off"; + const version: IPowerShellVersionDetails = { + version: "7.3.0", + edition: "Core", + commit: "7.3.0", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(!updater.shouldCheckForUpdate()); + }); + + it("Should otherwise check to update PowerShell", function () { + const version: IPowerShellVersionDetails = { + version: "7.3.0", + edition: "Core", + commit: "7.3.0", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + assert(updater.shouldCheckForUpdate()); + }); + }); + + describe("Which version it gets", function () { + it("Would update to LTS", async function () { + process.env.POWERSHELL_UPDATECHECK = "LTS"; + const version: IPowerShellVersionDetails = { + version: "7.2.0", + edition: "Core", + commit: "7.2.0", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + const tag: string = (await updater.maybeGetNewRelease()) ?? ""; + // NOTE: This will need to be updated each time an LTS is released. + // Also sometimes the prior LTS is more recently updated than the latest LTS. + assert(tag.startsWith("v7.4")); + }); + + it("Would update to stable", async function () { + const version: IPowerShellVersionDetails = { + version: "7.3.0", + edition: "Core", + commit: "7.3.0", + architecture: "X64", + }; + const updater = new UpdatePowerShell(settings, testLogger, version); + // @ts-expect-error method is private. + const tag: string | undefined = await updater.maybeGetNewRelease(); + // NOTE: This will need to be updated each new major stable. + // TODO: Upstream bug causes LTS releases to update the stable info. + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + assert(tag?.startsWith("v7.5") || tag?.startsWith("v7.4")); + }); + }); +}); diff --git a/test/mocks/BinaryModule/BinaryModule.csproj b/test/mocks/BinaryModule/BinaryModule.csproj new file mode 100644 index 0000000000..5f9e3d340d --- /dev/null +++ b/test/mocks/BinaryModule/BinaryModule.csproj @@ -0,0 +1,12 @@ + + + netstandard2.0 + BinaryModule + + + + + All + + + diff --git a/test/mocks/BinaryModule/BinaryModuleTest.ps1 b/test/mocks/BinaryModule/BinaryModuleTest.ps1 new file mode 100644 index 0000000000..8954566517 --- /dev/null +++ b/test/mocks/BinaryModule/BinaryModuleTest.ps1 @@ -0,0 +1,2 @@ +Import-Module $PSScriptRoot\bin\Debug\netstandard2.0\BinaryModule.dll +Test-SampleCmdlet diff --git a/test/mocks/BinaryModule/TestSampleCmdletCommand.cs b/test/mocks/BinaryModule/TestSampleCmdletCommand.cs new file mode 100644 index 0000000000..039f6c1e6c --- /dev/null +++ b/test/mocks/BinaryModule/TestSampleCmdletCommand.cs @@ -0,0 +1,49 @@ +using System.Management.Automation; + +namespace BinaryModule +{ + [Cmdlet(VerbsDiagnostic.Test, "SampleCmdlet")] + [OutputType(typeof(FavoriteStuff))] + public class TestSampleCmdletCommand : PSCmdlet + { + [Parameter( + Position = 0, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + public int FavoriteNumber { get; set; } = 42; + + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true)] + [ValidateSet("Cat", "Dog", "Horse")] + public string FavoritePet { get; set; } = "Dog"; + + // This method gets called once for each cmdlet in the pipeline when the pipeline starts executing + protected override void BeginProcessing() + { + WriteVerbose("Begin!"); + } + + // This method will be called for each input received from the pipeline to this cmdlet; if no input is received, this method is not called + protected override void ProcessRecord() + { + WriteObject(new FavoriteStuff + { + FavoriteNumber = FavoriteNumber, + FavoritePet = FavoritePet + }); + } + + // This method will be called once at the end of pipeline execution; if no input is received, this method is not called + protected override void EndProcessing() + { + WriteVerbose("End!"); + } + } + + public class FavoriteStuff + { + public int FavoriteNumber { get; set; } + public string FavoritePet { get; set; } + } +} diff --git a/test/mocks/BinaryModule/nuget.config b/test/mocks/BinaryModule/nuget.config new file mode 100644 index 0000000000..f003b0fbd5 --- /dev/null +++ b/test/mocks/BinaryModule/nuget.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 0000000000..aef25f0e64 --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { execSync } from "child_process"; +import * as path from "path"; +import * as vscode from "vscode"; +import type { IPowerShellExtensionClient } from "../src/features/ExternalApi"; +import type { ILogger } from "../src/logging"; +import { sleep } from "../src/utils"; + +// This lets us test the rest of our path assumptions against the baseline of +// this test file existing at `/test/utils.js`. +import { name, publisher } from "../package.json"; +export const extensionId = `${publisher}.${name}`; + +export class TestLogger implements ILogger { + logDirectoryPath: vscode.Uri = vscode.Uri.file(""); + updateLogLevel(_logLevelName: string): void { + return; + } + write(_message: string, ..._additionalMessages: string[]): void { + return; + } + writeAndShowInformation( + _message: string, + ..._additionalMessages: string[] + ): Promise { + return Promise.resolve(); + } + writeTrace(_message: string, ..._additionalMessages: string[]): void { + return; + } + writeDebug(_message: string, ..._additionalMessages: string[]): void { + return; + } + writeWarning(_message: string, ..._additionalMessages: string[]): void { + return; + } + writeAndShowWarning( + _message: string, + ..._additionalMessages: string[] + ): Promise { + return Promise.resolve(); + } + writeError(_message: string, ..._additionalMessages: string[]): void { + return; + } + writeAndShowError( + _message: string, + ..._additionalMessages: string[] + ): Promise { + return Promise.resolve(); + } + writeAndShowErrorWithActions( + _message: string, + _actions: { + prompt: string; + action: (() => Promise) | undefined; + }[], + ): Promise { + return Promise.resolve(); + } +} + +export const testLogger = new TestLogger(); + +export async function ensureExtensionIsActivated(): Promise { + let extension = vscode.extensions.getExtension(extensionId); + while (!extension) { + // Wait for VS Code to be ready + testLogger.writeDebug(`Extension ${extensionId} not yet found...`); + await sleep(200); + extension = vscode.extensions.getExtension(extensionId); + // Wait for VS Code to be ready + await sleep(200); + } + if (!extension.isActive) { + await extension.activate(); + } + return extension.exports as IPowerShellExtensionClient; +} + +export async function ensureEditorServicesIsConnected(): Promise { + const extension = await ensureExtensionIsActivated(); + const sessionId = extension.registerExternalExtension(extensionId); + await extension.waitUntilStarted(sessionId); + extension.unregisterExternalExtension(sessionId); + return extension; +} + +/** + * This is a workaround for sinon not being able to stub interfaces. Interfaces are a TypeScript-only concept so this effectively allows us to stub interfaces by not providing the entire implementation but only what matters for the test. "What matters" is not type checked so you must be careful to stub everything you need, otherwise you should provide a default implementation instead if you do not know. + */ +export function stubInterface(object?: Partial): T { + return object ? (object as T) : ({} as T); +} + +/** Builds the sample binary module code. We need to do this because the source maps have absolute paths so they are not portable between machines, and while we could do deterministic with source maps, that's way more complicated and everywhere we build has dotnet already anyways */ +export function BuildBinaryModuleMock(): void { + const projectPath = path.resolve( + `${__dirname}/../test/mocks/BinaryModule/BinaryModule.csproj`, + ); + try { + execSync(`dotnet publish ${projectPath}`, { + encoding: "utf8", + }); + } catch (err) { + throw new Error( + `Failed to build the binary module mock. Please ensure that you have the .NET Core SDK installed: ${err}`, + ); + } +} + +/** Waits until the registered vscode event is fired and returns the trigger result of the event. + * @param event The event to wait for + * @param filter An optional filter to apply to the event TResult. The filter will continue to monitor the event firings until the filter returns true. + * @returns A promise that resolves when the specified event is fired with the TResult subject of the event. If a filter is specified, the promise will not resolve until the filter returns true. + */ +export function WaitEvent( + event: vscode.Event, + filter?: (event: TResult) => boolean | undefined, +): Promise { + return new Promise((resolve) => { + const listener = event((result: TResult) => { + if (!filter || filter(result)) { + listener.dispose(); + resolve(result); + } + }); + }); +} diff --git a/themes/theme-psise/theme.json b/themes/theme-psise/theme.json new file mode 100644 index 0000000000..fcf52d0067 --- /dev/null +++ b/themes/theme-psise/theme.json @@ -0,0 +1,189 @@ +{ + "name": "PowerShell ISE", + "semanticHighlighting": true, + "tokenColors": [ + { + "settings": { + "background": "#FFFFFF", + "foreground": "#000000" + } + }, + { + "name": "Comments", + "scope": ["comment", "punctuation.definition.comment"], + "settings": { + "fontStyle": "italic", + "foreground": "#006400" + } + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "settings": { + "fontStyle": "", + "foreground": "#006400" + } + }, + { + "name": "Comments: Documentation", + "scope": ["comment.documentation", "comment.block.documentation"], + "settings": { + "foreground": "#006400" + } + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "settings": { + "background": "#96000014" + } + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "settings": { + "background": "#96000014", + "foreground": "#660000" + } + }, + { + "name": "Operators", + "scope": "keyword.operator", + "settings": { + "foreground": "#A9A9A9" + } + }, + { + "name": "Keywords", + "scope": ["keyword", "storage"], + "settings": { + "foreground": "#00008B" + } + }, + { + "name": "Types", + "scope": ["storage.type", "support.type"], + "settings": { + "foreground": "#00008B" + } + }, + { + "name": "Language Constants", + "scope": ["constant.language", "support.constant", "variable.language"], + "settings": { + "foreground": "#008080" + } + }, + { + "name": "Keys and Properties", + "scope": [ + "property", + "variable.other.property", + "variable.other.property.powershell" + ], + "settings": { + "foreground": "#2d2e45" + } + }, + { + "name": "Variables", + "scope": [ + "variable", + "support.variable", + "punctuation.definition.variable.powershell", + "variable.other.readwrite.powershell" + ], + "settings": { + "foreground": "#FF4500" + } + }, + { + "name": "Functions", + "scope": ["entity.name.function", "support.function"], + "settings": { + "foreground": "#0000FF" + } + }, + { + "name": "Classes", + "scope": [ + "entity.name.type", + "entity.other.inherited-class", + "support.class" + ], + "settings": { + "foreground": "#7A3E9D" + } + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "settings": { + "foreground": "#660000" + } + }, + { + "name": "Sections", + "scope": "entity.name.section", + "settings": {} + }, + { + "name": "Numbers, Characters", + "scope": ["constant.numeric", "constant.character", "constant"], + "settings": { + "foreground": "#800080" + } + }, + { + "name": "Strings", + "scope": "string", + "settings": { + "foreground": "#8B0000" + } + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "settings": { + "foreground": "#8B0000" + } + }, + { + "name": "Strings: Regular Expressions", + "scope": "string.regexp", + "settings": { + "foreground": "#8B0000" + } + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "settings": { + "foreground": "#8B0000" + } + }, + { + "name": "Punctuation", + "scope": "punctuation", + "settings": { + "foreground": "#000000" + } + } + ], + "colors": { + "activityBar.background": "#E1ECF9", + "activityBar.foreground": "#A9A9A9", + "activityBarBadge.background": "#A9A9A9", + "editor.lineHighlightBackground": "#add8e6", + "editor.selectionBackground": "#94c6f7", + "settings.checkboxBorder": "#A9A9A9", + "settings.dropdownBorder": "#A9A9A9", + "settings.numberInputBorder": "#A9A9A9", + "settings.textInputBorder": "#A9A9A9", + "statusBar.background": "#999999", + "statusBar.debuggingBackground": "#FF4500", + "statusBar.noFolderBackground": "#999999", + "terminal.background": "#012456", + "terminal.foreground": "#F5F5F5" + } +} diff --git a/tools/installPSResources.ps1 b/tools/installPSResources.ps1 new file mode 100644 index 0000000000..3bb642aced --- /dev/null +++ b/tools/installPSResources.ps1 @@ -0,0 +1,24 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +param( + [ValidateSet("PSGallery", "CFS")] + [string]$PSRepository = "PSGallery" +) + +if ($PSRepository -eq "CFS" -and -not (Get-PSResourceRepository -Name CFS -ErrorAction SilentlyContinue)) { + Register-PSResourceRepository -Name CFS -Uri "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/PowerShellGalleryMirror/nuget/v3/index.json" +} + +# NOTE: Due to a bug in Install-PSResource with upstream feeds, we have to +# request an exact version. Otherwise, if a newer version is available in the +# upstream feed, it will fail to install any version at all. +Install-PSResource -Verbose -TrustRepository -RequiredResource @{ + InvokeBuild = @{ + version = "5.12.1" + repository = $PSRepository + } + platyPS = @{ + version = "0.14.2" + repository = $PSRepository + } +} diff --git a/tools/updateVersion.ps1 b/tools/updateVersion.ps1 new file mode 100644 index 0000000000..dd007486df --- /dev/null +++ b/tools/updateVersion.ps1 @@ -0,0 +1,73 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +param( + [Parameter(Mandatory)] + [semver]$Version, + + [Parameter(Mandatory)] + [string]$Changes +) + +git diff --staged --quiet --exit-code +if ($LASTEXITCODE -ne 0) { + throw "There are staged changes in the repository. Please commit or reset them before running this script." +} + +if ($Version.Major -ne $(Get-Date).Year) { + throw "Major version should be the current year!" +} + +if ($Version.PreReleaseLabel) { + if ($Version.Minor % 2 -eq 0) { + throw "Minor version must be odd for pre-release!" + } +} else { + if ($Version.Minor % 2 -ne 0) { + throw "Minor version must be even for pre-release!" + } +} + +$v = "$($Version.Major).$($Version.Minor).$($Version.Patch)" + +$Path = "package.json" +$f = Get-Content -Path $Path +# NOTE: The prefix regex match two spaces exactly to avoid matching +# nested objects in the file. +$f = $f -replace '^(? "version":\s+")(.+)(?",)$', "`${prefix}${v}`${suffix}" + +# TODO: Bring this back when the marketplace supports it. +# if ($Version.PreReleaseLabel) { +# $icon = "media/PowerShell_Preview_Icon.png" +# } else { +# $icon = "media/PowerShell_Icon.png" +# } +# $f = $f -replace '^(? "icon":\s+")(.+)(?",)$', "`${prefix}${icon}`${suffix}" + +# NOTE: This is not a "preview" extension even when the version is a pre-release. +$f | Set-Content -Path $Path +git add $Path + +[xml]$PsesProps = Get-Content ../PowerShellEditorServices/PowerShellEditorServices.Common.props +$PsesVersion = $PsesProps.Project.PropertyGroup.VersionPrefix +$PsesSuffix = $PsesProps.Project.PropertyGroup.VersionSuffix +if ($PsesSuffix) { $PsesVersion += "-$PsesSuffix" } + +$Path = "CHANGELOG.md" +$Changelog = Get-Content -Path $Path +@( + $Changelog[0..1] + "## v$Version" + "### $([datetime]::Now.ToString('dddd, MMMM dd, yyyy'))" + "" + "With PowerShell Editor Services [v$PsesVersion](https://github.com/PowerShell/PowerShellEditorServices/releases/tag/v$PsesVersion)!" + "" + $Changes + "" + "See more details at the GitHub Release for [v$Version](https://github.com/PowerShell/vscode-powershell/releases/tag/v$Version)." + "" + $Changelog[2..$Changelog.Length] +) | Set-Content -Encoding utf8NoBOM -Path $Path +git add $Path + +git commit --edit --message "v$($Version): $Changes" diff --git a/tsconfig.json b/tsconfig.json index 76a2a1bce0..33ba7e18aa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,17 @@ { - "compilerOptions": { - "module": "commonjs", - "outDir": "out", - "noLib": true, - "target": "ES5", - "sourceMap": true - }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "target": "ESNext", + "esModuleInterop": true, + "skipLibCheck": true, + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "verbatimModuleSyntax": true, + "strict": true, + "noEmit": true, + "module": "Preserve" + }, + "include": ["**/*.ts", "eslint.config.mjs", ".vscode-test.mjs"], + "exclude": ["node_modules"] +} diff --git a/typings/vscode-typings.d.ts b/typings/vscode-typings.d.ts deleted file mode 100644 index b9b54de1eb..0000000000 --- a/typings/vscode-typings.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// \ No newline at end of file diff --git a/vscode-powershell.build.ps1 b/vscode-powershell.build.ps1 new file mode 100644 index 0000000000..e86987a0b7 --- /dev/null +++ b/vscode-powershell.build.ps1 @@ -0,0 +1,117 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +param( + [ValidateSet("Debug", "Release")] + [string]$Configuration = "Debug", + [string]$EditorServicesRepoPath = $null +) + +#Requires -Modules @{ ModuleName = "InvokeBuild"; ModuleVersion = "5.0.0" } + +function Get-EditorServicesPath { + $psesRepoPath = if ($EditorServicesRepoPath) { + $EditorServicesRepoPath + } else { + "$PSScriptRoot/../PowerShellEditorServices/" + } + # NOTE: The ErrorActionPreference for both Invoke-Build and Azure DevOps + # scripts is Stop, but we want to continue and return false here. + return Resolve-Path "$psesRepoPath/PowerShellEditorServices.build.ps1" -ErrorAction SilentlyContinue +} + +#region Setup tasks + +task RestoreNode -If { !(Test-Path ./node_modules/esbuild) } { + Write-Build DarkGreen "Restoring build dependencies" + Invoke-BuildExec { & npm ci --omit=optional } +} + +task RestoreNodeOptional -If { !(Test-Path ./node_modules/eslint) } { + Write-Build DarkMagenta "Restoring build, test, and lint dependencies" + Invoke-BuildExec { & npm ci --include=optional } +} + +task RestoreEditorServices -If (Get-EditorServicesPath) { + # With VSCE --follow-symlinks support, we can now use symlinks consistently + # for both Debug and Release configurations. + if ((Get-Item ./modules -ErrorAction SilentlyContinue).LinkType -ne "SymbolicLink") { + Write-Build DarkMagenta "Creating symbolic link to PSES" + Remove-BuildItem ./modules + New-Item -ItemType SymbolicLink -Path ./modules -Target "$(Split-Path (Get-EditorServicesPath))/module" + } + + Write-Build DarkGreen "Building PSES" + Invoke-Build Build (Get-EditorServicesPath) -Configuration $Configuration +} + +#endregion +#region Clean tasks + +task Clean { + Write-Build DarkMagenta "Cleaning vscode-powershell" + Remove-BuildItem *.js, *.js.map, ./dist, ./modules, ./node_modules, ./out +} + +task CleanEditorServices -If (Get-EditorServicesPath) { + Write-Build DarkMagenta "Cleaning PSES" + Invoke-Build Clean (Get-EditorServicesPath) +} + +#endregion +#region Build tasks +task Lint RestoreNodeOptional, { + Write-Build DarkMagenta "Linting TypeScript" + Invoke-BuildExec { & npm run lint } + Write-Build DarkMagenta "Checking formatting of TypeScript, JSON, etc." + Invoke-BuildExec { & npm run format } +} + +task Build RestoreEditorServices, RestoreNode, { + Write-Build DarkGreen "Building vscode-powershell" + Assert-Build (Test-Path ./modules/PowerShellEditorServices/bin) "Extension requires PSES" + + switch ($Configuration) { + "Debug" { Invoke-BuildExec { & npm run compile } } + "Release" { Invoke-BuildExec { & npm run compile -- --minify } } + } +} + +#endregion +#region Test tasks + +task Test Lint, Build, { + Write-Build DarkMagenta "Running extension tests" + Invoke-BuildExec { & npm run test } + # Reset the state of files modified by tests + Invoke-BuildExec { git checkout test/TestEnvironment.code-workspace } +} + +task TestEditorServices -If (Get-EditorServicesPath) { + Write-Build DarkMagenta "Testing PSES" + Invoke-Build Test (Get-EditorServicesPath) +} + +#endregion +#region Package tasks + +task Package { + [semver]$version = $((Get-Content -Raw -Path package.json | ConvertFrom-Json).version) + Write-Build DarkGreen "Packaging powershell-$version.vsix" + Remove-BuildItem ./out + New-Item -ItemType Directory -Force out | Out-Null + + Assert-Build (Test-Path ./dist/extension.js) "Extension must be built!" + Assert-Build (Test-Path ./modules/PowerShellEditorServices/bin) "PowerShell Editor Services must be built under modules!" + + if ($version.Minor % 2 -ne 0) { + Write-Build DarkRed "This is a pre-release!" + Invoke-BuildExec { & npm run package -- --pre-release } + } else { + Invoke-BuildExec { & npm run package } + } +} + +#endregion + +task . Test, Package